https://github.com/luminus-framework/jdbc-ring-session
JDBC Session store for Ring
https://github.com/luminus-framework/jdbc-ring-session
Last synced: 8 months ago
JSON representation
JDBC Session store for Ring
- Host: GitHub
- URL: https://github.com/luminus-framework/jdbc-ring-session
- Owner: luminus-framework
- License: epl-1.0
- Created: 2015-03-07T00:06:53.000Z (over 11 years ago)
- Default Branch: master
- Last Pushed: 2024-12-10T14:00:01.000Z (over 1 year ago)
- Last Synced: 2025-09-30T07:45:12.847Z (9 months ago)
- Language: Clojure
- Size: 59.6 KB
- Stars: 30
- Watchers: 2
- Forks: 14
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGES.md
- License: LICENSE
Awesome Lists containing this project
README
# jdbc-ring-session
A Clojure library for JDBC backed Ring sessions.
[](http://clojars.org/jdbc-ring-session)
## Usage
Use the `jdbc-ring-session.core/jdbc-store` function to create a new store. The function accepts
a `next.jdbc` datasource definition:
```clojure
(ns db.core
(:require [jdbc-ring-session.core :refer [jdbc-store]]))
(def db
{:dbtype "postgresql"
:dbname "session"
:user "admin"
:password "admin"})
(def store (jdbc-store db))
```
The function also accepts an existing datasource, e.g. the connection pool of your application.
### database configuration
The session will be stored as a byte array serialized using [nippy](https://github.com/ptaoussanis/nippy). The table formats are shown below.
PostgeSQL:
```sql
CREATE TABLE session_store
(
session_id VARCHAR(36) NOT NULL PRIMARY KEY,
idle_timeout BIGINT,
absolute_timeout BIGINT,
value BYTEA
)
```
Oracle:
```sql
CREATE TABLE SESSION_STORE
(
session_id VARCHAR2(100 BYTE) NOT NULL PRIMARY KEY,
absolute_timeout NUMBER,
idle_timeout NUMBER,
value BLOB
)
```
MySQL:
```sql
CREATE TABLE `session_store` (
`session_id` VARCHAR(36) NOT NULL,
`idle_timeout` DOUBLE DEFAULT NULL,
`absolute_timeout` DOUBLE DEFAULT NULL,
`value` BLOB,
PRIMARY KEY (`session_id`)
)
```
H2:
```h2
CREATE TABLE session_store (
session_id VARCHAR(36) NOT NULL,
idle_timeout BIGINT DEFAULT NULL,
absolute_timeout BIGINT DEFAULT NULL,
value BINARY(10000),
PRIMARY KEY (session_id)
)
```
SQL Server:
```sql
CREATE TABLE session_store (
session_id VARCHAR(36) NOT NULL,
idle_timeout BIGINT DEFAULT NULL,
absolute_timeout BIGINT DEFAULT NULL,
value VARBINARY(max),
PRIMARY KEY (session_id)
)
```
SQLite:
```sql
CREATE TABLE session_store
(
session_id VARCHAR NOT NULL PRIMARY KEY,
idle_timeout INTEGER,
absolute_timeout INTEGER,
value BLOB
)
```
### session store initialization
The `jdbc-store` function accepts an optional map with the keys called `:table`, `:serializer` and `:deserializer`. The `:table` defaults to `:session_store`, while the `:serializer` and `:deserializer` keys are used to specify how the session data should be serialized and deserialized for the specific database. The library will attempt to figure out the appropriate serializer/deserializer based on the connection type. MySQL, PostgeSQL and Oracle BLOB formats are supported out of the box.
```clojure
(jdbc-store db {:table :sessions})
```
### custom serialization
The serializer function accepts the session map and returns the serialized value that will be inserted
in the table, eg:
```clojure
(defn serialize-postgres [value]
(nippy/freeze value))
```
The deserializer function receives the session value in the database and returns the deserialized session, eg:
```clojure
(defn deserialize-postgres [value]
(when value
(nippy/thaw value)))
```
### stale session cleanup
A cleaner thread is provided in the `ring-jdbc-session.cleaner` for removing expired sessions from the database. The `idle_timeout` and `absolute_timeout` keys are expected to be populated by the [ring-session-timeout](https://github.com/ring-clojure/ring-session-timeout) library. These keys are used by the cleaner to remove stale sessions. The cleaner can be started and stopped as follows:
```clojure
(ns db.core
(:require [jdbc-ring-session.cleaner :refer [start-cleaner stop-cleaner]]))
(start-cleaner db)
(stop-cleaner session-cleaner)
```
The `start-cleaner` function accepts an optional map with the `:interval` key that defaults to 60. This is the number of seconds to sleep between runs.
```clojure
(start-cleaner {:interval 120})
```
## Troubleshooting
### Running a database on a non standard port
Note that when running a database on a non-standard port, the jdbc datasource definition must be formatted as follows ([from jdbc source](https://github.com/clojure/java.jdbc/blob/master/src/main/clojure/clojure/java/jdbc.clj#L195)):
```
DriverManager (alternative):
:dbtype (required) a String, the type of the database (the jdbc subprotocol)
:dbname (required) a String, the name of the database
:host (optional) a String, the host name/IP of the database
(defaults to 127.0.0.1)
:port (optional) a Long, the port of the database
(defaults to 3306 for mysql, 1433 for mssql/jtds, else nil)
(others) (optional) passed to the driver as properties.
```
Adding a `:port` key to the standard DriverManager map will result in the database connection failing with a `org.postgresql.util.PSQLException: FATAL: password authentication failed for user`, and it can be difficult to trace it back to the DriverManager format.
Using a string `subprotocol://user:password@host:post/subname`, instead of a DriverManager map will also work.
## License
Copyright © 2015 Yogthos
Distributed under the Eclipse Public License either version 1.0 or (at
your option) any later version.