This repository has been archived by the owner on Mar 12, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 9
/
pool.clj
82 lines (76 loc) · 3.1 KB
/
pool.clj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
(ns celtuce.pool
(:import
(java.util.function Supplier)
(io.lettuce.core RedisClient)
(io.lettuce.core.cluster RedisClusterClient)
(io.lettuce.core.codec RedisCodec)
(io.lettuce.core.api StatefulRedisConnection)
(io.lettuce.core.cluster.api StatefulRedisClusterConnection)
(io.lettuce.core.pubsub StatefulRedisPubSubConnection)
(io.lettuce.core.support ConnectionPoolSupport)
(org.apache.commons.pool2.impl GenericObjectPool GenericObjectPoolConfig)))
(defprotocol ConnectionPool
"Functions for using the connection pool"
(borrow-conn [this])
(return-conn [this conn])
(close [this]))
(defrecord ConnectionPoolImpl [^GenericObjectPool conn-pool connector cmds-fn]
ConnectionPool
(borrow-conn [_]
(.borrowObject conn-pool))
(return-conn [_ conn]
(.returnObject conn-pool conn))
(close [_]
(.close conn-pool)))
(defn ^GenericObjectPoolConfig pool-config
"Internal helper to build GenericObjectPoolConfig from a map"
[{:keys [max-total max-idle min-idle]
:or {max-total GenericObjectPoolConfig/DEFAULT_MAX_TOTAL
max-idle GenericObjectPoolConfig/DEFAULT_MAX_IDLE
min-idle GenericObjectPoolConfig/DEFAULT_MIN_IDLE}}]
(doto (GenericObjectPoolConfig.)
(.setMaxTotal max-total)
(.setMaxIdle max-idle)
(.setMinIdle min-idle)))
(defn conn-pool
"Create a ConnectionPoolImpl that wraps a ConnectionPoolSupport.
Takes a connector and a command function that will be called on pooled connections"
([connector cmds-fn]
(conn-pool connector cmds-fn {}))
([{:keys [redis-client stateful-conn codec] :as connector} cmds-fn options]
(->ConnectionPoolImpl
(ConnectionPoolSupport/createGenericObjectPool
(reify Supplier
(get [this]
(condp instance? stateful-conn
StatefulRedisConnection
(.connect ^RedisClient redis-client ^RedisCodec codec)
StatefulRedisClusterConnection
(.connect ^RedisClusterClient redis-client codec)
StatefulRedisPubSubConnection
(condp instance? redis-client
RedisClusterClient
(.connectPubSub ^RedisClusterClient redis-client codec)
RedisClient
(.connectPubSub ^RedisClient redis-client ^RedisCodec codec)))))
(pool-config options))
connector
cmds-fn)))
(defmacro with-conn-pool
"Takes a ConnectionPool `coon-pool` and a `cmds-name` symbol that will be bound to
the command function of the pool called on a borrowed connection"
[conn-pool cmds-name & body]
`(let [conn# (borrow-conn ~conn-pool)
~cmds-name ((:cmds-fn ~conn-pool)
(assoc (:connector ~conn-pool) :stateful-conn conn#))]
(try
~@body
(finally (return-conn ~conn-pool conn#)))))
(defmacro with-conn-pool*
"Like with-conn-pool but also binds the pooled connection to `conn-name`.
User is responsible for returning it to the pool within `body`"
[conn-pool cmds-name conn-name & body]
`(let [~conn-name (borrow-conn ~conn-pool)
~cmds-name ((:cmds-fn ~conn-pool)
(assoc (:connector ~conn-pool) :stateful-conn ~conn-name))]
~@body))