pgtk 0.32.8 → 0.33.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/Gemfile.lock +3 -3
- data/lib/pgtk/stash.rb +39 -3
- 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: 7acb299c9e4e6cd1e272651041704fd89da2858bd1e4b2aa935eed9724815419
|
|
4
|
+
data.tar.gz: 1260a6fb42a11e34d1a733eb9d1bff8ba6a28f81724457e12986adccd134ebc5
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 29aad3a51e77675418fc5eaffa72d7e0015d4e6d1464c87cc118f3ab94e223b0ce4461cffba91e7f4e2d22b594bb0a61f2d4b299db1055d2637d9afca5a0533d
|
|
7
|
+
data.tar.gz: 8483ec44d6da87cd0e57f57e2ca14373965269a5463bc74ba7e38ac4693b4acf35299a64b6ec91a17fc04812160ca31e6826313fce660cdd3e210c8cc3007c81
|
data/Gemfile.lock
CHANGED
|
@@ -36,7 +36,7 @@ GEM
|
|
|
36
36
|
tago (~> 0.1)
|
|
37
37
|
ellipsized (0.3.0)
|
|
38
38
|
joined (0.4.0)
|
|
39
|
-
json (2.
|
|
39
|
+
json (2.20.0)
|
|
40
40
|
language_server-protocol (3.17.0.5)
|
|
41
41
|
lint_roller (1.1.0)
|
|
42
42
|
logger (1.7.0)
|
|
@@ -95,7 +95,7 @@ GEM
|
|
|
95
95
|
tago (~> 0.0)
|
|
96
96
|
regexp_parser (2.12.0)
|
|
97
97
|
rexml (3.4.4)
|
|
98
|
-
rubocop (1.
|
|
98
|
+
rubocop (1.88.1)
|
|
99
99
|
json (~> 2.3)
|
|
100
100
|
language_server-protocol (~> 3.17.0.2)
|
|
101
101
|
lint_roller (~> 1.1.0)
|
|
@@ -109,7 +109,7 @@ GEM
|
|
|
109
109
|
rubocop-ast (1.49.1)
|
|
110
110
|
parser (>= 3.3.7.2)
|
|
111
111
|
prism (~> 1.7)
|
|
112
|
-
rubocop-elegant (0.
|
|
112
|
+
rubocop-elegant (0.7.0)
|
|
113
113
|
lint_roller (~> 1.1)
|
|
114
114
|
rubocop (~> 1.75)
|
|
115
115
|
rubocop-minitest (0.39.1)
|
data/lib/pgtk/stash.rb
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
require 'concurrent-ruby'
|
|
7
7
|
require 'joined'
|
|
8
8
|
require 'loog'
|
|
9
|
+
require 'objspace'
|
|
9
10
|
require 'tago'
|
|
10
11
|
require_relative '../pgtk'
|
|
11
12
|
|
|
@@ -15,6 +16,10 @@ require_relative '../pgtk'
|
|
|
15
16
|
# the cache when tables are modified. Read queries are cached while write
|
|
16
17
|
# queries bypass the cache and invalidate related cached entries.
|
|
17
18
|
#
|
|
19
|
+
# Tables that are too write-heavy to benefit from caching can be listed
|
|
20
|
+
# via the +volatile:+ constructor parameter; any read whose FROM/JOIN
|
|
21
|
+
# set touches one of them bypasses the cache entirely.
|
|
22
|
+
#
|
|
18
23
|
# Thread-safe with read-write locking.
|
|
19
24
|
#
|
|
20
25
|
# The implementation is very naive! Use it at your own risk.
|
|
@@ -67,11 +72,13 @@ class Pgtk::Stash
|
|
|
67
72
|
# @param [Float] retirement Interval in seconds between retirement tasks
|
|
68
73
|
# @param [Loog] loog Logger instance
|
|
69
74
|
# @param [Concurrent::ReentrantReadWriteLock] entrance Read-write lock for thread-safe access
|
|
75
|
+
# @param [Array<String>] volatile Table names that must never be cached
|
|
70
76
|
def initialize(
|
|
71
77
|
pool,
|
|
72
78
|
stash: { queries: {}, tables: {}, table_mod: {}, table_inflight: {} },
|
|
73
79
|
loog: Loog::NULL,
|
|
74
80
|
entrance: Concurrent::ReentrantReadWriteLock.new,
|
|
81
|
+
volatile: [],
|
|
75
82
|
refill: 16,
|
|
76
83
|
delay: 0,
|
|
77
84
|
maxqueue: 128,
|
|
@@ -89,6 +96,7 @@ class Pgtk::Stash
|
|
|
89
96
|
end
|
|
90
97
|
@loog = loog
|
|
91
98
|
@entrance = entrance
|
|
99
|
+
@volatile = Array(volatile).map(&:to_s).freeze
|
|
92
100
|
@refill = refill
|
|
93
101
|
@delay = delay
|
|
94
102
|
@maxqueue = maxqueue
|
|
@@ -133,7 +141,7 @@ class Pgtk::Stash
|
|
|
133
141
|
pure = (query.is_a?(Array) ? query.join(' ') : query).gsub(/\s+/, ' ').strip
|
|
134
142
|
if MODS_RE.match?(pure) || (WITH_RE.match?(pure) && ALTS_RE.match?(pure))
|
|
135
143
|
modify(pure, params, result)
|
|
136
|
-
elsif /(^|\s)pg_[a-z_]+\(/.match?(pure)
|
|
144
|
+
elsif /(^|\s)pg_[a-z_]+\(/.match?(pure) || (!@volatile.empty? && @volatile.intersect?(pure.scan(READS_RE).flatten))
|
|
137
145
|
@pool.exec(pure, params, result)
|
|
138
146
|
else
|
|
139
147
|
select(pure, params, result)
|
|
@@ -146,7 +154,7 @@ class Pgtk::Stash
|
|
|
146
154
|
# @return [Object] The result of the block
|
|
147
155
|
def transaction
|
|
148
156
|
@pool.transaction do |t|
|
|
149
|
-
yield(Pgtk::Stash.new(t, stash: @stash, loog: @loog, entrance: @entrance))
|
|
157
|
+
yield(Pgtk::Stash.new(t, stash: @stash, loog: @loog, entrance: @entrance, volatile: @volatile))
|
|
150
158
|
end
|
|
151
159
|
end
|
|
152
160
|
|
|
@@ -156,7 +164,7 @@ class Pgtk::Stash
|
|
|
156
164
|
# @return [Object] The result of the block
|
|
157
165
|
def session
|
|
158
166
|
@pool.session do |t|
|
|
159
|
-
yield(Pgtk::Stash.new(t, stash: @stash, loog: @loog, entrance: @entrance))
|
|
167
|
+
yield(Pgtk::Stash.new(t, stash: @stash, loog: @loog, entrance: @entrance, volatile: @volatile))
|
|
160
168
|
end
|
|
161
169
|
end
|
|
162
170
|
|
|
@@ -185,6 +193,7 @@ class Pgtk::Stash
|
|
|
185
193
|
' Not launched yet'
|
|
186
194
|
end,
|
|
187
195
|
" #{cached} queries cached (#{cached > @cap ? 'above' : 'below'} the cap)",
|
|
196
|
+
" ~#{footprint} bytes of RAM occupied by cache",
|
|
188
197
|
" #{@stash[:tables].count} tables in cache",
|
|
189
198
|
" #{list.sum { |a| a[:s] }} stale queries in cache:",
|
|
190
199
|
stale(list),
|
|
@@ -327,6 +336,33 @@ class Pgtk::Stash
|
|
|
327
336
|
end
|
|
328
337
|
end
|
|
329
338
|
|
|
339
|
+
# Estimate the total heap footprint, in bytes, of everything held in
|
|
340
|
+
# +@stash[:queries]+.
|
|
341
|
+
#
|
|
342
|
+
# The count of cached entries alone is misleading: a single query with many
|
|
343
|
+
# parameter combinations keeps a distinct +PG::Result+ per combination, and
|
|
344
|
+
# the +cap+ limits the number of entries, not their weight. This gauge sums
|
|
345
|
+
# +ObjectSpace.memsize_of+ over each cached entry and its +:ret+, +:params+,
|
|
346
|
+
# and key strings, so an operator can tell whether the cache is about to
|
|
347
|
+
# exhaust memory. +Marshal+ is not an option here since neither +PG::Result+
|
|
348
|
+
# nor +Concurrent::AtomicFixnum+ is marshallable.
|
|
349
|
+
#
|
|
350
|
+
# The result is approximate: +memsize_of+ is shallow, so nested contents
|
|
351
|
+
# (rows inside a +PG::Result+) are only partially accounted for. A rough
|
|
352
|
+
# order of magnitude is enough.
|
|
353
|
+
#
|
|
354
|
+
# @return [Integer] Approximate total bytes of RAM held by the cache
|
|
355
|
+
def footprint
|
|
356
|
+
@entrance.with_read_lock do
|
|
357
|
+
@stash[:queries].sum do |q, kk|
|
|
358
|
+
ObjectSpace.memsize_of(q) +
|
|
359
|
+
kk.sum do |params, entry|
|
|
360
|
+
[params, entry, entry[:ret], entry[:params]].sum { |o| ObjectSpace.memsize_of(o) }
|
|
361
|
+
end
|
|
362
|
+
end
|
|
363
|
+
end
|
|
364
|
+
end
|
|
365
|
+
|
|
330
366
|
# Discover ON DELETE CASCADE / ON UPDATE CASCADE foreign keys so that a
|
|
331
367
|
# modify on the parent table also invalidates cached queries on children.
|
|
332
368
|
def cascade!
|
data/lib/pgtk/version.rb
CHANGED