1
- require 'connection_pool'
1
+ require 'redis'
2
+ require 'concurrent-ruby'
2
3
3
4
module Gush
4
5
class Client
5
6
attr_reader :configuration
6
7
8
+ @@redis_connection = Concurrent ::ThreadLocalVar . new ( nil )
9
+
10
+ def self . redis_connection ( config )
11
+ cached = ( @@redis_connection . value ||= { url : config . redis_url , connection : nil } )
12
+ return cached [ :connection ] if !cached [ :connection ] . nil? && config . redis_url == cached [ :url ]
13
+
14
+ Redis . new ( url : config . redis_url ) . tap do |instance |
15
+ RedisClassy . redis = instance
16
+ @@redis_connection . value = { url : config . redis_url , connection : instance }
17
+ end
18
+ end
19
+
7
20
def initialize ( config = Gush . configuration )
8
21
@configuration = config
9
22
end
@@ -47,9 +60,7 @@ def next_free_job_id(workflow_id, job_klass)
47
60
48
61
loop do
49
62
job_id = SecureRandom . uuid
50
- available = connection_pool . with do |redis |
51
- !redis . hexists ( "gush.jobs.#{ workflow_id } .#{ job_klass } " , job_id )
52
- end
63
+ available = !redis . hexists ( "gush.jobs.#{ workflow_id } .#{ job_klass } " , job_id )
53
64
54
65
break if available
55
66
end
@@ -61,9 +72,7 @@ def next_free_workflow_id
61
72
id = nil
62
73
loop do
63
74
id = SecureRandom . uuid
64
- available = connection_pool . with do |redis |
65
- !redis . exists ( "gush.workflow.#{ id } " )
66
- end
75
+ available = !redis . exists ( "gush.workflow.#{ id } " )
67
76
68
77
break if available
69
78
end
@@ -72,37 +81,31 @@ def next_free_workflow_id
72
81
end
73
82
74
83
def all_workflows
75
- connection_pool . with do |redis |
76
- redis . scan_each ( match : "gush.workflows.*" ) . map do |key |
77
- id = key . sub ( "gush.workflows." , "" )
78
- find_workflow ( id )
79
- end
84
+ redis . scan_each ( match : "gush.workflows.*" ) . map do |key |
85
+ id = key . sub ( "gush.workflows." , "" )
86
+ find_workflow ( id )
80
87
end
81
88
end
82
89
83
90
def find_workflow ( id )
84
- connection_pool . with do |redis |
85
- data = redis . get ( "gush.workflows.#{ id } " )
91
+ data = redis . get ( "gush.workflows.#{ id } " )
86
92
87
- unless data . nil?
88
- hash = Gush ::JSON . decode ( data , symbolize_keys : true )
89
- keys = redis . scan_each ( match : "gush.jobs.#{ id } .*" )
93
+ unless data . nil?
94
+ hash = Gush ::JSON . decode ( data , symbolize_keys : true )
95
+ keys = redis . scan_each ( match : "gush.jobs.#{ id } .*" )
90
96
91
- nodes = keys . each_with_object ( [ ] ) do |key , array |
92
- array . concat redis . hvals ( key ) . map { |json | Gush ::JSON . decode ( json , symbolize_keys : true ) }
93
- end
94
-
95
- workflow_from_hash ( hash , nodes )
96
- else
97
- raise WorkflowNotFound . new ( "Workflow with given id doesn't exist" )
97
+ nodes = keys . each_with_object ( [ ] ) do |key , array |
98
+ array . concat redis . hvals ( key ) . map { |json | Gush ::JSON . decode ( json , symbolize_keys : true ) }
98
99
end
100
+
101
+ workflow_from_hash ( hash , nodes )
102
+ else
103
+ raise WorkflowNotFound . new ( "Workflow with given id doesn't exist" )
99
104
end
100
105
end
101
106
102
107
def persist_workflow ( workflow )
103
- connection_pool . with do |redis |
104
- redis . set ( "gush.workflows.#{ workflow . id } " , workflow . to_json )
105
- end
108
+ redis . set ( "gush.workflows.#{ workflow . id } " , workflow . to_json )
106
109
107
110
workflow . jobs . each { |job | persist_job ( workflow . id , job ) }
108
111
workflow . mark_as_persisted
@@ -111,9 +114,7 @@ def persist_workflow(workflow)
111
114
end
112
115
113
116
def persist_job ( workflow_id , job )
114
- connection_pool . with do |redis |
115
- redis . hset ( "gush.jobs.#{ workflow_id } .#{ job . klass } " , job . id , job . to_json )
116
- end
117
+ redis . hset ( "gush.jobs.#{ workflow_id } .#{ job . klass } " , job . id , job . to_json )
117
118
end
118
119
119
120
def find_job ( workflow_id , job_name )
@@ -132,31 +133,23 @@ def find_job(workflow_id, job_name)
132
133
end
133
134
134
135
def destroy_workflow ( workflow )
135
- connection_pool . with do |redis |
136
- redis . del ( "gush.workflows.#{ workflow . id } " )
137
- end
136
+ redis . del ( "gush.workflows.#{ workflow . id } " )
138
137
workflow . jobs . each { |job | destroy_job ( workflow . id , job ) }
139
138
end
140
139
141
140
def destroy_job ( workflow_id , job )
142
- connection_pool . with do |redis |
143
- redis . del ( "gush.jobs.#{ workflow_id } .#{ job . klass } " )
144
- end
141
+ redis . del ( "gush.jobs.#{ workflow_id } .#{ job . klass } " )
145
142
end
146
143
147
144
def expire_workflow ( workflow , ttl = nil )
148
145
ttl = ttl || configuration . ttl
149
- connection_pool . with do |redis |
150
- redis . expire ( "gush.workflows.#{ workflow . id } " , ttl )
151
- end
146
+ redis . expire ( "gush.workflows.#{ workflow . id } " , ttl )
152
147
workflow . jobs . each { |job | expire_job ( workflow . id , job , ttl ) }
153
148
end
154
149
155
150
def expire_job ( workflow_id , job , ttl = nil )
156
151
ttl = ttl || configuration . ttl
157
- connection_pool . with do |redis |
158
- redis . expire ( "gush.jobs.#{ workflow_id } .#{ job . name } " , ttl )
159
- end
152
+ redis . expire ( "gush.jobs.#{ workflow_id } .#{ job . klass } " , ttl )
160
153
end
161
154
162
155
def enqueue_job ( workflow_id , job )
@@ -172,16 +165,11 @@ def enqueue_job(workflow_id, job)
172
165
def find_job_by_klass_and_id ( workflow_id , job_name )
173
166
job_klass , job_id = job_name . split ( '|' )
174
167
175
- connection_pool . with do |redis |
176
- redis . hget ( "gush.jobs.#{ workflow_id } .#{ job_klass } " , job_id )
177
- end
168
+ redis . hget ( "gush.jobs.#{ workflow_id } .#{ job_klass } " , job_id )
178
169
end
179
170
180
171
def find_job_by_klass ( workflow_id , job_name )
181
- new_cursor , result = connection_pool . with do |redis |
182
- redis . hscan ( "gush.jobs.#{ workflow_id } .#{ job_name } " , 0 , count : 1 )
183
- end
184
-
172
+ new_cursor , result = redis . hscan ( "gush.jobs.#{ workflow_id } .#{ job_name } " , 0 , count : 1 )
185
173
return nil if result . empty?
186
174
187
175
job_id , job = *result [ 0 ]
@@ -202,14 +190,8 @@ def workflow_from_hash(hash, nodes = [])
202
190
flow
203
191
end
204
192
205
- def build_redis
206
- Redis . new ( url : configuration . redis_url ) . tap do |instance |
207
- RedisClassy . redis = instance
208
- end
209
- end
210
-
211
- def connection_pool
212
- @connection_pool ||= ConnectionPool . new ( size : configuration . concurrency , timeout : 1 ) { build_redis }
193
+ def redis
194
+ self . class . redis_connection ( configuration )
213
195
end
214
196
end
215
197
end
0 commit comments