ask-state-providers 0.4.3 → 0.4.4

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 51d2e01d6072da9c0296061aabcd038dd19e24b72d80de80b68a7ae3ed0ca8c3
4
- data.tar.gz: 2e2f5887f6e4cc7cfdfd56c20318532cc12c1a709533a333aff715a3d2b29056
3
+ metadata.gz: 269e8a62defb31a02eb53fe42e5e13fb375b1a2037d3feb1a88048481f670ff5
4
+ data.tar.gz: 86ca88be92adcd9ee95651904cf3fd72079a1adc899a1870c87065de1657d1e8
5
5
  SHA512:
6
- metadata.gz: 3552f0646a71c13685d16671d2dada5dec480c8dc40096e792c09220e9cd7da0013af0c600004c30935dba15dc53b66c37159c0e9b7011ce060d042d8524780a
7
- data.tar.gz: 5236da7d851548d43c89dec20ab7f130a6a54f5b77b52ced711553607143dc98a4e03c476f23b60480e79ebea3ac1c0548a0d7340add3ffe3526e1595d68d073
6
+ metadata.gz: 0f8cd296decf02725687d44a96d3991b074fe975425885bf49ca064f68472370ed17d4596a336c8abaf6f8ff20366d0d7ff571a26dd7f46df1a0017c1d5053ac
7
+ data.tar.gz: 7c7425f0732e1f92b66b9458274ded4009e42ef673ac354e266290055af0792a0451d27e2c1b6b1ff9329c26ed2e0400283471dd4890962a7b7b8c1dfae75cd1
@@ -3,6 +3,8 @@
3
3
  require "json"
4
4
  require "time"
5
5
  require "securerandom"
6
+ require "connection_pool"
7
+ require "pg"
6
8
 
7
9
  module Ask
8
10
  module State
@@ -58,8 +60,6 @@ module Ask
58
60
  # @param pool_size [Integer] connection pool size (default 5)
59
61
  def initialize(url: ENV.fetch("DATABASE_URL", "postgres://localhost:5432/ask_state"),
60
62
  pool_size: 5)
61
- require "pg"
62
-
63
63
  @pool = ConnectionPool.new(size: pool_size) do
64
64
  ::PG.connect(url)
65
65
  end
@@ -81,9 +81,11 @@ module Ask
81
81
 
82
82
  def set(key, value, ttl: nil)
83
83
  @pool.with do |conn|
84
+ # Explicit casts: $3 is nil when no ttl, and PostgreSQL can't
85
+ # infer a type for a bare NULL parameter.
84
86
  conn.exec_params(<<~SQL, [key, JSON.generate(value), ttl ? Time.now.utc + ttl : nil])
85
87
  INSERT INTO state_store (key, value, expires_at)
86
- VALUES ($1, $2, $3)
88
+ VALUES ($1::text, $2::text, $3::timestamptz)
87
89
  ON CONFLICT (key) DO UPDATE SET
88
90
  value = EXCLUDED.value,
89
91
  expires_at = EXCLUDED.expires_at
@@ -105,14 +107,21 @@ module Ask
105
107
  now = Time.now.utc
106
108
  expires = ttl ? now + ttl : nil
107
109
 
110
+ # Insert when the key is missing or its row is expired. An
111
+ # expired row still conflicts on the primary key, so the
112
+ # ON CONFLICT branch overwrites it — but only when it is
113
+ # actually expired, never a live value.
108
114
  result = conn.exec_params(<<~SQL, [key, JSON.generate(value), expires, now])
109
115
  INSERT INTO state_store (key, value, expires_at)
110
- SELECT $1, $2, $3
116
+ SELECT $1::text, $2::text, $3::timestamptz
111
117
  WHERE NOT EXISTS (
112
118
  SELECT 1 FROM state_store
113
119
  WHERE key = $1 AND (expires_at IS NULL OR expires_at > $4)
114
120
  )
115
- ON CONFLICT (key) DO NOTHING
121
+ ON CONFLICT (key) DO UPDATE SET
122
+ value = EXCLUDED.value,
123
+ expires_at = EXCLUDED.expires_at
124
+ WHERE state_store.expires_at IS NOT NULL AND state_store.expires_at <= $4
116
125
  SQL
117
126
  result.cmd_tuples > 0
118
127
  end
@@ -167,9 +176,9 @@ module Ask
167
176
  conn.exec_params("DELETE FROM locks WHERE key = $1 AND expires_at <= $2",
168
177
  [key, now])
169
178
 
170
- result = conn.exec_params(<<~SQL, [key, expires_at_time, token, now])
179
+ result = conn.exec_params(<<~SQL, [key, expires_at_time, token])
171
180
  INSERT INTO locks (key, expires_at, token)
172
- SELECT $1, $2, $3
181
+ SELECT $1::text, $2::timestamptz, $3::text
173
182
  WHERE NOT EXISTS (
174
183
  SELECT 1 FROM locks
175
184
  WHERE key = $1
@@ -248,13 +257,16 @@ module Ask
248
257
 
249
258
  return unless max_length
250
259
 
251
- conn.exec_params(<<~SQL, [key, key, max_length])
252
- DELETE FROM lists WHERE id <= (
260
+ # Keep the newest max_length entries: the cutoff is the
261
+ # oldest id inside the newest max_length — delete strictly
262
+ # older rows (and only this list's).
263
+ conn.exec_params(<<~SQL, [key, max_length, key])
264
+ DELETE FROM lists WHERE list_key = $3 AND id < (
253
265
  SELECT COALESCE(MIN(id), 0) FROM (
254
266
  SELECT id FROM lists
255
267
  WHERE list_key = $1
256
268
  ORDER BY id DESC
257
- LIMIT $3
269
+ LIMIT $2::bigint
258
270
  ) sub
259
271
  )
260
272
  SQL
@@ -3,7 +3,7 @@
3
3
  module Ask
4
4
  module State
5
5
  module Providers
6
- VERSION = "0.4.3"
6
+ VERSION = "0.4.4"
7
7
  end
8
8
  end
9
9
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ask-state-providers
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.3
4
+ version: 0.4.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kaka Ruto
@@ -23,6 +23,34 @@ dependencies:
23
23
  - - ">="
24
24
  - !ruby/object:Gem::Version
25
25
  version: 0.11.3
26
+ - !ruby/object:Gem::Dependency
27
+ name: connection_pool
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: '2.2'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '2.2'
40
+ - !ruby/object:Gem::Dependency
41
+ name: pg
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: '1.5'
47
+ type: :runtime
48
+ prerelease: false
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: '1.5'
26
54
  - !ruby/object:Gem::Dependency
27
55
  name: minitest
28
56
  requirement: !ruby/object:Gem::Requirement