pgtk 0.24.4 → 0.26.0
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/README.md +3 -0
- data/lib/pgtk/stash.rb +68 -45
- data/lib/pgtk/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: 5b7cf162ce55193a057e281c59e4ade55ba6dccee8e2076e7ebf6cc5ebd8b3d6
|
|
4
|
+
data.tar.gz: f84661c917982464a21be179bccd34e7ae0b8d3f234562dcf026e3f5aebe4793
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 855c4d94c5ff429abe22d4593076f459df95f9cf3612157c149e929243f79e2d49bf9d56183d2c0da074e8abb30e73bff12722dbd1e57e04c3385abd8ca9314c
|
|
7
|
+
data.tar.gz: 7d9f3cfc61dfda380a6bdb63f3451ba8f09cf798796a8786fe6a0ce251e25174faf1cf21d1e4619cfed6bea95041a1072f9c62c9a60e3c825a229795d115cd6b
|
data/README.md
CHANGED
|
@@ -228,6 +228,9 @@ stash = Pgtk::Stash.new(
|
|
|
228
228
|
cap: 10_000, # Maximum cached query results (default: 10,000)
|
|
229
229
|
cap_interval: 60, # Seconds between cache size enforcement (default: 60)
|
|
230
230
|
refill_interval: 16, # Seconds between stale query refilling (default: 16)
|
|
231
|
+
refill_delay: 0.5, # Seconds to wait before refilling the cache (default: 0)
|
|
232
|
+
retire: 60, # Maximum age in seconds to keep a query in cache (default: 15 min)
|
|
233
|
+
retire_interval: 5.5, # How often to retire (default: 60)
|
|
231
234
|
threads: 4, # Worker threads for background refilling (default: 4)
|
|
232
235
|
max_queue_length: 128 # Maximum refilling tasks in queue (default: 128)
|
|
233
236
|
)
|
data/lib/pgtk/stash.rb
CHANGED
|
@@ -41,54 +41,54 @@ class Pgtk::Stash
|
|
|
41
41
|
|
|
42
42
|
# Initialize a new Stash with query caching.
|
|
43
43
|
#
|
|
44
|
+
# Set any of the intervals to nil to disable the cron.
|
|
45
|
+
#
|
|
44
46
|
# @param [Object] pool The underlying connection pool that executes actual database queries
|
|
45
47
|
# @param [Hash] stash Internal cache structure containing queries and tables hashes for sharing state
|
|
46
48
|
# across transactions
|
|
47
|
-
# @param [
|
|
49
|
+
# @param [Float] refill_interval Interval in seconds between background tasks that recalculate stale
|
|
48
50
|
# cached queries
|
|
51
|
+
# @param [Float] refill_delay A pause in seconds we take before making a refill
|
|
49
52
|
# @param [Integer] max_queue_length Maximum number of refilling tasks allowed in the thread pool queue
|
|
50
53
|
# before new tasks are skipped
|
|
51
54
|
# @param [Integer] threads Number of worker threads in the background thread pool for cache refilling
|
|
52
55
|
# operations
|
|
53
56
|
# @param [Integer] cap Maximum number of cached query results to retain; oldest queries are evicted when
|
|
54
57
|
# this limit is exceeded
|
|
55
|
-
# @param [
|
|
58
|
+
# @param [Float] cap_interval Interval in seconds between background tasks that enforce the cache size
|
|
56
59
|
# cap by removing old queries
|
|
57
60
|
# @param [Integer] retire Maximum age in seconds to keep a query in cache after its latest usage
|
|
58
|
-
# @param [
|
|
61
|
+
# @param [Float] retire_interval Interval in seconds between background tasks that remove
|
|
59
62
|
# retired queries
|
|
60
63
|
# @param [Loog] loog Logger instance for debugging and monitoring cache operations (default: null logger)
|
|
61
64
|
# @param [Concurrent::ReentrantReadWriteLock] entrance Read-write lock for thread-safe cache access
|
|
62
65
|
# shared across instances
|
|
63
|
-
# @param [Concurrent::AtomicBoolean] launched Atomic boolean flag tracking whether background tasks have
|
|
64
|
-
# been started to prevent multiple launches
|
|
65
66
|
def initialize(
|
|
66
67
|
pool,
|
|
67
68
|
stash: { queries: {}, tables: {} },
|
|
69
|
+
loog: Loog::NULL,
|
|
70
|
+
entrance: Concurrent::ReentrantReadWriteLock.new,
|
|
68
71
|
refill_interval: 16,
|
|
72
|
+
refill_delay: 0,
|
|
69
73
|
max_queue_length: 128,
|
|
70
74
|
threads: 4,
|
|
71
75
|
cap: 10_000,
|
|
72
76
|
cap_interval: 60,
|
|
73
77
|
retire: 15 * 60,
|
|
74
|
-
retire_interval: 60
|
|
75
|
-
loog: Loog::NULL,
|
|
76
|
-
entrance: Concurrent::ReentrantReadWriteLock.new,
|
|
77
|
-
launched: Concurrent::AtomicBoolean.new(false)
|
|
78
|
+
retire_interval: 60
|
|
78
79
|
)
|
|
79
80
|
@pool = pool
|
|
80
81
|
@stash = stash
|
|
81
|
-
@
|
|
82
|
+
@loog = loog
|
|
82
83
|
@entrance = entrance
|
|
83
84
|
@refill_interval = refill_interval
|
|
85
|
+
@refill_delay = refill_delay
|
|
84
86
|
@max_queue_length = max_queue_length
|
|
85
87
|
@threads = threads
|
|
86
88
|
@cap = cap
|
|
87
89
|
@cap_interval = cap_interval
|
|
88
90
|
@retire = retire
|
|
89
91
|
@retire_interval = retire_interval
|
|
90
|
-
@loog = loog
|
|
91
|
-
@tpool = Concurrent::FixedThreadPool.new(@threads)
|
|
92
92
|
end
|
|
93
93
|
|
|
94
94
|
# Start the connection pool and launch background cache management tasks.
|
|
@@ -99,8 +99,8 @@ class Pgtk::Stash
|
|
|
99
99
|
#
|
|
100
100
|
# @return [void]
|
|
101
101
|
def start!
|
|
102
|
-
launch!
|
|
103
102
|
@pool.start!
|
|
103
|
+
launch!
|
|
104
104
|
end
|
|
105
105
|
|
|
106
106
|
# Get the PostgreSQL server version.
|
|
@@ -132,19 +132,41 @@ class Pgtk::Stash
|
|
|
132
132
|
[
|
|
133
133
|
'Pgtk::Stash (',
|
|
134
134
|
[
|
|
135
|
-
"refill_interval=#{@refill_interval}s",
|
|
136
|
-
"max_queue_length=#{@max_queue_length}",
|
|
137
135
|
"threads=#{@threads}",
|
|
138
|
-
"
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
136
|
+
"max_queue_length=#{@max_queue_length}",
|
|
137
|
+
if @refill_interval
|
|
138
|
+
[
|
|
139
|
+
"refill_interval=#{@refill_interval}s",
|
|
140
|
+
"refill_delay=#{@refill_delay}s"
|
|
141
|
+
]
|
|
142
|
+
else
|
|
143
|
+
'no refilling'
|
|
144
|
+
end,
|
|
145
|
+
if @cap_interval
|
|
146
|
+
[
|
|
147
|
+
"cap_interval=#{@cap_interval}s",
|
|
148
|
+
"cap=#{@cap}"
|
|
149
|
+
]
|
|
150
|
+
else
|
|
151
|
+
'no capping'
|
|
152
|
+
end,
|
|
153
|
+
if @retire_interval
|
|
154
|
+
[
|
|
155
|
+
"retire_interval=#{@retire_interval}s",
|
|
156
|
+
"retire=#{@retire}"
|
|
157
|
+
]
|
|
158
|
+
else
|
|
159
|
+
'no retirement'
|
|
160
|
+
end
|
|
161
|
+
].flatten.join(', '),
|
|
143
162
|
'):'
|
|
144
163
|
].join,
|
|
145
|
-
|
|
164
|
+
if @tpool
|
|
165
|
+
" #{@tpool.queue_length} tasks in the thread pool"
|
|
166
|
+
else
|
|
167
|
+
' Not launched yet'
|
|
168
|
+
end,
|
|
146
169
|
" #{stash_size} queries cached (#{stash_size > @cap ? 'above' : 'below'} the cap)",
|
|
147
|
-
" #{@tpool.queue_length} tasks in the thread pool",
|
|
148
170
|
" #{@stash[:tables].count} tables in cache",
|
|
149
171
|
" #{qq.sum { |a| a[:s] }} stale queries in cache:",
|
|
150
172
|
qq.select { |a| a[:s].positive? }.sort_by { -_1[:p] }.take(8).map do |a|
|
|
@@ -177,7 +199,7 @@ class Pgtk::Stash
|
|
|
177
199
|
tables.each do |t|
|
|
178
200
|
@stash[:tables][t]&.each do |q|
|
|
179
201
|
@stash[:queries][q]&.each_key do |key|
|
|
180
|
-
@stash[:queries][q][key][:stale] =
|
|
202
|
+
@stash[:queries][q][key][:stale] = Time.now
|
|
181
203
|
end
|
|
182
204
|
end
|
|
183
205
|
end
|
|
@@ -222,12 +244,8 @@ class Pgtk::Stash
|
|
|
222
244
|
yield Pgtk::Stash.new(
|
|
223
245
|
t,
|
|
224
246
|
stash: @stash,
|
|
225
|
-
refill_interval: @refill_interval,
|
|
226
|
-
max_queue_length: @max_queue_length,
|
|
227
|
-
threads: @threads,
|
|
228
247
|
loog: @loog,
|
|
229
|
-
entrance: @entrance
|
|
230
|
-
launched: @launched
|
|
248
|
+
entrance: @entrance
|
|
231
249
|
)
|
|
232
250
|
end
|
|
233
251
|
end
|
|
@@ -252,28 +270,33 @@ class Pgtk::Stash
|
|
|
252
270
|
# @return [nil]
|
|
253
271
|
# @raise [RuntimeError] if background tasks have already been launched on this cache instance
|
|
254
272
|
def launch!
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
@
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
273
|
+
@tpool = Concurrent::FixedThreadPool.new(@threads)
|
|
274
|
+
if @cap_interval
|
|
275
|
+
Concurrent::TimerTask.execute(execution_interval: @cap_interval, executor: @tpool) do
|
|
276
|
+
loop do
|
|
277
|
+
break if stash_size <= @cap
|
|
278
|
+
@entrance.with_write_lock do
|
|
279
|
+
@stash[:queries].each_key do |q|
|
|
280
|
+
m = @stash[:queries][q].values.map { |h| h[:used] }.min
|
|
281
|
+
next unless m
|
|
282
|
+
@stash[:queries][q].delete_if { |_, h| h[:used] == m }
|
|
283
|
+
@stash[:queries].delete_if { |_, kk| kk.empty? }
|
|
284
|
+
end
|
|
265
285
|
end
|
|
266
286
|
end
|
|
267
287
|
end
|
|
268
288
|
end
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
@
|
|
272
|
-
@stash[:queries]
|
|
273
|
-
|
|
289
|
+
if @retire_interval
|
|
290
|
+
Concurrent::TimerTask.execute(execution_interval: @retire_interval, executor: @tpool) do
|
|
291
|
+
@entrance.with_write_lock do
|
|
292
|
+
@stash[:queries].each_key do |q|
|
|
293
|
+
@stash[:queries][q].delete_if { |_, h| h[:used] < Time.now - @retire }
|
|
294
|
+
@stash[:queries].delete_if { |_, kk| kk.empty? }
|
|
295
|
+
end
|
|
274
296
|
end
|
|
275
297
|
end
|
|
276
298
|
end
|
|
299
|
+
return unless @refill_interval
|
|
277
300
|
Concurrent::TimerTask.execute(execution_interval: @refill_interval, executor: @tpool) do
|
|
278
301
|
@stash[:queries]
|
|
279
302
|
.map { |k, v| [k, v.values.sum { |vv| vv[:popularity] }, v.values.any? { |vv| vv[:stale] }] }
|
|
@@ -283,19 +306,19 @@ class Pgtk::Stash
|
|
|
283
306
|
q = a[0]
|
|
284
307
|
@stash[:queries][q].each_key do |k|
|
|
285
308
|
next unless @stash[:queries][q][k][:stale]
|
|
309
|
+
next if @stash[:queries][q][k][:stale] > Time.now - @refill_delay
|
|
286
310
|
next if @tpool.queue_length >= @max_queue_length
|
|
287
311
|
@tpool.post do
|
|
288
312
|
h = @stash[:queries][q][k]
|
|
289
313
|
ret = @pool.exec(q, h[:params], h[:result])
|
|
290
314
|
@entrance.with_write_lock do
|
|
291
315
|
h = @stash[:queries][q][k]
|
|
292
|
-
h
|
|
316
|
+
h.delete(:stale)
|
|
293
317
|
h[:ret] = ret
|
|
294
318
|
end
|
|
295
319
|
end
|
|
296
320
|
end
|
|
297
321
|
end
|
|
298
322
|
end
|
|
299
|
-
nil
|
|
300
323
|
end
|
|
301
324
|
end
|
data/lib/pgtk/version.rb
CHANGED