ask-state-providers 0.4.4 → 0.4.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/ask/state/providers/postgres.rb +45 -18
- data/lib/ask/state/providers/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: cb68f83181b30aa39191b2d19252a62231921b17aae87e1f3673bc0bb97cfacb
|
|
4
|
+
data.tar.gz: 8ffdbac8c8577c8934482c8ed7b2b8e96563e9994ba48770ecbe7c51b0eaca46
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: '0907e2cbe480f8760546a6f5790ea19ab8c81694db591a864ebc4de4f538d1f1baecac436b91257f544ed93e8b9de7ffeaa9d396c118b7a63a87750167a69e62'
|
|
7
|
+
data.tar.gz: 42984849cf013942caf8fbc27a859abc40e37720bf5c26a60e92c4e435f0df0cb133f1c591ef0e88284ac5b342e451c084c34fd0eb55391200d9161163de6ec3
|
|
@@ -60,6 +60,13 @@ module Ask
|
|
|
60
60
|
# @param pool_size [Integer] connection pool size (default 5)
|
|
61
61
|
def initialize(url: ENV.fetch("DATABASE_URL", "postgres://localhost:5432/ask_state"),
|
|
62
62
|
pool_size: 5)
|
|
63
|
+
# On macOS, libpq's default GSSAPI negotiation can segfault
|
|
64
|
+
# when a forked process (SolidQueue worker) opens a fresh
|
|
65
|
+
# connection — the same crash the sibling apps guard with
|
|
66
|
+
# `gssencmode: disable` in database.yml. The store connects
|
|
67
|
+
# directly (not through ActiveRecord), so the guard lives here.
|
|
68
|
+
url = self.class.darwin_safe_url(url) if RUBY_PLATFORM =~ /darwin/
|
|
69
|
+
|
|
63
70
|
@pool = ConnectionPool.new(size: pool_size) do
|
|
64
71
|
::PG.connect(url)
|
|
65
72
|
end
|
|
@@ -67,10 +74,18 @@ module Ask
|
|
|
67
74
|
migrate
|
|
68
75
|
end
|
|
69
76
|
|
|
77
|
+
# Append gssencmode=disable to a URL on macOS (idempotent).
|
|
78
|
+
def self.darwin_safe_url(url)
|
|
79
|
+
return url if url.include?("gssencmode")
|
|
80
|
+
|
|
81
|
+
separator = url.include?("?") ? "&" : "?"
|
|
82
|
+
"#{url}#{separator}gssencmode=disable"
|
|
83
|
+
end
|
|
84
|
+
|
|
70
85
|
# -- key-value --
|
|
71
86
|
|
|
72
87
|
def get(key)
|
|
73
|
-
|
|
88
|
+
with_connection do |conn|
|
|
74
89
|
row = conn.exec_params(<<~SQL, [key, Time.now.utc])
|
|
75
90
|
SELECT value FROM state_store
|
|
76
91
|
WHERE key = $1 AND (expires_at IS NULL OR expires_at > $2)
|
|
@@ -80,7 +95,7 @@ module Ask
|
|
|
80
95
|
end
|
|
81
96
|
|
|
82
97
|
def set(key, value, ttl: nil)
|
|
83
|
-
|
|
98
|
+
with_connection do |conn|
|
|
84
99
|
# Explicit casts: $3 is nil when no ttl, and PostgreSQL can't
|
|
85
100
|
# infer a type for a bare NULL parameter.
|
|
86
101
|
conn.exec_params(<<~SQL, [key, JSON.generate(value), ttl ? Time.now.utc + ttl : nil])
|
|
@@ -94,7 +109,7 @@ module Ask
|
|
|
94
109
|
end
|
|
95
110
|
|
|
96
111
|
def delete(key)
|
|
97
|
-
|
|
112
|
+
with_connection do |conn|
|
|
98
113
|
conn.exec_params("DELETE FROM state_store WHERE key = $1", [key])
|
|
99
114
|
# delete removes everything under the key, including ordered
|
|
100
115
|
# lists (consumers store event feeds as lists).
|
|
@@ -103,7 +118,7 @@ module Ask
|
|
|
103
118
|
end
|
|
104
119
|
|
|
105
120
|
def set_if_not_exists(key, value, ttl: nil)
|
|
106
|
-
|
|
121
|
+
with_connection do |conn|
|
|
107
122
|
now = Time.now.utc
|
|
108
123
|
expires = ttl ? now + ttl : nil
|
|
109
124
|
|
|
@@ -128,7 +143,7 @@ module Ask
|
|
|
128
143
|
end
|
|
129
144
|
|
|
130
145
|
def clear
|
|
131
|
-
|
|
146
|
+
with_connection do |conn|
|
|
132
147
|
conn.exec("DELETE FROM state_store")
|
|
133
148
|
conn.exec("DELETE FROM locks")
|
|
134
149
|
conn.exec("DELETE FROM queues")
|
|
@@ -137,7 +152,7 @@ module Ask
|
|
|
137
152
|
end
|
|
138
153
|
|
|
139
154
|
def exists?(key)
|
|
140
|
-
|
|
155
|
+
with_connection do |conn|
|
|
141
156
|
result = conn.exec_params(<<~SQL, [key, Time.now.utc])
|
|
142
157
|
SELECT 1 FROM state_store
|
|
143
158
|
WHERE key = $1 AND (expires_at IS NULL OR expires_at > $2)
|
|
@@ -147,7 +162,7 @@ module Ask
|
|
|
147
162
|
end
|
|
148
163
|
|
|
149
164
|
def keys(pattern: nil)
|
|
150
|
-
|
|
165
|
+
with_connection do |conn|
|
|
151
166
|
sql, params = if pattern
|
|
152
167
|
like = self.class.glob_to_like(pattern)
|
|
153
168
|
[<<~SQL, [like, Time.now.utc]]
|
|
@@ -171,7 +186,7 @@ module Ask
|
|
|
171
186
|
expires_at_time = now + ttl
|
|
172
187
|
token = SecureRandom.hex(16)
|
|
173
188
|
|
|
174
|
-
acquired =
|
|
189
|
+
acquired = with_connection do |conn|
|
|
175
190
|
# First clean up expired locks
|
|
176
191
|
conn.exec_params("DELETE FROM locks WHERE key = $1 AND expires_at <= $2",
|
|
177
192
|
[key, now])
|
|
@@ -191,7 +206,7 @@ module Ask
|
|
|
191
206
|
end
|
|
192
207
|
|
|
193
208
|
def release_lock(key, lock)
|
|
194
|
-
|
|
209
|
+
with_connection do |conn|
|
|
195
210
|
result = conn.exec_params(
|
|
196
211
|
"DELETE FROM locks WHERE key = $1 AND token = $2",
|
|
197
212
|
[key, lock.token]
|
|
@@ -205,7 +220,7 @@ module Ask
|
|
|
205
220
|
def enqueue(queue, value)
|
|
206
221
|
id = SecureRandom.uuid
|
|
207
222
|
|
|
208
|
-
|
|
223
|
+
with_connection do |conn|
|
|
209
224
|
conn.exec_params(<<~SQL, [queue, JSON.generate(value), Time.now.utc])
|
|
210
225
|
INSERT INTO queues (queue_name, value, enqueued_at)
|
|
211
226
|
VALUES ($1, $2, $3)
|
|
@@ -216,7 +231,7 @@ module Ask
|
|
|
216
231
|
end
|
|
217
232
|
|
|
218
233
|
def dequeue(queue)
|
|
219
|
-
|
|
234
|
+
with_connection do |conn|
|
|
220
235
|
result = conn.exec_params(<<~SQL, [queue])
|
|
221
236
|
DELETE FROM queues
|
|
222
237
|
WHERE id = (
|
|
@@ -238,7 +253,7 @@ module Ask
|
|
|
238
253
|
end
|
|
239
254
|
|
|
240
255
|
def queue_depth(queue)
|
|
241
|
-
|
|
256
|
+
with_connection do |conn|
|
|
242
257
|
result = conn.exec_params(
|
|
243
258
|
"SELECT COUNT(*) AS cnt FROM queues WHERE queue_name = $1", [queue]
|
|
244
259
|
)
|
|
@@ -249,7 +264,7 @@ module Ask
|
|
|
249
264
|
# -- ordered lists --
|
|
250
265
|
|
|
251
266
|
def list_append(key, value, max_length: nil)
|
|
252
|
-
|
|
267
|
+
with_connection do |conn|
|
|
253
268
|
conn.exec_params(<<~SQL, [key, JSON.generate(value)])
|
|
254
269
|
INSERT INTO lists (list_key, value)
|
|
255
270
|
VALUES ($1, $2)
|
|
@@ -274,7 +289,7 @@ module Ask
|
|
|
274
289
|
end
|
|
275
290
|
|
|
276
291
|
def list_range(key, start = 0, stop = -1)
|
|
277
|
-
|
|
292
|
+
with_connection do |conn|
|
|
278
293
|
rows = if stop == -1
|
|
279
294
|
conn.exec_params(<<~SQL, [key, start])
|
|
280
295
|
SELECT value FROM lists
|
|
@@ -297,7 +312,7 @@ module Ask
|
|
|
297
312
|
|
|
298
313
|
def list_remove(key, value)
|
|
299
314
|
serialized = JSON.generate(value)
|
|
300
|
-
|
|
315
|
+
with_connection do |conn|
|
|
301
316
|
result = conn.exec_params(
|
|
302
317
|
"DELETE FROM lists WHERE list_key = $1 AND value = $2",
|
|
303
318
|
[key, serialized]
|
|
@@ -311,17 +326,29 @@ module Ask
|
|
|
311
326
|
# Idempotent setup — creates tables if they don't exist.
|
|
312
327
|
# Called automatically on initialize. Safe to call multiple times.
|
|
313
328
|
def setup!
|
|
314
|
-
|
|
329
|
+
with_connection { |conn| conn.exec(MIGRATIONS) }
|
|
315
330
|
end
|
|
316
331
|
|
|
317
332
|
def close
|
|
318
|
-
@pool&.shutdown { |c| c.close }
|
|
333
|
+
@pool&.shutdown { |c| c.close unless c.finished? }
|
|
319
334
|
end
|
|
320
335
|
|
|
321
336
|
private
|
|
322
337
|
|
|
338
|
+
# Check out a connection, running the block with it. A dead
|
|
339
|
+
# pooled connection (the server closed it — a fork inherited it,
|
|
340
|
+
# an idle timeout, a server restart) raises PG::ConnectionBad;
|
|
341
|
+
# reload the pool and retry once so a stale checkout never
|
|
342
|
+
# surfaces to callers.
|
|
343
|
+
def with_connection(&block)
|
|
344
|
+
@pool.with(&block)
|
|
345
|
+
rescue PG::ConnectionBad
|
|
346
|
+
@pool.reload { |conn| conn.close unless conn.finished? }
|
|
347
|
+
@pool.with(&block)
|
|
348
|
+
end
|
|
349
|
+
|
|
323
350
|
def migrate
|
|
324
|
-
|
|
351
|
+
with_connection { |conn| conn.exec(MIGRATIONS) }
|
|
325
352
|
end
|
|
326
353
|
end
|
|
327
354
|
end
|