https://github.com/puppetlabs/jdbc-util
Common jdbc utilities for use in Puppet Labs clojure projects
https://github.com/puppetlabs/jdbc-util
Last synced: 3 months ago
JSON representation
Common jdbc utilities for use in Puppet Labs clojure projects
- Host: GitHub
- URL: https://github.com/puppetlabs/jdbc-util
- Owner: puppetlabs
- License: epl-1.0
- Created: 2014-04-11T20:55:57.000Z (about 11 years ago)
- Default Branch: main
- Last Pushed: 2025-02-04T02:12:21.000Z (5 months ago)
- Last Synced: 2025-03-30T03:05:48.086Z (3 months ago)
- Language: Clojure
- Size: 300 KB
- Stars: 8
- Watchers: 36
- Forks: 24
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Contributing: CONTRIBUTING.md
- License: LICENSE
- Codeowners: CODEOWNERS
Awesome Lists containing this project
README
[](https://travis-ci.org/puppetlabs/jdbc-util)
# jdbc-util
_Being a collection of common jdbc utility code we use at Puppet
Labs._## Usage
### Lazy connection pool
The pool namespace provides functions to create a hikaricp connection pool that
is lazily initialized witha user-provided init function, and which will not hand
out connections until that function has run.```clojure
(let [timeout-ms-when-starting 5000
;; Accepts most hikari options, with clojure style names.
options {:pool-name "app-pool-1"
:jdbc-url "jdbc:postgresql:the_gibson"
:username "eugene"
:password "god"}
init-fn (fn [db] (migrate-database db))
db-pool (pool/connection-pool-with-delayed-init
(pool/options->hikari-config options)
init-fn
timeout-ms-when-starting)]
;; ... wait a while, do some work ...
(jdbc/query db-pool ["SELECT * FROM garbage_files;"]))
```The database pool is wrapped in a future which loops attempting to connect to
the database. Once it connects, it runs `init-fn`, passing in the datasource in
a map as java.jdbc expects it (`{:datasource datasource}`). Once the init
function completes, the pool future is realized and it will hand out connections
transparently. If a connection is requested before the future is realized, it
will wait for the configured timeout (the third argument to
`connection-pool-with-delayed-init`) for it to become realized, and if it times
out raise a `java.sql.SQLTransientConnectionException`.#### Options
Several functions are provided to configure the pool using either a database
spec (such as java.jdbc would use) or hikari options. See the docstrings for
`pool/spec->options` and `pool/options->hikari-config`. The
`pool/connection-pool-with-delayed-init` function expects a native
`HikariConfig` object.#### Status
The pool also implements a status protocol (`pool/PoolStatus`) to check its
state and whether the initialization function was successful. The status method
will return a map representing the current pool health. Before the pool is
finished initializing the map will be:```clojure
{:state :starting}
```Once started the state becomes `:ready` or `:error`. When in an error state, an
additional `:messages` key will be present containing one or more error
messages. For example:```clojure
{:state :error
:messages ["Initialization resulted in an error: A rabbit's in the system."]}
```When the initialization function throws an exception, the pool will continue to
function normally but the status will show an error state. The exception message
will appear under `:messages`, and the full exception object can be retrieved by
calling `init-error` on the pool.The status is implemented using an io.dropwizard.metrics HealthCheckRegistry. If
one is provided to the hikari config under `:health-check-registry` it will be
used, otherwise one will be created automatically.#### Lifetime
The pool implements a lifetime protocol (`pool/PoolLifetime`) to provide methods
of determining if the initialization is complete, cancelling the initialization
if possible, or waiting on the completion of the initialization. Additionally
a new close interface `close-after-ready` waits to close the datasource until
the init routine is complete.Before the initialization is complete `init-complete?` returns false. If the
initialization routine finishes, fails or was cancelled, `init-complete?` returns
true.`cancel-init` will attempt to cancel the async initialization process and return
true if it was cancelled, or false if it wasn't. If the init routine has already
completed, `cancel-init` returns false.`close-after-ready` has two forms, one that will block forever until the init
routine completes, or one that accepts a timeout in milliseconds. If the
timeout is exceeded prior to the init completing, the routine will attempt to cancel
the init and then immediately close the connection.## Support
To file a bug, please open a Jira ticket against this project. Bugs and PRs are
addressed on a best-effort basis. Puppet Inc. does not guarantee support for
this project.## Running tests
You'll need PostgreSQL installed (9.6 is the mainly-used version for us right
now). To manually create the needed postgres resources for running tests, set up
a "jdbc_util_test" DB and user "jdbc_util_test" with password "foobar" and superuser
permissions.To give the "jdbc_util_test" and "migrator" users permission to create databases, open up a psql
session and then run:
```sql
ALTER ROLE jdbc_util_test CREATEDB CREATEROLE;Alternately, if you have a local postgres user configured super user read and write
capability, you can run the setup script at the root of this application. You will
need execute permissions for your local user on the dev-setup file in the root
directory of the application. Executing that file will do some local db cleanup
and create the needed test databases with users and permissions.Run ```./dev-setup```
## License
Copyright © 2018 Puppet, Inc.
Distributed under the [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.html)