tina4ruby 3.13.31 → 3.13.32
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/tina4/database.rb +22 -7
- data/lib/tina4/response_cache.rb +35 -10
- data/lib/tina4/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: 02b84dbb5f8e4d009306495921ab7849a28fd769d81d13019b311523d970a0e5
|
|
4
|
+
data.tar.gz: e1b298c7bd03444def8787941f87a7e6fd0adcb6be23efe810990c6005d27910
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8bf774f6208956221c87bb2f546a04aab950a3cae5962dae94bbd430ee55463481886ba315a21f2680b017828d99df0c6e7a54fff331cff0e559b176da45c5a9
|
|
7
|
+
data.tar.gz: 5242a9295d6e70763ca68a377f2aa3dfd2ac8b37402b8660f439ea6bc6e0c5ddb1f278d277c2ff4ab8bf62b6d80f0ad316c8c07c099f07ecdee9040bea0ddfe5
|
data/lib/tina4/database.rb
CHANGED
|
@@ -366,11 +366,20 @@ module Tina4
|
|
|
366
366
|
# v3.13.12: default `limit` is **nil** (no truncation) — the method
|
|
367
367
|
# name says fetch_all, so it returns all matching rows. Pre-v3.13.12
|
|
368
368
|
# silently truncated to 100. Pass an explicit `limit:` to cap.
|
|
369
|
-
|
|
370
|
-
|
|
369
|
+
#
|
|
370
|
+
# Pass `no_cache: true` to bypass the query cache for this call (see #fetch).
|
|
371
|
+
def fetch_all(sql, params = [], limit: nil, offset: nil, no_cache: false)
|
|
372
|
+
fetch(sql, params, limit: limit, offset: offset, no_cache: no_cache).records
|
|
371
373
|
end
|
|
372
374
|
|
|
373
|
-
|
|
375
|
+
# Fetch rows with pagination, returning a DatabaseResult.
|
|
376
|
+
#
|
|
377
|
+
# Pass `no_cache: true` to bypass the query cache entirely for this single
|
|
378
|
+
# call — no lookup, no store — and run the query directly against the
|
|
379
|
+
# driver. Works for both the request-scoped auto-cache and the persistent
|
|
380
|
+
# DB cache. The default `false` preserves the cached behaviour. Parity with
|
|
381
|
+
# Python db.fetch(no_cache=) / PHP / Node.
|
|
382
|
+
def fetch(sql, params = [], limit: 100, offset: nil, no_cache: false)
|
|
374
383
|
offset ||= 0
|
|
375
384
|
drv = current_driver
|
|
376
385
|
|
|
@@ -388,7 +397,7 @@ module Tina4
|
|
|
388
397
|
effective_sql = drv.apply_limit(effective_sql, limit, offset)
|
|
389
398
|
end
|
|
390
399
|
|
|
391
|
-
if @cache_enabled
|
|
400
|
+
if @cache_enabled && !no_cache
|
|
392
401
|
key = cache_key(effective_sql, params)
|
|
393
402
|
cached = cache_get(key)
|
|
394
403
|
if cached
|
|
@@ -406,9 +415,15 @@ module Tina4
|
|
|
406
415
|
Tina4::DatabaseResult.new(rows, sql: effective_sql, db: self)
|
|
407
416
|
end
|
|
408
417
|
|
|
409
|
-
|
|
418
|
+
# Fetch a single row (or nil).
|
|
419
|
+
#
|
|
420
|
+
# Pass `no_cache: true` to bypass the query cache entirely for this call —
|
|
421
|
+
# no lookup, no store — running the query directly. The `no_cache` flag is
|
|
422
|
+
# propagated to the inner #fetch so the request-scoped/persistent cache is
|
|
423
|
+
# never populated either. Default `false` preserves cached behaviour.
|
|
424
|
+
def fetch_one(sql, params = [], no_cache: false)
|
|
410
425
|
sql = Tina4::Database.strip_trailing_semicolons(sql)
|
|
411
|
-
if @cache_enabled
|
|
426
|
+
if @cache_enabled && !no_cache
|
|
412
427
|
key = cache_key(sql + ":ONE", params)
|
|
413
428
|
cached = cache_get(key)
|
|
414
429
|
if cached
|
|
@@ -422,7 +437,7 @@ module Tina4
|
|
|
422
437
|
return value
|
|
423
438
|
end
|
|
424
439
|
|
|
425
|
-
result = fetch(sql, params, limit: 1)
|
|
440
|
+
result = fetch(sql, params, limit: 1, no_cache: no_cache)
|
|
426
441
|
result.first
|
|
427
442
|
end
|
|
428
443
|
|
data/lib/tina4/response_cache.rb
CHANGED
|
@@ -86,6 +86,7 @@ module Tina4
|
|
|
86
86
|
if hit
|
|
87
87
|
if response.respond_to?(:call)
|
|
88
88
|
new_response = response.call(hit.body, hit.status_code, hit.content_type)
|
|
89
|
+
set_cache_headers(new_response, "HIT", remaining_ttl(hit.expires_at))
|
|
89
90
|
return [request, new_response]
|
|
90
91
|
end
|
|
91
92
|
end
|
|
@@ -106,16 +107,17 @@ module Tina4
|
|
|
106
107
|
def after_cache(request, response)
|
|
107
108
|
return [request, response] unless enabled?
|
|
108
109
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
110
|
+
# Read the tags using the SAME mechanism before_cache wrote them with.
|
|
111
|
+
# before_cache keys the write on respond_to?(:[]=), so read the same way:
|
|
112
|
+
# a Tina4::Request responds to #[] (read-only param lookup) but NOT #[]=,
|
|
113
|
+
# so the tags live on instance variables, not the param hash.
|
|
114
|
+
if request.respond_to?(:[]=)
|
|
115
|
+
method = request[:_cache_method]
|
|
116
|
+
url = request[:_cache_url]
|
|
117
|
+
else
|
|
118
|
+
method = request.instance_variable_get(:@_cache_method)
|
|
119
|
+
url = request.instance_variable_get(:@_cache_url)
|
|
120
|
+
end
|
|
119
121
|
return [request, response] if method.nil? || url.nil?
|
|
120
122
|
|
|
121
123
|
status = if response.respond_to?(:status_code)
|
|
@@ -137,6 +139,9 @@ module Tina4
|
|
|
137
139
|
end
|
|
138
140
|
|
|
139
141
|
internal_store(method, url, status.to_i, content_type.to_s, body)
|
|
142
|
+
# The handler ran (cache miss) — annotate the response so clients can
|
|
143
|
+
# see this was a fresh response and how long it will be cached.
|
|
144
|
+
set_cache_headers(response, "MISS", @ttl)
|
|
140
145
|
[request, response]
|
|
141
146
|
end
|
|
142
147
|
|
|
@@ -279,6 +284,26 @@ module Tina4
|
|
|
279
284
|
"#{method}:#{url}"
|
|
280
285
|
end
|
|
281
286
|
|
|
287
|
+
# Stamp X-Cache / X-Cache-TTL on a response. `state` is "HIT" or "MISS";
|
|
288
|
+
# `ttl` is the remaining (HIT) or configured (MISS) TTL in seconds.
|
|
289
|
+
# Parity with Python/PHP/Node ResponseCache, which set the same two
|
|
290
|
+
# headers (no Cache-Control). No-op for responses that don't carry a
|
|
291
|
+
# mutable headers hash (e.g. test doubles).
|
|
292
|
+
def set_cache_headers(response, state, ttl)
|
|
293
|
+
return unless response.respond_to?(:headers) && response.headers.is_a?(Hash)
|
|
294
|
+
|
|
295
|
+
response.headers["X-Cache"] = state
|
|
296
|
+
response.headers["X-Cache-TTL"] = ttl.to_i.to_s
|
|
297
|
+
end
|
|
298
|
+
|
|
299
|
+
# Remaining whole seconds until `expires_at` (a monotonic-ish Time.now.to_f
|
|
300
|
+
# epoch), floored at 0 so an entry on the cusp of expiry never reports a
|
|
301
|
+
# negative TTL.
|
|
302
|
+
def remaining_ttl(expires_at)
|
|
303
|
+
remaining = (expires_at || 0) - Time.now.to_f
|
|
304
|
+
remaining.positive? ? remaining : 0
|
|
305
|
+
end
|
|
306
|
+
|
|
282
307
|
# Internal: retrieve a cached response. Used by middleware hooks only.
|
|
283
308
|
def internal_lookup(method, url)
|
|
284
309
|
return nil unless enabled?
|
data/lib/tina4/version.rb
CHANGED