{"id":31943284,"url":"https://github.com/luminus-framework/jdbc-ring-session","last_synced_at":"2025-10-14T09:50:47.752Z","repository":{"id":28282745,"uuid":"31794817","full_name":"luminus-framework/jdbc-ring-session","owner":"luminus-framework","description":"JDBC Session store for Ring","archived":false,"fork":false,"pushed_at":"2024-12-10T14:00:01.000Z","size":61,"stargazers_count":30,"open_issues_count":1,"forks_count":14,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-09-30T07:45:12.847Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Clojure","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"epl-1.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/luminus-framework.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGES.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-03-07T00:06:53.000Z","updated_at":"2024-12-10T14:00:05.000Z","dependencies_parsed_at":"2022-07-24T15:47:13.045Z","dependency_job_id":null,"html_url":"https://github.com/luminus-framework/jdbc-ring-session","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/luminus-framework/jdbc-ring-session","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/luminus-framework%2Fjdbc-ring-session","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/luminus-framework%2Fjdbc-ring-session/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/luminus-framework%2Fjdbc-ring-session/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/luminus-framework%2Fjdbc-ring-session/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/luminus-framework","download_url":"https://codeload.github.com/luminus-framework/jdbc-ring-session/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/luminus-framework%2Fjdbc-ring-session/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279018554,"owners_count":26086404,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-14T02:00:06.444Z","response_time":60,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-10-14T09:50:22.979Z","updated_at":"2025-10-14T09:50:47.746Z","avatar_url":"https://github.com/luminus-framework.png","language":"Clojure","funding_links":[],"categories":[],"sub_categories":[],"readme":"# jdbc-ring-session\n\nA Clojure library for JDBC backed Ring sessions.\n\n[![Clojars Project](http://clojars.org/jdbc-ring-session/latest-version.svg)](http://clojars.org/jdbc-ring-session)\n\n## Usage\n\nUse the `jdbc-ring-session.core/jdbc-store` function to create a new store. The function accepts\na `next.jdbc` datasource definition:\n\n```clojure\n(ns db.core\n  (:require [jdbc-ring-session.core :refer [jdbc-store]]))\n\n(def db\n  {:dbtype \"postgresql\"\n   :dbname \"session\"\n   :user \"admin\"\n   :password \"admin\"})\n\n(def store (jdbc-store db))\n```\n\nThe function also accepts an existing datasource, e.g. the connection pool of your application.\n\n### database configuration\n\nThe session will be stored as a byte array serialized using [nippy](https://github.com/ptaoussanis/nippy). The table formats are shown below.\n\n\nPostgeSQL:\n\n```sql\nCREATE TABLE session_store\n(\n  session_id VARCHAR(36) NOT NULL PRIMARY KEY,\n  idle_timeout BIGINT,\n  absolute_timeout BIGINT,\n  value BYTEA\n)\n```\n\nOracle:\n\n```sql\nCREATE TABLE SESSION_STORE\n(\n  session_id VARCHAR2(100 BYTE) NOT NULL PRIMARY KEY,\n  absolute_timeout NUMBER,\n  idle_timeout NUMBER,\n  value BLOB\n)\n```\n\nMySQL:\n\n```sql\nCREATE TABLE `session_store` (\n  `session_id` VARCHAR(36) NOT NULL,\n  `idle_timeout` DOUBLE DEFAULT NULL,\n  `absolute_timeout` DOUBLE DEFAULT NULL,\n  `value` BLOB,\n  PRIMARY KEY (`session_id`)\n)\n```\n\nH2:\n\n```h2\nCREATE TABLE session_store (\n  session_id VARCHAR(36) NOT NULL,\n  idle_timeout BIGINT DEFAULT NULL,\n  absolute_timeout BIGINT DEFAULT NULL,\n  value BINARY(10000),\n  PRIMARY KEY (session_id)\n)\n```\n\nSQL Server:\n\n```sql\nCREATE TABLE session_store (\n  session_id VARCHAR(36) NOT NULL,\n  idle_timeout BIGINT DEFAULT NULL,\n  absolute_timeout BIGINT DEFAULT NULL,\n  value VARBINARY(max),\n  PRIMARY KEY (session_id)\n)\n```\n\nSQLite:\n\n```sql\nCREATE TABLE session_store\n(\n    session_id       VARCHAR NOT NULL PRIMARY KEY,\n    idle_timeout     INTEGER,\n    absolute_timeout INTEGER,\n    value            BLOB\n)\n```\n\n### session store initialization\n\nThe `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.\n\n```clojure\n(jdbc-store db {:table :sessions})\n```\n\n### custom serialization\n\nThe serializer function accepts the session map and returns the serialized value that will be inserted\nin the table, eg:\n\n```clojure\n(defn serialize-postgres [value]\n  (nippy/freeze value))\n```\n\nThe deserializer function receives the session value in the database and returns the deserialized session, eg:\n\n```clojure\n(defn deserialize-postgres [value]\n  (when value\n    (nippy/thaw value)))\n```\n\n\n### stale session cleanup\n\nA 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:\n\n```clojure\n(ns db.core\n  (:require [jdbc-ring-session.cleaner :refer [start-cleaner stop-cleaner]]))\n\n(start-cleaner db)\n\n(stop-cleaner session-cleaner)\n```\n\nThe `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.\n\n```clojure\n(start-cleaner {:interval 120})\n```\n\n## Troubleshooting\n\n### Running a database on a non standard port\n\nNote 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)):\n\n```\nDriverManager (alternative):\n    :dbtype      (required) a String, the type of the database (the jdbc subprotocol)\n    :dbname      (required) a String, the name of the database\n    :host        (optional) a String, the host name/IP of the database\n                            (defaults to 127.0.0.1)\n    :port        (optional) a Long, the port of the database\n                            (defaults to 3306 for mysql, 1433 for mssql/jtds, else nil)\n                            (others)     (optional) passed to the driver as properties.\n```\n\nAdding 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.\n\nUsing a string `subprotocol://user:password@host:post/subname`, instead of a DriverManager map will also work.\n\n## License\n\nCopyright © 2015 Yogthos\n\nDistributed under the Eclipse Public License either version 1.0 or (at\nyour option) any later version.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fluminus-framework%2Fjdbc-ring-session","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fluminus-framework%2Fjdbc-ring-session","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fluminus-framework%2Fjdbc-ring-session/lists"}