typed_cache 0.2.0 → 0.3.1

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.
Files changed (62) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/README.md +34 -12
  4. data/examples.md +51 -17
  5. data/lib/typed_cache/backends/active_support.rb +54 -9
  6. data/lib/typed_cache/backends/memory.rb +7 -8
  7. data/lib/typed_cache/cache_key.rb +9 -1
  8. data/lib/typed_cache/cache_ref.rb +16 -16
  9. data/lib/typed_cache/decorator.rb +9 -1
  10. data/lib/typed_cache/decorators/instrumented.rb +21 -8
  11. data/lib/typed_cache/either.rb +22 -0
  12. data/lib/typed_cache/instrumenter.rb +6 -6
  13. data/lib/typed_cache/instrumenters/mixins/namespaced_singleton.rb +3 -0
  14. data/lib/typed_cache/instrumenters.rb +2 -1
  15. data/lib/typed_cache/maybe.rb +18 -0
  16. data/lib/typed_cache/namespace.rb +33 -6
  17. data/lib/typed_cache/railtie.rb +15 -0
  18. data/lib/typed_cache/snapshot.rb +18 -10
  19. data/lib/typed_cache/store.rb +51 -19
  20. data/lib/typed_cache/version.rb +1 -1
  21. data/lib/typed_cache.rb +4 -0
  22. data/rbi/typed_cache/backend.rbi +9 -0
  23. data/rbi/typed_cache/backends/active_support.rbi +13 -0
  24. data/rbi/typed_cache/backends/memory.rbi +13 -0
  25. data/rbi/typed_cache/backends.rbi +19 -0
  26. data/rbi/typed_cache/cache_builder.rbi +23 -0
  27. data/rbi/typed_cache/cache_key.rbi +16 -0
  28. data/rbi/typed_cache/cache_ref.rbi +56 -0
  29. data/rbi/typed_cache/decorator.rbi +67 -0
  30. data/rbi/typed_cache/decorators/instrumented.rbi +13 -0
  31. data/rbi/typed_cache/decorators.rbi +19 -0
  32. data/rbi/typed_cache/either.rbi +122 -0
  33. data/rbi/typed_cache/errors.rbi +20 -0
  34. data/rbi/typed_cache/instrumenter.rbi +45 -0
  35. data/rbi/typed_cache/instrumenters/mixins/namedspaced_singleton.rbi +33 -0
  36. data/rbi/typed_cache/instrumenters.rbi +19 -0
  37. data/rbi/typed_cache/maybe.rbi +108 -0
  38. data/rbi/typed_cache/namespace.rbi +30 -0
  39. data/rbi/typed_cache/snapshot.rbi +54 -0
  40. data/rbi/typed_cache/store.rbi +71 -0
  41. data/rbi/typed_cache/version.rbi +5 -0
  42. data/rbi/typed_cache.rbi +49 -0
  43. data/sig/generated/typed_cache/backends/active_support.rbs +14 -2
  44. data/sig/generated/typed_cache/backends/memory.rbs +2 -2
  45. data/sig/generated/typed_cache/cache_key.rbs +5 -0
  46. data/sig/generated/typed_cache/cache_ref.rbs +4 -4
  47. data/sig/generated/typed_cache/decorator.rbs +4 -0
  48. data/sig/generated/typed_cache/decorators/instrumented.rbs +4 -4
  49. data/sig/generated/typed_cache/either.rbs +24 -0
  50. data/sig/generated/typed_cache/instrumenter.rbs +5 -5
  51. data/sig/generated/typed_cache/instrumenters/mixins/namespaced_singleton.rbs +3 -0
  52. data/sig/generated/typed_cache/instrumenters.rbs +2 -0
  53. data/sig/generated/typed_cache/maybe.rbs +20 -0
  54. data/sig/generated/typed_cache/namespace.rbs +24 -3
  55. data/sig/generated/typed_cache/railtie.rbs +6 -0
  56. data/sig/generated/typed_cache/snapshot.rbs +12 -6
  57. data/sig/generated/typed_cache/store.rbs +23 -8
  58. data/sig/generated/typed_cache.rbs +2 -0
  59. data/typed_cache.gemspec +1 -1
  60. data.tar.gz.sig +0 -0
  61. metadata +26 -3
  62. metadata.gz.sig +0 -0
@@ -6,7 +6,7 @@ module TypedCache
6
6
  # @rbs! type event = Dry::Events::Event | ActiveSupport::Notifications::Event
7
7
 
8
8
  # @rbs [R](String, String, **untyped) { -> R } -> R
9
- def instrument(event_name, key, **payload)
9
+ def instrument(event_name, key, **payload, &)
10
10
  raise NotImplementedError, "#{self.class} must implement #instrument"
11
11
  end
12
12
 
@@ -20,21 +20,21 @@ module TypedCache
20
20
  config.namespace
21
21
  end
22
22
 
23
+ # @rbs () -> bool
24
+ def enabled? = config.enabled
25
+
26
+ private
27
+
23
28
  # @rbs (String, String, **untyped) -> Hash[Symbol, untyped]
24
29
  def build_payload(operation, key, **payload)
25
30
  { namespace:, key:, operation: }.merge(payload)
26
31
  end
27
32
 
28
- # @rbs () -> bool
29
- def enabled? = config.enabled
30
-
31
33
  # @rbs (String) -> String
32
34
  def event_name(operation)
33
35
  "#{namespace}.#{operation}"
34
36
  end
35
37
 
36
- private
37
-
38
38
  # @rbs () -> TypedCache::_TypedCacheInstrumentationConfig
39
39
  def config
40
40
  TypedCache.config.instrumentation
@@ -43,6 +43,9 @@ module TypedCache
43
43
  namespace_cache.get(namespace.to_s)
44
44
  end
45
45
 
46
+ # @rbs () -> void
47
+ def clear_namespace_cache = namespace_cache.clear
48
+
46
49
  # @rbs () -> Concurrent::Map[String, Class[Instrumenter & NamespacedSingleton]]
47
50
  def namespace_cache = @namespace_cache ||= Concurrent::Map.new # rubocop:disable ThreadSafety
48
51
  end
@@ -28,11 +28,12 @@ module TypedCache
28
28
  # @rbs () -> Registry[Symbol, Class[Instrumenter]]
29
29
  def registry = REGISTRY
30
30
 
31
+ # @rbs! def register: (Symbol, Class[Instrumenter]) -> void
31
32
  # @rbs! def resolve: (Symbol, **untyped) -> either[Error, Instrumenter]
32
33
  # @rbs! def available: () -> Array[Symbol]
33
34
  # @rbs! def registered?: (Symbol) -> Boolean
34
35
 
35
- def_delegators :registry, :resolve, :available, :registered?
36
+ def_delegators :registry, :resolve, :available, :registered?, :register
36
37
  end
37
38
  end
38
39
  end
@@ -33,6 +33,8 @@ module TypedCache
33
33
  # def nothing?: -> bool
34
34
  # def map: [T] () { (V) -> T } -> maybe[T]
35
35
  # def bind: [T] () { (V) -> maybe[T] } -> maybe[T]
36
+ # def value_or: [T] (T) -> T
37
+ # def value_or_raise!: -> V
36
38
  # alias flat_map bind
37
39
  # end
38
40
 
@@ -62,6 +64,14 @@ module TypedCache
62
64
  #: [T] () { (V) -> maybe[T] } -> maybe[T]
63
65
  def bind(&) = yield(value)
64
66
 
67
+ # @rbs override
68
+ #: [T] (T) -> T
69
+ def value_or(default) = value
70
+
71
+ # @rbs override
72
+ #: -> V
73
+ def value_or_raise! = value
74
+
65
75
  alias flat_map bind
66
76
 
67
77
  #: (Array[top]) -> ({ value: V })
@@ -88,5 +98,13 @@ module TypedCache
88
98
  #: [T] () { (V) -> maybe[T] } -> maybe[T]
89
99
  def bind(&) = self
90
100
  alias flat_map bind
101
+
102
+ # @rbs override
103
+ #: [T] (T) -> T
104
+ def value_or(default) = default
105
+
106
+ # @rbs override
107
+ #: -> V
108
+ def value_or_raise! = raise TypedCache::TypeError, 'Nothing has no value'
91
109
  end
92
110
  end
@@ -20,16 +20,17 @@ module TypedCache
20
20
  # Returns a new Namespace instance rooted at the given namespace string.
21
21
  #
22
22
  # @param namespace [String] the root namespace
23
+ # @param namespaces [Array<String>] additional namespaces to join
23
24
  # @return [Namespace] a new Namespace instance at the given root
24
25
  #
25
26
  # Example:
26
- # TypedCache::Namespace.at("users") # => #<TypedCache::Namespace namespace=users>
27
+ # TypedCache::Namespace.at("users", "sessions") # => #<TypedCache::Namespace namespace=users:sessions>
27
28
  #
28
29
  # The returned Namespace can be further nested or used to generate cache keys.
29
30
  #
30
- # @rbs (String) -> Namespace
31
- def at(namespace)
32
- root.nested(namespace)
31
+ # @rbs (String, *String) -> Namespace
32
+ def at(namespace, *namespaces)
33
+ root.join(namespace, *namespaces)
33
34
  end
34
35
 
35
36
  # Returns the root Namespace instance (with an empty namespace).
@@ -79,7 +80,26 @@ module TypedCache
79
80
  def nested(namespace, &key_factory)
80
81
  key_factory ||= @key_factory
81
82
 
82
- self.class.new("#{@namespace}:#{namespace}", &key_factory)
83
+ self.class.new([@namespace, namespace].join(delimiter), &key_factory)
84
+ end
85
+
86
+ # Creates a new namespace by joining the current namespace with the given namespaces.
87
+ #
88
+ # @param namespaces [Array<String>] the namespaces to join
89
+ # @param key_factory [Proc, nil] optional custom key factory for the joined namespace
90
+ # @return [Namespace] a new Namespace instance with the combined namespace
91
+ #
92
+ # Example:
93
+ # ns = Namespace.at("users")
94
+ # ns.join("sessions", "admin") # => #<TypedCache::Namespace namespace=users:sessions:admin>
95
+ #
96
+ # If no key_factory is provided, the parent's key factory is inherited.
97
+ #
98
+ # @rbs (*String) ?{ (Namespace, String) -> CacheKey } -> Namespace
99
+ def join(*namespaces, &key_factory)
100
+ key_factory ||= @key_factory
101
+
102
+ self.class.new([@namespace, *namespaces].join(delimiter), &key_factory)
83
103
  end
84
104
 
85
105
  # Returns the parent namespace by removing the last namespace segment.
@@ -96,7 +116,7 @@ module TypedCache
96
116
  def parent_namespace
97
117
  return self if @namespace.empty?
98
118
 
99
- case pathsep_idx = @namespace.rindex(':')
119
+ case pathsep_idx = @namespace.rindex(delimiter)
100
120
  when nil
101
121
  self.class.root
102
122
  else
@@ -158,5 +178,12 @@ module TypedCache
158
178
  end
159
179
 
160
180
  alias eql? ==
181
+
182
+ private
183
+
184
+ # @rbs (String) -> String
185
+ def delimiter
186
+ TypedCache.config.cache_delimiter
187
+ end
161
188
  end
162
189
  end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TypedCache
4
+ class Railtie < ::Rails::Railtie
5
+ config.to_prepare do
6
+ # Set the default instrumenter to Rails
7
+ ::TypedCache.configure do |config|
8
+ config.instrumentation.instrumenter = :rails
9
+ end
10
+
11
+ # Register the ActiveSupport backend
12
+ ::TypedCache.backends.register(:active_support, ::TypedCache::Instrumenters::ActiveSupport)
13
+ end
14
+ end
15
+ end
@@ -4,12 +4,14 @@ module TypedCache
4
4
  # Immutable snapshot of a cached value with metadata about its source and age
5
5
  # @rbs generic V
6
6
  class Snapshot
7
+ attr_reader :key #: CacheKey
7
8
  attr_reader :value #: V
8
9
  attr_reader :retrieved_at #: Time
9
10
  attr_reader :source #: Symbol
10
11
 
11
- #: (V, source: Symbol, retrieved_at: Time) -> void
12
- def initialize(value, source:, retrieved_at: Time.now)
12
+ #: (CacheKey, V, source: Symbol, retrieved_at: Time) -> void
13
+ def initialize(key, value, source:, retrieved_at: Time.now)
14
+ @key = key
13
15
  @value = value
14
16
  @retrieved_at = retrieved_at
15
17
  @source = source
@@ -43,29 +45,35 @@ module TypedCache
43
45
  #: [R] () { (V) -> R } -> Snapshot[R]
44
46
  def map(&block)
45
47
  new_value = yield(value)
46
- Snapshot.new(new_value, source: source, retrieved_at: retrieved_at)
48
+ Snapshot.new(key, new_value, source: source, retrieved_at: retrieved_at)
47
49
  end
48
50
 
49
51
  # Bind over the value with Either error handling
50
52
  #: [R] () { (V) -> either[Error, R] } -> either[Error, Snapshot[R]]
51
53
  def bind(&block)
52
54
  result = yield(value)
53
- result.map { |new_value| Snapshot.new(new_value, source: source, retrieved_at: retrieved_at) }
55
+ result.map { |new_value| Snapshot.new(key, new_value, source: source, retrieved_at: retrieved_at) }
54
56
  end
55
57
 
56
58
  alias flat_map bind
57
59
 
58
60
  class << self
61
+ # Creates a snapshot for a cached value
62
+ #: [V] (CacheKey, V) -> Snapshot[V]
63
+ def cached(key, value)
64
+ new(key, value, source: :cache)
65
+ end
66
+
59
67
  # Creates a snapshot for a computed value
60
- #: [V] (V) -> Snapshot[V]
61
- def computed(value)
62
- new(value, source: :computed)
68
+ #: [V] (CacheKey, V) -> Snapshot[V]
69
+ def computed(key, value)
70
+ new(key, value, source: :computed)
63
71
  end
64
72
 
65
73
  # Creates a snapshot for an updated value
66
- #: [V] (V) -> Snapshot[V]
67
- def updated(value)
68
- new(value, source: :updated)
74
+ #: [V] (CacheKey, V) -> Snapshot[V]
75
+ def updated(key, value)
76
+ new(key, value, source: :updated)
69
77
  end
70
78
  end
71
79
  end
@@ -17,13 +17,16 @@ module TypedCache
17
17
 
18
18
  # @rbs!
19
19
  # interface _Store[V]
20
- # def get: (cache_key) -> either[Error, Snapshot[V]]
20
+ # def read: (cache_key) -> either[Error, Snapshot[V]]
21
+ # def read_all: (Array[cache_key]) -> either[Error, Array[Snapshot[V]]]
21
22
  # def ref: (cache_key) -> CacheRef[V]
22
- # def set: (cache_key, V) -> either[Error, Snapshot[V]]
23
+ # def write: (cache_key, V) -> either[Error, Snapshot[V]]
24
+ # def write_all: (Hash[cache_key, V]) -> either[Error, Array[Snapshot[V]]]
23
25
  # def delete: (cache_key) -> either[Error, Snapshot[V]]
24
26
  # def key?: (cache_key) -> bool
25
27
  # def clear: () -> maybe[Error]
26
- # def fetch: (cache_key) { () -> V } -> either[Error, Snapshot[V]]
28
+ # def fetch: (cache_key) { () -> V? } -> either[Error, Snapshot[maybe[V]]]
29
+ # def fetch_all: (Array[cache_key]) { (CacheKey) -> V? } -> either[Error, Array[Snapshot[V]]]
27
30
  # def namespace: () -> Namespace
28
31
  # def with_namespace: (Namespace) -> Store[V]
29
32
  # def store_type: () -> String
@@ -42,9 +45,18 @@ module TypedCache
42
45
  end
43
46
 
44
47
  # Retrieves a value from the cache
45
- # @rbs (cache_key) -> either[Error, Snapshot[V]]
46
- def get(key)
47
- Either.left(NotImplementedError.new("#{self.class} must implement #get"))
48
+ # @rbs (cache_key, **top) -> either[Error, Snapshot[V]]
49
+ def read(key, **kwargs)
50
+ Either.left(NotImplementedError.new("#{self.class} must implement #read"))
51
+ end
52
+
53
+ # @rbs (Array[cache_key], **top) -> either[Error, Hash[cache_key, Snapshot[V]]]
54
+ def read_all(keys, **kwargs)
55
+ keys.map { |key| read(key, **kwargs) }.reduce(Either.right({})) do |acc, result|
56
+ acc.bind do |values|
57
+ result.map { |value| values.merge(value.key => value) }
58
+ end
59
+ end
48
60
  end
49
61
 
50
62
  # Retrieves a cache reference for a key
@@ -54,9 +66,18 @@ module TypedCache
54
66
  end
55
67
 
56
68
  # Stores a value in the cache
57
- # @rbs (cache_key, V) -> either[Error, Snapshot[V]]
58
- def set(key, value)
59
- Either.left(NotImplementedError.new("#{self.class} must implement #set"))
69
+ # @rbs (cache_key, V, **top) -> either[Error, Snapshot[V]]
70
+ def write(key, value, **kwargs)
71
+ Either.left(NotImplementedError.new("#{self.class} must implement #write"))
72
+ end
73
+
74
+ # @rbs (Hash[cache_key, V], **top) -> either[Error, Hash[cache_key, Snapshot[V]]]
75
+ def write_all(values, **kwargs)
76
+ values.map { |key, value| write(key, value, **kwargs) }.reduce(Either.right({})) do |acc, result|
77
+ acc.bind do |values|
78
+ result.map { |value| values.merge(value.key => value) }
79
+ end
80
+ end
60
81
  end
61
82
 
62
83
  # Removes a value from the cache, returning the removed value
@@ -78,26 +99,36 @@ module TypedCache
78
99
  end
79
100
 
80
101
  # Fetches a value from cache, computing and storing it if not found
81
- # This is an atomic operation that combines get and set
82
- # @rbs (cache_key) { () -> V } -> either[Error, Snapshot[V]]
83
- def fetch(key, &block)
84
- # Default implementation using get/set pattern
85
- get_result = get(key)
86
- return get_result if get_result.right?
102
+ # This is an atomic operation that combines read and write
103
+ # @rbs (cache_key, **top) { () -> V } -> either[Error, Snapshot[V]]
104
+ def fetch(key, **kwargs, &block)
105
+ # Default implementation using read/write pattern
106
+ read_result = read(key)
107
+ return read_result if read_result.right?
87
108
 
88
109
  # Only proceed if it's a cache miss
89
- return get_result unless get_result.error.is_a?(CacheMissError)
110
+ return read_result unless read_result.error.is_a?(CacheMissError)
90
111
 
91
112
  # Compute and store new value
92
113
  begin
93
114
  computed_value = yield
94
- set(key, computed_value)
95
- Either.right(Snapshot.computed(computed_value))
115
+ write(key, computed_value, **kwargs)
116
+ Either.right(Snapshot.computed(key, computed_value))
96
117
  rescue => e
97
118
  Either.left(StoreError.new(:fetch, key, "Failed to compute value for key '#{key}': #{e.message}", e))
98
119
  end
99
120
  end
100
121
 
122
+ # @rbs (Array[cache_key], **top) { (CacheKey) -> V } -> either[Error, Array[Snapshot[V]]]
123
+ def fetch_all(keys, **kwargs, &block)
124
+ keys = keys.map { |key| namespaced_key(key) }
125
+ keys.reduce(Either.right([])) do |acc, key|
126
+ acc.bind do |values|
127
+ fetch(key. **kwargs) { yield(key) }.map { |value| values + [value] }
128
+ end
129
+ end
130
+ end
131
+
101
132
  # @rbs () -> Instrumenter
102
133
  def instrumenter = Instrumenters::Null.instance
103
134
 
@@ -109,11 +140,12 @@ module TypedCache
109
140
 
110
141
  # Accepts a String segment or a fully-formed Namespace and returns a cloned
111
142
  # store scoped to that namespace.
112
- # @rbs (Namespace | String) -> Store[V]
143
+ #: (Namespace | String | Array[String]) -> Store[V]
113
144
  def with_namespace(ns)
114
145
  new_namespace =
115
146
  case ns
116
147
  when Namespace then ns
148
+ when Array then namespace.join(*ns)
117
149
  else
118
150
  # treat as nested segment under the current namespace
119
151
  namespace.nested(ns.to_s)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module TypedCache
4
- VERSION = '0.2.0'
4
+ VERSION = '0.3.1'
5
5
  end
data/lib/typed_cache.rb CHANGED
@@ -39,6 +39,7 @@ module TypedCache
39
39
  # @rbs!
40
40
  # interface _TypedCacheConfig
41
41
  # def default_namespace: -> String
42
+ # def cache_delimiter: -> String
42
43
  # def instrumentation: -> _TypedCacheInstrumentationConfig
43
44
  # end
44
45
 
@@ -46,6 +47,7 @@ module TypedCache
46
47
 
47
48
  # Configuration
48
49
  setting :default_namespace, default: 'typed_cache'
50
+ setting :cache_delimiter, default: ':'
49
51
 
50
52
  setting :instrumentation do
51
53
  setting :enabled, default: false
@@ -72,3 +74,5 @@ module TypedCache
72
74
  def instrumenters = Instrumenters
73
75
  end
74
76
  end
77
+
78
+ require 'typed_cache/railtie' if defined?(Rails::Railtie)
@@ -0,0 +1,9 @@
1
+ # typed: strict
2
+
3
+ module TypedCache
4
+ module Backend
5
+ extend T::Generic
6
+ include ::TypedCache::Store
7
+ CachedType = type_member
8
+ end
9
+ end
@@ -0,0 +1,13 @@
1
+ # typed: strict
2
+
3
+ module TypedCache
4
+ module Backends
5
+ module ActiveSupport
6
+ extend T::Generic
7
+
8
+ include ::TypedCache::Backend
9
+
10
+ CachedType = type_member
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ # typed: strict
2
+
3
+ module TypedCache
4
+ module Backends
5
+ module Memory
6
+ extend T::Generic
7
+
8
+ include ::TypedCache::Backend
9
+
10
+ CachedType = type_member
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,19 @@
1
+ # typed: strict
2
+
3
+ module TypedCache
4
+ module Backends
5
+ class << self
6
+ sig { params(name: Symbol, klass: T::Class[::TypedCache::Backend[T.anything]]).returns(T.self_type) }
7
+ def register(name, klass); end
8
+
9
+ sig { params(name: Symbol, args: T::Array[T.anything], options: T::Hash[Symbol, T.anything]).returns(T.self_type) }
10
+ def resolve(name, *args, **options); end
11
+
12
+ sig { returns(T::Array[T::Class[::TypedCache::Backend[T.anything]]]) }
13
+ def available; end
14
+
15
+ sig { params(name: Symbol).returns(T::Boolean) }
16
+ def registered?(name); end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,23 @@
1
+ # typed: strict
2
+
3
+ module TypedCache
4
+ class CacheBuilder
5
+ Error = T.type_alias { TypedCache::Error }
6
+ Config = T.type_alias { ::TypedCache::Private::Configuration }
7
+ InstrumenterSource = T.type_alias { T.any(Symbol, ::TypedCache::Instrumenter) }
8
+
9
+ private_constant :Config, :Error, :InstrumenterSource
10
+
11
+ sig { params(namespace: ::TypedCache::Namespace).returns(::TypedCache::Either[Error, ::TypedCache::Store[T.anything]]) }
12
+ def build(namespace = T.unsafe(nil)); end
13
+
14
+ sig { params(name: Symbol, args: T.untyped, options: T::Hash[Symbol, T.anything]).returns(T.self_type) }
15
+ def with_backend(name, *args, **options); end
16
+
17
+ sig { params(name: Symbol, options: T::Hash[Symbol, T.anything]).returns(T.self_type) }
18
+ def with_decorator(name, **options); end
19
+
20
+ sig { params(source: InstrumenterSource).returns(T.self_type) }
21
+ def with_instrumentation(source = T.unsafe(nil)); end
22
+ end
23
+ end
@@ -0,0 +1,16 @@
1
+ # typed: strict
2
+
3
+ module TypedCache
4
+ class CacheKey
5
+ sealed!
6
+
7
+ sig { returns(::TypedCache::Namespace) }
8
+ attr_reader :namespace
9
+
10
+ sig { returns(String) }
11
+ attr_reader :key
12
+
13
+ sig { returns(String) }
14
+ def to_s; end
15
+ end
16
+ end
@@ -0,0 +1,56 @@
1
+ # typed: strict
2
+
3
+ module TypedCache
4
+ class CacheRef
5
+ extend T::Generic
6
+
7
+ sealed!
8
+
9
+ RefType = type_member
10
+
11
+ sig { returns(::TypedCache::Either[Error, ::TypedCache::Snapshot[RefType]]) }
12
+ def read; end
13
+
14
+ sig { params(value: RefType).returns(::TypedCache::Either[Error, ::TypedCache::Snapshot[RefType]]) }
15
+ def write(value); end
16
+
17
+ sig { returns(::TypedCache::Either[Error, ::TypedCache::Snapshot[RefType]]) }
18
+ def delete; end
19
+
20
+ sig { params(block: T.proc.params(value: RefType).returns(RefType)).returns(::TypedCache::Either[Error, ::TypedCache::Snapshot[RefType]]) }
21
+ def fetch(&block); end
22
+
23
+ sig { returns(T::Boolean) }
24
+ def present?; end
25
+
26
+ sig { returns(T::Boolean) }
27
+ def empty?; end
28
+
29
+ sig { params(block: T.proc.params(value: RefType).returns(RefType)).returns(::TypedCache::Either[Error, ::TypedCache::Snapshot[RefType]]) }
30
+ def update(&block); end
31
+
32
+ sig { params(default: RefType).returns(RefType) }
33
+ def value_or(default); end
34
+
35
+ sig { returns(::TypedCache::Maybe[RefType]) }
36
+ def value_maybe; end
37
+
38
+ sig { params(block: T.proc.params(value: RefType).returns(RefType)).returns(::TypedCache::Either[Error, ::TypedCache::Snapshot[RefType]]) }
39
+ def compute_if_absent(&block); end
40
+
41
+ sig { params(new_key: String).returns(::TypedCache::CacheRef[RefType]) }
42
+ def with_key(new_key); end
43
+
44
+ sig { params(scope_key: String).returns(::TypedCache::CacheRef[RefType]) }
45
+ def scope(scope_key); end
46
+
47
+ sig { type_parameters(:T).params(left_fn: T.proc.params(value: Error).returns(T.type_parameter(:T)), right_fn: T.proc.params(value: ::TypedCache::Snapshot[RefType]).returns(T.type_parameter(:T))).returns(T.type_parameter(:T)) }
48
+ def fold(left_fn, right_fn); end
49
+
50
+ sig { type_parameters(:T).params(block: T.proc.params(value: ::TypedCache::Snapshot[RefType]).returns(T.type_parameter(:T))).returns(::TypedCache::Either[Error, T.type_parameter(:T)]) }
51
+ def with_snapshot(&block); end
52
+
53
+ sig { type_parameters(:T).params(block: T.proc.params(value: RefType).returns(T.type_parameter(:T))).returns(::TypedCache::Either[Error, T.type_parameter(:T)]) }
54
+ def with(&block); end
55
+ end
56
+ end
@@ -0,0 +1,67 @@
1
+ # typed: strict
2
+
3
+ module TypedCache
4
+ module Decorator
5
+ extend T::Generic
6
+
7
+ include ::TypedCache::Store
8
+
9
+ abstract!
10
+
11
+ CachedType = type_member
12
+
13
+ sig { params(store: ::TypedCache::Store[CachedType]).void }
14
+ def initialize(store); end
15
+
16
+ sig { overridable.returns(::TypedCache::Store[CachedType]) }
17
+ def store; end
18
+
19
+ sig(:final) { params(key: T.any(String, ::TypedCache::CacheKey)).returns(::TypedCache::CacheRef[CachedType]) }
20
+ def ref(key); end
21
+
22
+ sig { overridable.params(key: T.any(String, ::TypedCache::CacheKey)).returns(::TypedCache::Either[Error, ::TypedCache::Snapshot[CachedType]]) }
23
+ def read(key); end
24
+
25
+ sig { overridable.params(key: T.any(String, ::TypedCache::CacheKey), value: CachedType).returns(::TypedCache::Either[Error, ::TypedCache::Snapshot[CachedType]]) }
26
+ def write(key, value); end
27
+
28
+ sig { overridable.params(key: T.any(String, ::TypedCache::CacheKey)).returns(::TypedCache::Either[Error, ::TypedCache::Snapshot[CachedType]]) }
29
+ def delete(key); end
30
+
31
+ sig { overridable.params(key: T.any(String, ::TypedCache::CacheKey)).returns(T::Boolean) }
32
+ def key?(key); end
33
+
34
+ sig { overridable.params(key: T.any(String, ::TypedCache::CacheKey), block: T.proc.params(value: CachedType).returns(CachedType)).returns(::TypedCache::Either[Error, ::TypedCache::Snapshot[CachedType]]) }
35
+ def fetch(key, &block); end
36
+
37
+ sig { overridable.params(keys: T::Array[T.any(String, ::TypedCache::CacheKey)]).returns(::TypedCache::Either[Error, T::Array[::TypedCache::Snapshot[CachedType]]]) }
38
+ def read_all(keys); end
39
+
40
+ sig { overridable.params(keys: T::Array[T.any(String, ::TypedCache::CacheKey)], block: T.proc.params(key: T.any(String, ::TypedCache::CacheKey)).returns(CachedType)).returns(::TypedCache::Either[Error, T::Array[::TypedCache::Snapshot[CachedType]]]) }
41
+ def fetch_all(keys, &block); end
42
+
43
+ sig { overridable.params(values: T::Hash[T.any(String, ::TypedCache::CacheKey), CachedType]).returns(::TypedCache::Either[Error, T::Array[::TypedCache::Snapshot[CachedType]]]) }
44
+ def write_all(values); end
45
+
46
+ sig { overridable.void }
47
+ def clear; end
48
+
49
+ sig(:final) { returns(::TypedCache::Namespace) }
50
+ def namespace; end
51
+
52
+ sig(:final) { params(namespace: ::TypedCache::Namespace).returns(::TypedCache::Store[CachedType]) }
53
+ def with_namespace(namespace); end
54
+
55
+ sig { abstract.returns(String) }
56
+ def store_type; end
57
+
58
+ sig { overridable.params(other: T.self_type).void }
59
+ def initialize_copy(other); end
60
+
61
+ sig(:final) { params(key: T.any(String, ::TypedCache::CacheKey)).returns(::TypedCache::CacheKey) }
62
+ def namespaced_key(key); end
63
+
64
+ sig { overridable.returns(::TypedCache::Instrumenter) }
65
+ def instrumenter; end
66
+ end
67
+ end
@@ -0,0 +1,13 @@
1
+ # typed: strict
2
+
3
+ module TypedCache
4
+ module Decorators
5
+ module Instrumented
6
+ extend T::Generic
7
+
8
+ include ::TypedCache::Decorator
9
+
10
+ CachedType = type_member
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,19 @@
1
+ # typed: strict
2
+
3
+ module TypedCache
4
+ module Decorators
5
+ class << self
6
+ sig { params(name: Symbol, klass: T::Class[::TypedCache::Decorator[T.anything]]).returns(T.self_type) }
7
+ def register(name, klass); end
8
+
9
+ sig { params(name: Symbol, args: T::Array[T.anything], options: T::Hash[Symbol, T.anything]).returns(T.self_type) }
10
+ def resolve(name, *args, **options); end
11
+
12
+ sig { returns(T::Array[T::Class[::TypedCache::Decorator[T.anything]]]) }
13
+ def available; end
14
+
15
+ sig { params(name: Symbol).returns(T::Boolean) }
16
+ def registered?(name); end
17
+ end
18
+ end
19
+ end