sequel-privacy 0.7.1 → 0.7.2
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/CHANGELOG.md +6 -0
- data/lib/sequel/privacy/cache.rb +8 -38
- data/lib/sequel/privacy/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: 3a775f6a706825d2606e667f2b83076f00bed29b079e18581be62a6452bbff32
|
|
4
|
+
data.tar.gz: 538b8ca6f3eb9c748a2697dab1a0d9f5b013c2a0cabaa4f06702513def743bd9
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8c1e2f5aad69229373e401207e4e3aa664f8c9f8a5e615d147208c24690dbe32155647a8d7e6dd3a81543e8f838dc1b449a993be4a2d24511c11418cddc94bc2
|
|
7
|
+
data.tar.gz: f5397fe792ad89555aed6e81bb40be6ced0cfdc0e88ebd9c20e09c6466351498dc83293a6a5a2f41dd86d978721ad702ca8f8e87e4e9d999bc970b21e6e278d7
|
data/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,12 @@
|
|
|
3
3
|
|
|
4
4
|
## [Unreleased]
|
|
5
5
|
|
|
6
|
+
## [0.7.2] – 2026-09-21
|
|
7
|
+
|
|
8
|
+
- Reduced the overhead of operation-scoped cache access.
|
|
9
|
+
|
|
10
|
+
## [0.7.1] – 2026-09-21
|
|
11
|
+
|
|
6
12
|
- Added `Sequel::Privacy.with_cache_scope` for nested, exception-safe policy
|
|
7
13
|
caches isolated between concurrent threads and fibers.
|
|
8
14
|
|
data/lib/sequel/privacy/cache.rb
CHANGED
|
@@ -4,31 +4,6 @@
|
|
|
4
4
|
module Sequel
|
|
5
5
|
# Privacy enforcement and operation-scoped policy caching.
|
|
6
6
|
module Privacy
|
|
7
|
-
# One policy cache scope. Kept separate from ViewerContext because a
|
|
8
|
-
# long-lived context may serve many independent operations.
|
|
9
|
-
class CacheScope
|
|
10
|
-
extend T::Sig
|
|
11
|
-
|
|
12
|
-
sig { returns(T::Hash[Integer, Symbol]) }
|
|
13
|
-
attr_reader :cache
|
|
14
|
-
|
|
15
|
-
sig { returns(T::Hash[Integer, Integer]) }
|
|
16
|
-
attr_reader :single_matches
|
|
17
|
-
|
|
18
|
-
sig { void }
|
|
19
|
-
def initialize
|
|
20
|
-
@cache = T.let({}, T::Hash[Integer, Symbol])
|
|
21
|
-
@single_matches = T.let({}, T::Hash[Integer, Integer])
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
sig { void }
|
|
25
|
-
def clear!
|
|
26
|
-
@cache = {}
|
|
27
|
-
@single_matches = {}
|
|
28
|
-
end
|
|
29
|
-
end
|
|
30
|
-
private_constant :CacheScope
|
|
31
|
-
|
|
32
7
|
# In-memory cache for policy evaluation results. Concurrent applications
|
|
33
8
|
# should wrap each independent operation in with_cache_scope.
|
|
34
9
|
class << self
|
|
@@ -44,7 +19,7 @@ module Sequel
|
|
|
44
19
|
end
|
|
45
20
|
def with_cache_scope(&block)
|
|
46
21
|
previous = Thread.current[CACHE_SCOPE_KEY]
|
|
47
|
-
Thread.current[CACHE_SCOPE_KEY] =
|
|
22
|
+
Thread.current[CACHE_SCOPE_KEY] = [{}, {}]
|
|
48
23
|
block.()
|
|
49
24
|
ensure
|
|
50
25
|
Thread.current[CACHE_SCOPE_KEY] = previous
|
|
@@ -52,33 +27,28 @@ module Sequel
|
|
|
52
27
|
|
|
53
28
|
sig { returns(T::Hash[Integer, Symbol]) }
|
|
54
29
|
def cache
|
|
55
|
-
|
|
30
|
+
scope = Thread.current[CACHE_SCOPE_KEY]
|
|
31
|
+
scope ? scope[0] : (@cache ||= T.let({}, T.nilable(T::Hash[Integer, Symbol])))
|
|
56
32
|
end
|
|
57
33
|
|
|
58
34
|
# Tracks single-match optimization state.
|
|
59
35
|
# Key: [policy, actor, viewer_context].hash → Value: subject.hash
|
|
60
36
|
sig { returns(T::Hash[Integer, Integer]) }
|
|
61
37
|
def single_matches
|
|
62
|
-
|
|
63
|
-
|
|
38
|
+
scope = Thread.current[CACHE_SCOPE_KEY]
|
|
39
|
+
scope ? scope[1] : (@single_matches ||= T.let({}, T.nilable(T::Hash[Integer, Integer])))
|
|
64
40
|
end
|
|
65
41
|
|
|
66
42
|
sig { void }
|
|
67
43
|
def clear_cache!
|
|
68
|
-
if (scope =
|
|
69
|
-
scope
|
|
44
|
+
if (scope = Thread.current[CACHE_SCOPE_KEY])
|
|
45
|
+
scope[0] = {}
|
|
46
|
+
scope[1] = {}
|
|
70
47
|
else
|
|
71
48
|
@cache = {}
|
|
72
49
|
@single_matches = {}
|
|
73
50
|
end
|
|
74
51
|
end
|
|
75
|
-
|
|
76
|
-
private
|
|
77
|
-
|
|
78
|
-
sig { returns(T.nilable(CacheScope)) }
|
|
79
|
-
def active_cache_scope
|
|
80
|
-
T.cast(Thread.current[CACHE_SCOPE_KEY], T.nilable(CacheScope))
|
|
81
|
-
end
|
|
82
52
|
end
|
|
83
53
|
end
|
|
84
54
|
end
|