typed_cache 0.2.0 → 0.3.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.
Files changed (62) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/README.md +25 -3
  4. data/examples.md +36 -2
  5. data/lib/typed_cache/backends/active_support.rb +50 -5
  6. data/lib/typed_cache/backends/memory.rb +5 -5
  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 +47 -15
  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
@@ -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
@@ -43,8 +46,17 @@ module TypedCache
43
46
 
44
47
  # Retrieves a value from the cache
45
48
  # @rbs (cache_key) -> either[Error, Snapshot[V]]
46
- def get(key)
47
- Either.left(NotImplementedError.new("#{self.class} must implement #get"))
49
+ def read(key)
50
+ Either.left(NotImplementedError.new("#{self.class} must implement #read"))
51
+ end
52
+
53
+ # @rbs (Array[cache_key]) -> either[Error, Hash[cache_key, Snapshot[V]]]
54
+ def read_all(keys)
55
+ keys.map { |key| read(key) }.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
@@ -55,8 +67,17 @@ module TypedCache
55
67
 
56
68
  # Stores a value in the cache
57
69
  # @rbs (cache_key, V) -> either[Error, Snapshot[V]]
58
- def set(key, value)
59
- Either.left(NotImplementedError.new("#{self.class} must implement #set"))
70
+ def write(key, value)
71
+ Either.left(NotImplementedError.new("#{self.class} must implement #write"))
72
+ end
73
+
74
+ # @rbs (Hash[cache_key, V]) -> either[Error, Hash[cache_key, Snapshot[V]]]
75
+ def write_all(values)
76
+ values.map { |key, value| write(key, value) }.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
102
+ # This is an atomic operation that combines read and write
82
103
  # @rbs (cache_key) { () -> V } -> either[Error, Snapshot[V]]
83
104
  def fetch(key, &block)
84
- # Default implementation using get/set pattern
85
- get_result = get(key)
86
- return get_result if get_result.right?
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)
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]) { (CacheKey) -> V } -> either[Error, Array[Snapshot[V]]]
123
+ def fetch_all(keys, &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) { 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.0'
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
@@ -0,0 +1,122 @@
1
+ # typed: strict
2
+
3
+ module TypedCache
4
+ module Either
5
+ extend T::Generic
6
+ include Kernel
7
+
8
+ mixes_in_class_methods(T::Generic)
9
+
10
+ sealed!
11
+ interface!
12
+
13
+ L = type_member(:out)
14
+ R = type_member(:out)
15
+
16
+ interface!
17
+
18
+ sig { abstract.returns(T::Boolean) }
19
+ def left?; end
20
+
21
+ sig { abstract.returns(T::Boolean) }
22
+ def right?; end
23
+
24
+ sig { abstract.type_parameters(:T).params(block: T.proc.params(value: R).returns(T.type_parameter(:T))).returns(::TypedCache::Either[L, T.type_parameter(:T)]) }
25
+ def map(&block); end
26
+
27
+ sig { abstract.type_parameters(:T).params(block: T.proc.params(value: L).returns(T.type_parameter(:T))).returns(::TypedCache::Either[T.type_parameter(:T), R]) }
28
+ def map_left(&block); end
29
+
30
+ sig { abstract.type_parameters(:E, :R2).params(block: T.proc.params(value: R).returns(::TypedCache::Either[T.type_parameter(:E), T.type_parameter(:R2)])).returns(::TypedCache::Either[T.type_parameter(:E), T.type_parameter(:R2)]) }
31
+ def bind(&block); end
32
+
33
+ sig { abstract.type_parameters(:T).params(left_block: T.proc.params(value: L).returns(T.type_parameter(:T)), right_block: T.proc.params(value: R).returns(T.type_parameter(:T))).returns(T.type_parameter(:T)) }
34
+ def fold(left_block, right_block); end
35
+
36
+ sig { abstract.params(block: T.proc.params(value: L).void).returns(R) }
37
+ def right_or_else(&block); end
38
+
39
+ sig { abstract.returns(R) }
40
+ def right_or_raise!; end
41
+ end
42
+
43
+ class Left
44
+ sealed!
45
+
46
+ include ::TypedCache::Either
47
+ extend T::Generic
48
+
49
+ L = type_member(:out)
50
+ R = type_member(:out) { { fixed: T.noreturn } }
51
+
52
+ sig { override.returns(TrueClass) }
53
+ def left?; end
54
+
55
+ sig { override.returns(FalseClass) }
56
+ def right?; end
57
+
58
+ sig { override.type_parameters(:T).params(block: T.proc.params(value: R).returns(T.type_parameter(:T))).returns(T.self_type) }
59
+ def map(&block); end
60
+
61
+ sig { override.type_parameters(:T).params(block: T.proc.params(value: L).returns(T.type_parameter(:T))).returns(Left[T.type_parameter(:T)]) }
62
+ def map_left(&block); end
63
+
64
+ sig { override.type_parameters(:E, :R2).params(block: T.proc.params(value: R).returns(::TypedCache::Either[T.type_parameter(:E), T.type_parameter(:R2)])).returns(T.self_type) }
65
+ def bind(&block); end
66
+
67
+ sig { override.type_parameters(:T).params(left_block: T.proc.params(value: L).returns(T.type_parameter(:T)), right_block: T.proc.params(value: R).returns(T.type_parameter(:T))).returns(T.type_parameter(:T)) }
68
+ def fold(left_block, right_block); end
69
+
70
+ sig { returns(L) }
71
+ def value; end
72
+
73
+ sig { returns(L) }
74
+ def error; end
75
+
76
+ sig { params(block: T.proc.params(value: L).void).returns(R) }
77
+ def right_or_else(&block); end
78
+
79
+ sig { returns(T.noreturn) }
80
+ def right_or_raise!; end
81
+ end
82
+
83
+ class Right
84
+ sealed!
85
+
86
+ include ::TypedCache::Either
87
+ extend T::Generic
88
+
89
+ L = type_member(:out) { { fixed: T.noreturn } }
90
+ R = type_member(:out)
91
+
92
+ sig { override.returns(FalseClass) }
93
+ def left?; end
94
+
95
+ sig { override.returns(TrueClass) }
96
+ def right?; end
97
+
98
+ sig { override.type_parameters(:T).params(block: T.proc.params(value: R).returns(T.type_parameter(:T))).returns(Right[T.type_parameter(:T)]) }
99
+ def map(&block); end
100
+
101
+ sig { override.type_parameters(:T).params(block: T.proc.params(value: L).returns(T.type_parameter(:T))).returns(T.self_type) }
102
+ def map_left(&block); end
103
+
104
+ sig { override.type_parameters(:E, :R2).params(block: T.proc.params(value: R).returns(::TypedCache::Either[T.type_parameter(:E), T.type_parameter(:R2)])).returns(::TypedCache::Either[T.type_parameter(:E), T.type_parameter(:R2)]) }
105
+ def bind(&block); end
106
+
107
+ sig { override.type_parameters(:T).params(left_block: T.proc.params(value: L).returns(T.type_parameter(:T)), right_block: T.proc.params(value: R).returns(T.type_parameter(:T))).returns(T.type_parameter(:T)) }
108
+ def fold(left_block, right_block); end
109
+
110
+ sig { returns(R) }
111
+ def value; end
112
+
113
+ sig { returns(R) }
114
+ def result; end
115
+
116
+ sig { params(block: T.proc.params(value: T.anything).void).returns(R) }
117
+ def right_or_else(&block); end
118
+
119
+ sig { returns(R) }
120
+ def right_or_raise!; end
121
+ end
122
+ end