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 	/** The duration without access after which a session expires.
30 	*/
31 	@property Duration expirationTime() const { return m_expirationTime; }
32 	/// ditto
33 	@property void expirationTime(Duration dur) { m_expirationTime = dur; }
34 
35 	@property SessionStorageType storageType() const { return SessionStorageType.json; }
36 
37 	Session create()
38 	{
39 		auto s = createSessionInstance();
40 		m_db.hset(s.id, "__SESS", true); // set place holder to avoid create empty hash
41 		assert(m_db.exists(s.id));
42 		if (m_expirationTime != Duration.max)
43 			m_db.expire(s.id, m_expirationTime);
44 		return s;
45 	}
46 
47 	Session open(string id)
48 	{
49 		if (m_db.exists(id))
50 		{
51 			auto s = createSessionInstance(id);
52 			if (m_expirationTime != Duration.max)
53 				m_db.expire(s.id, m_expirationTime);
54 			return s;
55 		}
56 		return Session.init;
57 	}
58 
59 	void set(string id, string name, Variant value)
60 	@trusted {
61 		m_db.hset(id, name, value.get!Json.toString());
62 	}
63 
64 	Variant get(string id, string name, lazy Variant defaultVal)
65 	@trusted {
66 		auto v = m_db.hget!(Nullable!string)(id, name);
67 		return v.isNull ? defaultVal : Variant(parseJsonString(v.get));
68 	}
69 
70 	bool isKeySet(string id, string key)
71 	{
72 		return m_db.hexists(id, key);
73 	}
74 
75 	void remove(string id, string key)
76 	{
77 		m_db.hdel(id, key);
78 	}
79 
80 	void destroy(string id)
81 	{
82 		m_db.del(id);
83 	}
84 
85 	int delegate(int delegate(ref string key, ref Variant value)) iterateSession(string id)
86 	{
87 		assert(false, "Not available for RedisSessionStore");
88 	}
89 
90 	int iterateSession(string id, scope int delegate(string key) @safe del)
91 	{
92 		auto res = m_db.hkeys(id);
93 		while (!res.empty) {
94 			auto key = res.front;
95 			res.popFront();
96 			if (auto ret = del(key))
97 				return ret;
98 		}
99 		return 0;
100 	}
101 }