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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5eb38e8d785a444233248ed07fe7ba2316b947b1b3a779f7738145cff4d56306
4
- data.tar.gz: 8870ff5a0a87c911439618b6d26c9e42a9bb37edcf14182b4067d208774794a9
3
+ metadata.gz: 5b7cf162ce55193a057e281c59e4ade55ba6dccee8e2076e7ebf6cc5ebd8b3d6
4
+ data.tar.gz: f84661c917982464a21be179bccd34e7ae0b8d3f234562dcf026e3f5aebe4793
5
5
  SHA512:
6
- metadata.gz: 15991d0bd081e1b4a35da843c346e2da28196f0fa682a5088de811f37cb027bb57134fc92444ffdd3c6aa29587ff974085d6cb02cf3852a6e23419efd9a8fb94
7
- data.tar.gz: 5fcb874e760ad74bca1c04aa2291c444139dbb441b84ac60dfc5352ae81c1174db7d3e8884aed413919cdb0d5863bf6c0120642f44250481380a5b065319bd0d
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 [Integer] refill_interval Interval in seconds between background tasks that recalculate stale
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 [Integer] cap_interval Interval in seconds between background tasks that enforce the cache size
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 [Integer] retire_interval Interval in seconds between background tasks that remove
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
- @launched = launched
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
- "cap=#{@cap}",
139
- "cap_interval=#{@cap_interval}s",
140
- "retire=#{@retire}",
141
- "retire_interval=#{@retire_interval}s"
142
- ].join(', '),
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
- " #{'not ' if @launched.false?}launched",
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] = true
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
- raise 'Cannot launch multiple times on same cache data' unless @launched.make_true
256
- Concurrent::TimerTask.execute(execution_interval: @cap_interval, executor: @tpool) do
257
- loop do
258
- break if stash_size <= @cap
259
- @entrance.with_write_lock do
260
- @stash[:queries].each_key do |q|
261
- m = @stash[:queries][q].values.map { |h| h[:used] }.min
262
- next unless m
263
- @stash[:queries][q].delete_if { |_, h| h[:used] == m }
264
- @stash[:queries].delete_if { |_, kk| kk.empty? }
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
- Concurrent::TimerTask.execute(execution_interval: @retire_interval, executor: @tpool) do
270
- @entrance.with_write_lock do
271
- @stash[:queries].each_key do |q|
272
- @stash[:queries][q].delete_if { |_, h| h[:used] < Time.now - @retire }
273
- @stash[:queries].delete_if { |_, kk| kk.empty? }
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[:stale] = false
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
@@ -11,5 +11,5 @@ require_relative '../pgtk'
11
11
  # License:: MIT
12
12
  module Pgtk
13
13
  # Current version of the library.
14
- VERSION = '0.24.4'
14
+ VERSION = '0.26.0'
15
15
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pgtk
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.24.4
4
+ version: 0.26.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yegor Bugayenko