Skip to content

luminus-framework/jdbc-ring-session

Repository files navigation

jdbc-ring-session

A Clojure library for JDBC backed Ring sessions.

Clojars Project

Usage

Use the jdbc-ring-session.core/jdbc-store function to create a new store. The function accepts a next.jdbc datasource definition:

(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. The table formats are shown below.

PostgeSQL:

CREATE TABLE session_store
(
  session_id VARCHAR(36) NOT NULL PRIMARY KEY,
  idle_timeout BIGINT,
  absolute_timeout BIGINT,
  value BYTEA
)

Oracle:

CREATE TABLE SESSION_STORE
(
  session_id VARCHAR2(100 BYTE) NOT NULL PRIMARY KEY,
  absolute_timeout NUMBER,
  idle_timeout NUMBER,
  value BLOB
)

MySQL:

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:

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:

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:

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.

(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:

(defn serialize-postgres [value]
  (nippy/freeze value))

The deserializer function receives the session value in the database and returns the deserialized session, eg:

(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 library. These keys are used by the cleaner to remove stale sessions. The cleaner can be started and stopped as follows:

(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.

(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):

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.

About

JDBC Session store for Ring

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published