diff --git a/.travis.yml b/.travis.yml index 44ae20d..8d5af14 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,2 +1,4 @@ ---- language: clojure +lein: lein2 +services: + - redis-server diff --git a/README.md b/README.md index 1d86ebb..9731355 100644 --- a/README.md +++ b/README.md @@ -106,7 +106,7 @@ There is a generalized protocol called Store and currently a simple memory imple It should be pretty simple to implement this Store with redis, sql, datomic or what have you. -It includes a simple Redis implementation. +It includes a simple Redis implementation based on Carmine. The stores used by the various parts are defined in an atom for each type. reset! each of them with your own implementation. @@ -120,23 +120,16 @@ The following stores are currently defined: To use the redis store add the following to your code: ```clojure -(reset! token-store (create-redis-store "tokens")) -(reset! auth-code-store (create-redis-store "auth-codes")) -(reset! client-store (create-redis-store "clients")) -(reset! user-store (create-redis-store "users")) -``` - -And wrap your handler with a redis connection middleware similar to this: - -```clojure -(defn wrap-redis-store [app] - (fn [req] - (redis/with-server - {:host "127.0.0.1" - :port 6379 - :db 14 - } - (app req)))) +(def server-conn + {:pool {} + :spec {:host "127.0.0.1" + :port 6379 + :db 14}}) + +(reset! token-store (create-redis-store "tokens" server-conn)) +(reset! auth-code-store (create-redis-store "auth-codes" server-conn)) +(reset! client-store (create-redis-store "clients" server-conn)) +(reset! user-store (create-redis-store "users" server-conn)) ``` ## Authorization OAuth Tokens diff --git a/project.clj b/project.clj index 004dab6..6db8438 100644 --- a/project.clj +++ b/project.clj @@ -13,7 +13,7 @@ :profiles {:dev { :dependencies [[ring/ring-jetty-adapter "1.1.0"] [lein-marginalia "0.7.0"] - [org.clojars.tavisrudd/redis-clojure "1.3.1"] + [com.taoensso/carmine "2.2.0"] [hiccup-bootstrap "0.1.0"]]}} :clean-non-project-classes true ) diff --git a/src/clauth/demo.clj b/src/clauth/demo.clj index 5fd61d7..1542941 100644 --- a/src/clauth/demo.clj +++ b/src/clauth/demo.clj @@ -7,7 +7,7 @@ [user :refer [user-store]] [auth-code :refer [auth-code-store]]] [clauth.store.redis - :refer [create-redis-store with-redis wrap-redis]] + :refer [create-redis-store]] [ring.adapter.jetty :refer [run-jetty]] [ring.middleware [cookies :refer [wrap-cookies]] @@ -86,10 +86,9 @@ (try (do (reset! token-store (create-redis-store "tokens")) - (reset! auth-code-store (create-redis-store "autho-codes")) + (reset! auth-code-store (create-redis-store "auth-codes")) (reset! client-store (create-redis-store "clients")) (reset! user-store (create-redis-store "users")) - (with-redis (let [client (or (first (clients)) (register-client "Clauth Demo" "http://pelle.github.com/clauth")) @@ -113,8 +112,7 @@ (wrap-params) (wrap-cookies) (wrap-session) - (wrap-redis) - (wrap-bootstrap-resources)) {:port 3000})))) + (wrap-bootstrap-resources)) {:port 3000}))) (catch java.net.ConnectException e (println "You don't have a Redis database running in the background:" diff --git a/src/clauth/store/redis.clj b/src/clauth/store/redis.clj index 936a6f3..c1e1313 100644 --- a/src/clauth/store/redis.clj +++ b/src/clauth/store/redis.clj @@ -1,56 +1,54 @@ (ns clauth.store.redis (:require [clauth.store :refer [Store]] - [redis.core :as redis])) + [taoensso.carmine :as car :refer (wcar)])) -(defn namespaced-keys - "get namespaced list of keys" - [namespace] - (redis/keys (str namespace "/*"))) - -(defn all-in-namespace - "get all items in namespace" - [namespace] - (let [ks (remove nil? (namespaced-keys namespace))] - (if (not-empty ks) (apply redis/mget ks)))) - -(defrecord RedisStore [namespace] - Store - (fetch [this t] (if-let [j (redis/get (str namespace "/" t))] - (cheshire.core/parse-string j true))) - (revoke! [this t] (redis/del (str namespace "/" t))) - (store! [this key_param item] - (do - (redis/set (str namespace "/" (key_param item)) - (cheshire.core/generate-string item)) - item)) - (entries [this] (map #(cheshire.core/parse-string % true) - (all-in-namespace namespace))) - (reset-store! [this] (redis/flushdb))) - -(defn create-redis-store - "Create a redis store" - [namespace] - (RedisStore. namespace)) - -(def redis-server +(def server1-conn (if-let [redis_url (or (get (System/getenv) "REDIS_URL") (get (System/getenv) "REDISTOGO_URL"))] (let [uri (new java.net.URI redis_url) host (.getHost uri) port (.getPort uri) password (last (clojure.string/split (.getUserInfo uri) #":"))] - {:host host - :port port - :password password}) - {:host "127.0.0.1" - :port 6379 - :db 14})) + {:pool {} + :spec {:host host + :port port + :password password}}) + {:pool {} + :spec {:host "127.0.0.1" + :port 6379 + :db 14}})) -(defmacro with-redis +(defmacro wcar* "Evaluates body in the context of a new connection to either local Redis server or server specified in REDIS_URL or REDISTOGO_URL" [& body] - `(redis/with-server redis-server ~@body)) + `(car/wcar ~'server-conn ~@body)) -(defn wrap-redis [app] - (fn [req] (with-redis (app req)))) +(defn namespaced-keys + "get namespaced list of keys" + [namespace server-conn] + (wcar* (car/keys (str namespace "/*")))) + +(defn all-in-namespace + "get all items in namespace" + [namespace server-conn] + (let [ks (remove nil? (namespaced-keys namespace server-conn))] + (if (not-empty ks) (wcar* (apply car/mget ks)) + []))) + +(defrecord RedisStore [namespace server-conn] + Store + (fetch [this t] (wcar* (car/get (str namespace "/" t)))) + (revoke! [this t] (wcar* (car/del (str namespace "/" t)))) + (store! [this key_param item] + (wcar* (car/set (str namespace "/" (key_param item)) item)) + item) + (entries [this] (all-in-namespace namespace server-conn)) + (reset-store! [this] (wcar* (car/flushdb)))) + +(defn create-redis-store + "Create a redis store" + ([namespace] + (RedisStore. namespace server1-conn)) + ([namespace server-conn] + (RedisStore. namespace server-conn))) diff --git a/test/clauth/test/store/redis.clj b/test/clauth/test/store/redis.clj index afb1955..b20e9d9 100644 --- a/test/clauth/test/store/redis.clj +++ b/test/clauth/test/store/redis.clj @@ -6,19 +6,21 @@ [token :as token] [client :as client] [user :as user]] - [redis.core :as redis])) + [taoensso.carmine :as car :refer (wcar)])) -(deftest redis-store-implementaiton - (redis/with-server - {:host "127.0.0.1" - :port 6379 - :db 15} - (let [st (base/create-redis-store "testing")] +(def server-conn + {:pool {} + :spec {:host "127.0.0.1" + :port 6379 + :db 15}}) + +(deftest redis-store-implementation + (let [st (base/create-redis-store "testing" server-conn)] (store/reset-store! st) (is (= 0 (count (store/entries st)))) (is (= [] (store/entries st))) (is (nil? (store/fetch st "item"))) - (let [item (store/store! st :key {:key "item" :hello "world"})] + (let [item (store/store! st :key {:key "item" :hello "world"})] (is (= 1 (count (store/entries st)))) (is (= item (store/fetch st "item"))) (is (= [item] (store/entries st))) @@ -27,14 +29,10 @@ (do (store/reset-store! st) (is (= 0 (count (store/entries st)))) (is (= [] (store/entries st))) - (is (nil? (store/fetch st "item")))))))) + (is (nil? (store/fetch st "item"))))))) (deftest token-store-implementation - (redis/with-server - {:host "127.0.0.1" - :port 6379 - :db 15} - (reset! token/token-store (base/create-redis-store "tokens")) + (reset! token/token-store (base/create-redis-store "tokens" server-conn)) (token/reset-token-store!) (is (= 0 (count (token/tokens))) "starts out empty") (let @@ -43,14 +41,10 @@ (do (token/store-token record) (is (= record (token/fetch-token (:token record)))) (is (= 1 (count (token/tokens))) "added one")))) - (reset! token/token-store (store/create-memory-store))) + (reset! token/token-store (store/create-memory-store)) (deftest client-store-implementation - (redis/with-server - {:host "127.0.0.1" - :port 6379 - :db 15} - (reset! client/client-store (base/create-redis-store "clients")) + (reset! client/client-store (base/create-redis-store "clients" server-conn)) (client/reset-client-store!) (is (= 0 (count (client/clients))) "starts out empty") (let [record (client/client-app)] @@ -58,14 +52,10 @@ (do (client/store-client record) (is (= record (client/fetch-client (:client-id record)))) (is (= 1 (count (client/clients))) "added one")))) - (reset! client/client-store (store/create-memory-store))) + (reset! client/client-store (store/create-memory-store)) (deftest user-store-implementation - (redis/with-server - {:host "127.0.0.1" - :port 6379 - :db 15} - (reset! user/user-store (base/create-redis-store "users")) + (reset! user/user-store (base/create-redis-store "users" server-conn)) (user/reset-user-store!) (is (= 0 (count (user/users))) "starts out empty") (let [record (user/new-user "john@example.com" "password")] @@ -73,4 +63,4 @@ (do (user/store-user record) (is (= record (user/fetch-user "john@example.com"))) (is (= 1 (count (user/users))) "added one")))) - (reset! user/user-store (store/create-memory-store))) + (reset! user/user-store (store/create-memory-store))