1 module vibe.db.redis.sessionstore; 2 3 import vibe.data.json; 4 import vibe.db.redis.redis; 5 import vibe.http.session; 6 import core.time; 7 import std.typecons : Nullable; 8 import std.variant; 9 10 11 final class RedisSessionStore : SessionStore { 12 private { 13 RedisDatabase m_db; 14 Duration m_expirationTime = Duration.max; 15 } 16 17 /** Constructs a new Redis session store. 18 19 Params: 20 host = Host name of the Redis instance to connect to 21 database = Database number to select on the server 22 port = Optional port number to use when connecting to the server 23 */ 24 this(string host, long database, ushort port = RedisClient.defaultPort) 25 { 26 m_db = connectRedis(host, port).getDatabase(database); 27 } 28 29 /** Release all connections that are not in use. Call this at the end of 30 * your program to clean up unused sockets that may be held by the GC. 31 */ 32 void releaseUnusedConnections() @safe 33 { 34 m_db.client.releaseUnusedConnections(); 35 } 36 37 /** The duration without access after which a session expires. 38 */ 39 @property Duration expirationTime() const { return m_expirationTime; } 40 /// ditto 41 @property void expirationTime(Duration dur) { m_expirationTime = dur; } 42 43 @property SessionStorageType storageType() const { return SessionStorageType.json; } 44 45 Session create() 46 { 47 auto s = createSessionInstance(); 48 m_db.hset(s.id, "__SESS", true); // set place holder to avoid create empty hash 49 assert(m_db.exists(s.id)); 50 if (m_expirationTime != Duration.max) 51 m_db.expire(s.id, m_expirationTime); 52 return s; 53 } 54 55 Session open(string id) 56 { 57 if (m_db.exists(id)) 58 { 59 auto s = createSessionInstance(id); 60 if (m_expirationTime != Duration.max) 61 m_db.expire(s.id, m_expirationTime); 62 return s; 63 } 64 return Session.init; 65 } 66 67 void set(string id, string name, Variant value) 68 @trusted { 69 m_db.hset(id, name, value.get!Json.toString()); 70 } 71 72 Variant get(string id, string name, lazy Variant defaultVal) 73 @trusted { 74 auto v = m_db.hget!(Nullable!string)(id, name); 75 return v.isNull ? defaultVal : Variant(parseJsonString(v.get)); 76 } 77 78 bool isKeySet(string id, string key) 79 { 80 return m_db.hexists(id, key); 81 } 82 83 void remove(string id, string key) 84 { 85 m_db.hdel(id, key); 86 } 87 88 void destroy(string id) 89 { 90 m_db.del(id); 91 } 92 93 int delegate(int delegate(ref string key, ref Variant value)) iterateSession(string id) 94 { 95 assert(false, "Not available for RedisSessionStore"); 96 } 97 98 int iterateSession(string id, scope int delegate(string key) @safe del) 99 { 100 auto res = m_db.hkeys(id); 101 while (!res.empty) { 102 auto key = res.front; 103 res.popFront(); 104 if (auto ret = del(key)) 105 return ret; 106 } 107 return 0; 108 } 109 }