typed_cache 0.1.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 (52) hide show
  1. checksums.yaml +7 -0
  2. checksums.yaml.gz.sig +0 -0
  3. data/LICENSE +201 -0
  4. data/README.md +168 -0
  5. data/examples.md +190 -0
  6. data/lib/typed_cache/backend.rb +16 -0
  7. data/lib/typed_cache/backends/active_support.rb +113 -0
  8. data/lib/typed_cache/backends/memory.rb +166 -0
  9. data/lib/typed_cache/backends.rb +34 -0
  10. data/lib/typed_cache/cache_builder.rb +77 -0
  11. data/lib/typed_cache/cache_key.rb +45 -0
  12. data/lib/typed_cache/cache_ref.rb +155 -0
  13. data/lib/typed_cache/clock.rb +23 -0
  14. data/lib/typed_cache/decorator.rb +12 -0
  15. data/lib/typed_cache/decorators.rb +35 -0
  16. data/lib/typed_cache/either.rb +121 -0
  17. data/lib/typed_cache/errors.rb +64 -0
  18. data/lib/typed_cache/instrumentation.rb +112 -0
  19. data/lib/typed_cache/maybe.rb +92 -0
  20. data/lib/typed_cache/namespace.rb +162 -0
  21. data/lib/typed_cache/registry.rb +55 -0
  22. data/lib/typed_cache/snapshot.rb +72 -0
  23. data/lib/typed_cache/store/instrumented.rb +83 -0
  24. data/lib/typed_cache/store.rb +152 -0
  25. data/lib/typed_cache/version.rb +5 -0
  26. data/lib/typed_cache.rb +58 -0
  27. data/sig/generated/typed_cache/backend.rbs +17 -0
  28. data/sig/generated/typed_cache/backends/active_support.rbs +56 -0
  29. data/sig/generated/typed_cache/backends/memory.rbs +95 -0
  30. data/sig/generated/typed_cache/backends.rbs +21 -0
  31. data/sig/generated/typed_cache/cache_builder.rbs +37 -0
  32. data/sig/generated/typed_cache/cache_key.rbs +33 -0
  33. data/sig/generated/typed_cache/cache_ref.rbs +91 -0
  34. data/sig/generated/typed_cache/clock.rbs +15 -0
  35. data/sig/generated/typed_cache/decorator.rbs +14 -0
  36. data/sig/generated/typed_cache/decorators.rbs +25 -0
  37. data/sig/generated/typed_cache/either.rbs +106 -0
  38. data/sig/generated/typed_cache/errors.rbs +51 -0
  39. data/sig/generated/typed_cache/instrumentation.rbs +30 -0
  40. data/sig/generated/typed_cache/maybe.rbs +85 -0
  41. data/sig/generated/typed_cache/namespace.rbs +130 -0
  42. data/sig/generated/typed_cache/registry.rbs +25 -0
  43. data/sig/generated/typed_cache/snapshot.rbs +50 -0
  44. data/sig/generated/typed_cache/store/instrumented.rbs +37 -0
  45. data/sig/generated/typed_cache/store.rbs +104 -0
  46. data/sig/generated/typed_cache/version.rbs +5 -0
  47. data/sig/generated/typed_cache.rbs +34 -0
  48. data/sig/handwritten/gems/zeitwerk/2.7/zeitwerk.rbs +9 -0
  49. data/typed_cache.gemspec +42 -0
  50. data.tar.gz.sig +0 -0
  51. metadata +228 -0
  52. metadata.gz.sig +0 -0
@@ -0,0 +1,152 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TypedCache
4
+ # @rbs!
5
+ #
6
+
7
+ # Generic interface for type-safe cache storage implementations
8
+ # All stores are assumed to handle namespacing internally
9
+ #
10
+ # This interface follows the Command-Query Separation principle:
11
+ # - Commands (set, delete, clear) perform actions and may return results
12
+ # - Queries (get, key?, fetch) ask questions without side effects
13
+ #
14
+ # @rbs generic V
15
+ module Store
16
+ # @rbs! type cache_key = String | CacheKey
17
+
18
+ # @rbs!
19
+ # interface _Store[V]
20
+ # def get: (cache_key) -> either[Error, Snapshot[V]]
21
+ # def ref: (cache_key) -> CacheRef[V]
22
+ # def set: (cache_key, V) -> either[Error, Snapshot[V]]
23
+ # def delete: (cache_key) -> either[Error, Snapshot[V]]
24
+ # def key?: (cache_key) -> bool
25
+ # def clear: () -> maybe[Error]
26
+ # def fetch: (cache_key) { () -> V } -> either[Error, Snapshot[V]]
27
+ # def namespace: () -> Namespace
28
+ # def with_namespace: (Namespace) -> Store[V]
29
+ # def store_type: () -> String
30
+ # end
31
+ # include _Store[V]
32
+
33
+ # @rbs!
34
+ # interface _Decorator[V]
35
+ # def initialize: (Store[V]) -> void
36
+ # end
37
+
38
+ # @rbs (Store[V]) -> void
39
+ def initialize_copy(other)
40
+ super
41
+ @namespace = other.namespace
42
+ end
43
+
44
+ # 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
+ end
49
+
50
+ # Retrieves a cache reference for a key
51
+ # @rbs (cache_key) -> CacheRef[V]
52
+ def ref(key)
53
+ CacheRef.new(self, namespaced_key(key))
54
+ end
55
+
56
+ # 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"))
60
+ end
61
+
62
+ # Removes a value from the cache, returning the removed value
63
+ # @rbs (cache_key) -> either[Error, Snapshot[V]]
64
+ def delete(key)
65
+ Either.left(NotImplementedError.new("#{self.class} must implement #delete"))
66
+ end
67
+
68
+ # Checks if a key exists in the cache (query operation)
69
+ # @rbs (cache_key) -> bool
70
+ def key?(key)
71
+ false # Safe default - assume key doesn't exist
72
+ end
73
+
74
+ # Clears all values from the cache namespace (command operation)
75
+ # @rbs () -> maybe[Error]
76
+ def clear
77
+ Maybe.some(NotImplementedError.new("#{self.class} does not implement #clear"))
78
+ end
79
+
80
+ # 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?
87
+
88
+ # Only proceed if it's a cache miss
89
+ return get_result unless get_result.error.is_a?(CacheMissError)
90
+
91
+ # Compute and store new value
92
+ begin
93
+ computed_value = yield
94
+ set(key, computed_value)
95
+ Either.right(Snapshot.computed(computed_value))
96
+ rescue => e
97
+ Either.left(StoreError.new(:fetch, key, "Failed to compute value for key '#{key}': #{e.message}", e))
98
+ end
99
+ end
100
+
101
+ # Returns the namespace for this store (for instrumentation/debugging)
102
+ # @rbs () -> Namespace
103
+ def namespace
104
+ raise NotImplementedError, "#{self.class} must implement #namespace"
105
+ end
106
+
107
+ # Accepts a String segment or a fully-formed Namespace and returns a cloned
108
+ # store scoped to that namespace.
109
+ # @rbs (Namespace | String) -> Store[V]
110
+ def with_namespace(ns)
111
+ new_namespace =
112
+ case ns
113
+ when Namespace then ns
114
+ else
115
+ # treat as nested segment under the current namespace
116
+ namespace.nested(ns.to_s)
117
+ end
118
+
119
+ clone.tap { |store| store.namespace = new_namespace }
120
+ end
121
+
122
+ # Returns the store type identifier for instrumentation/debugging
123
+ # @rbs () -> String
124
+ def store_type
125
+ snake_case(self.class.name.split('::').last)
126
+ end
127
+
128
+ protected
129
+
130
+ attr_writer :namespace #: Namespace
131
+
132
+ private
133
+
134
+ #: (String) -> String
135
+ def snake_case(string)
136
+ string
137
+ .gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
138
+ .gsub(/([a-z\d])([A-Z])/, '\1_\2')
139
+ .tr('-', '_')
140
+ .downcase
141
+ end
142
+
143
+ #: (cache_key) -> CacheKey
144
+ def namespaced_key(key)
145
+ key.is_a?(CacheKey) ? key : CacheKey.new(namespace, key)
146
+ end
147
+ end
148
+
149
+ # @rbs! type backend[V] = Store::_Store[V]
150
+ # @rbs! type decorator[V] = backend[V] & Store::_Decorator[V]
151
+ # @rbs! type store[V] = backend[V] | decorator[V]
152
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TypedCache
4
+ VERSION = '0.1.1'
5
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'zeitwerk'
4
+ require 'dry-configurable'
5
+ require 'concurrent-ruby'
6
+
7
+ # Load core registry before Zeitwerk
8
+ require_relative 'typed_cache/registry'
9
+ require_relative 'typed_cache/errors'
10
+
11
+ Zeitwerk::Loader.for_gem.setup
12
+
13
+ module TypedCache
14
+ extend Dry::Configurable
15
+
16
+ # @rbs!
17
+ # interface _TypedCacheInstrumentationConfig
18
+ # def enabled: -> bool
19
+ # def namespace: -> String
20
+ # end
21
+
22
+ # @rbs!
23
+ # interface _TypedCacheConfig
24
+ # def default_namespace: -> String
25
+ # def instrumentation: -> _TypedCacheInstrumentationConfig
26
+ # end
27
+
28
+ # @rbs! type typed_cache_config = _TypedCacheConfig
29
+
30
+ # Configuration
31
+ setting :default_namespace, default: 'typed_cache'
32
+
33
+ setting :instrumentation do
34
+ setting :enabled, default: false
35
+ setting :namespace, default: 'typed_cache'
36
+ end
37
+
38
+ class << self
39
+ # Returns a CacheBuilder with the fluent interface
40
+ # @rbs [V] () -> CacheBuilder[V]
41
+ def builder
42
+ CacheBuilder.new(config, Backends, Decorators)
43
+ end
44
+
45
+ # @rbs! def config: -> _TypedCacheConfig
46
+
47
+ # @rbs () -> singleton(Instrumentation)
48
+ def instrumentation
49
+ Instrumentation
50
+ end
51
+
52
+ # @rbs () -> Registry[backend[untyped]]
53
+ def backends = Backends
54
+
55
+ # @rbs () -> Register[decorator[untyped]]
56
+ def decorators = Decorators
57
+ end
58
+ end
@@ -0,0 +1,17 @@
1
+ # Generated from lib/typed_cache/backend.rb with RBS::Inline
2
+
3
+ module TypedCache
4
+ # Marker mixin for concrete cache back-ends.
5
+ # A Backend *is* a Store, but the reverse is not necessarily true (decorators also
6
+ # include Store). By tagging back-ends with this module we can type-check and
7
+ # register them separately from decorators.
8
+ #
9
+ # Back-ends should *not* assume they wrap another store – they are the leaf nodes
10
+ # that actually persist data.
11
+ # @rbs generic V
12
+ module Backend[V]
13
+ include Store[V]
14
+
15
+ include Store::_Store[V]
16
+ end
17
+ end
@@ -0,0 +1,56 @@
1
+ # Generated from lib/typed_cache/backends/active_support.rb with RBS::Inline
2
+
3
+ module TypedCache
4
+ module Backends
5
+ # Adapter that wraps any ActiveSupport::Cache::Store to work with TypedCache
6
+ # @rbs generic V
7
+ class ActiveSupport[V]
8
+ include Backend[V]
9
+
10
+ attr_reader namespace: Namespace
11
+
12
+ attr_reader cache_store: ::ActiveSupport::Cache::Store
13
+
14
+ attr_reader default_options: Hash[Symbol, top]
15
+
16
+ # : (Namespace, ::ActiveSupport::Cache::Store, ?Hash[Symbol, top]) -> void
17
+ def initialize: (Namespace, ::ActiveSupport::Cache::Store, ?Hash[Symbol, top]) -> void
18
+
19
+ # @rbs override
20
+ # : (cache_key) -> either[Error, Snapshot[V]]
21
+ def get: ...
22
+
23
+ # @rbs override
24
+ # : (cache_key, V) -> either[Error, Snapshot[V]]
25
+ def set: ...
26
+
27
+ # @rbs override
28
+ # : (cache_key) -> either[Error, Snapshot[V]]
29
+ def delete: ...
30
+
31
+ # @rbs override
32
+ # : (cache_key) -> bool
33
+ def key?: ...
34
+
35
+ # @rbs override
36
+ # : -> maybe[Error]
37
+ def clear: ...
38
+
39
+ # @rbs override
40
+ # : -> String
41
+ def store_type: ...
42
+
43
+ # : (Hash[Symbol, top]) -> ActiveSupport[V]
44
+ def with_options: (Hash[Symbol, top]) -> ActiveSupport[V]
45
+
46
+ # : -> ::ActiveSupport::Cache::Store
47
+ def raw_cache: () -> ::ActiveSupport::Cache::Store
48
+
49
+ private
50
+
51
+ # Regex patterns that match keys for this namespace (with trailing colon)
52
+ # : -> Array[Regexp]
53
+ def namespace_prefix_patterns: () -> Array[Regexp]
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,95 @@
1
+ # Generated from lib/typed_cache/backends/memory.rb with RBS::Inline
2
+
3
+ module TypedCache
4
+ class MemoryStoreRegistry
5
+ include Singleton
6
+
7
+ extend Forwardable
8
+
9
+ # : -> void
10
+ def initialize: () -> void
11
+ end
12
+
13
+ module Backends
14
+ # A type-safe memory store implementation with built-in namespacing
15
+ # @rbs generic V
16
+ class Memory[V]
17
+ include Backend[V]
18
+
19
+ interface _HashLike[K, V]
20
+ def []: (K) -> V?
21
+
22
+ def []=: (K, V) -> V
23
+
24
+ def delete: (K) -> V?
25
+
26
+ def key?: (K) -> bool
27
+
28
+ def keys: () -> Array[K]
29
+ end
30
+
31
+ type hash_like[K, V] = _HashLike[K, V]
32
+
33
+ # @private
34
+ # @rbs generic V
35
+ class Entry[V] < Dry::Struct
36
+ attr_accessor expires_at: Time
37
+
38
+ attr_reader value: V
39
+
40
+ # @rbs (value: V, expires_in: Integer) -> Entry[V]
41
+ def self.expiring: (value: V, expires_in: Integer) -> Entry[V]
42
+
43
+ # @rbs () -> bool
44
+ def expired?: () -> bool
45
+ end
46
+
47
+ attr_reader namespace: Namespace
48
+
49
+ attr_reader ttl: Namespace
50
+
51
+ attr_reader backing_store: hash_like[CacheKey, Entry[V]]
52
+
53
+ # : (Namespace, shared: bool, ttl: Integer) -> void
54
+ def initialize: (Namespace, shared: bool, ttl: Integer) -> void
55
+
56
+ # @rbs override
57
+ # : (cache_key) -> either[Error, Snapshot[V]]
58
+ def get: ...
59
+
60
+ # @rbs override
61
+ # : (cache_key, V) -> either[Error, Snapshot[V]]
62
+ def set: ...
63
+
64
+ # @rbs override
65
+ # : (cache_key) -> either[Error, Snapshot[V]]
66
+ def delete: ...
67
+
68
+ # @rbs override
69
+ # : (cache_key) -> bool
70
+ def key?: ...
71
+
72
+ # @rbs override
73
+ # : -> maybe[Error]
74
+ def clear: ...
75
+
76
+ # @rbs override
77
+ # : -> String
78
+ def store_type: ...
79
+
80
+ # : -> Integer
81
+ def size: () -> Integer
82
+
83
+ # : -> Array[CacheKey]
84
+ def keys: () -> Array[CacheKey]
85
+
86
+ private
87
+
88
+ # : -> Hash[CacheKey, Entry[V]]
89
+ def namespaced_entries: () -> Hash[CacheKey, Entry[V]]
90
+
91
+ # : -> void
92
+ def purge_expired_keys: () -> void
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,21 @@
1
+ # Generated from lib/typed_cache/backends.rb with RBS::Inline
2
+
3
+ module TypedCache
4
+ module Backends
5
+ # Backend registry using composition
6
+ REGISTRY: untyped
7
+
8
+ extend Forwardable
9
+
10
+ # : -> Registry
11
+ def self.registry: () -> Registry
12
+
13
+ def resolve: (Symbol, *untyped, **untyped) -> either[Error, Store[untyped]]
14
+
15
+ def available: () -> Array[Symbol]
16
+
17
+ def register: (Symbol, Class) -> either[Error, void]
18
+
19
+ def registered?: (Symbol) -> bool
20
+ end
21
+ end
@@ -0,0 +1,37 @@
1
+ # Generated from lib/typed_cache/cache_builder.rb with RBS::Inline
2
+
3
+ module TypedCache
4
+ class CacheBuilder
5
+ type config = TypedCache::typed_cache_config
6
+
7
+ # @rbs (config, Registry[backend[untyped]], Registry[decorator[untyped]]) -> void
8
+ def initialize: (config, Registry[backend[untyped]], Registry[decorator[untyped]]) -> void
9
+
10
+ # Builds the cache - the only method that can fail
11
+ # @rbs (?Namespace) -> either[Error, Store[V]]
12
+ def build: (?Namespace) -> either[Error, Store[V]]
13
+
14
+ # Familiar Ruby fluent interface - always succeeds
15
+ # Invalid configurations are caught during build()
16
+ # @rbs (Symbol, *untyped, **untyped) -> self
17
+ def with_backend: (Symbol, *untyped, **untyped) -> self
18
+
19
+ # Adds an arbitrary decorator by registry key
20
+ # @rbs (Symbol) -> self
21
+ def with_decorator: (Symbol) -> self
22
+
23
+ # @rbs () -> self
24
+ def with_instrumentation: () -> self
25
+
26
+ private
27
+
28
+ # @rbs (Namespace) -> either[Error, Store[V]]
29
+ def validate_and_build: (Namespace) -> either[Error, Store[V]]
30
+
31
+ # @rbs (Namespace) -> either[Error, Store[V]]
32
+ def create_store: (Namespace) -> either[Error, Store[V]]
33
+
34
+ # @rbs (Store[V]) -> either[Error, Store[V]]
35
+ def apply_decorators: (Store[V]) -> either[Error, Store[V]]
36
+ end
37
+ end
@@ -0,0 +1,33 @@
1
+ # Generated from lib/typed_cache/cache_key.rb with RBS::Inline
2
+
3
+ module TypedCache
4
+ class CacheKey
5
+ extend Forwardable
6
+
7
+ attr_reader namespace: Namespace
8
+
9
+ attr_reader key: String
10
+
11
+ # @rbs (Namespace, String) -> void
12
+ def initialize: (Namespace, String) -> void
13
+
14
+ # @rbs (Namespace) -> bool
15
+ def belongs_to?: (Namespace) -> bool
16
+
17
+ # @rbs () -> String
18
+ def to_s: () -> String
19
+
20
+ alias cache_key to_s
21
+
22
+ # @rbs () -> String
23
+ def inspect: () -> String
24
+
25
+ # @rbs () -> Integer
26
+ def hash: () -> Integer
27
+
28
+ # @rbs (Object) -> bool
29
+ def ==: (Object) -> bool
30
+
31
+ alias eql? ==
32
+ end
33
+ end
@@ -0,0 +1,91 @@
1
+ # Generated from lib/typed_cache/cache_ref.rb with RBS::Inline
2
+
3
+ module TypedCache
4
+ # A monadic wrapper for cached values that provides safe access with rich error context.
5
+ # All operations return Either[Error, Snapshot[V]] to provide detailed information about
6
+ # cache operations and the source of values.
7
+ #
8
+ # @rbs generic V
9
+ class CacheRef[V]
10
+ attr_reader store: Store[V]
11
+
12
+ attr_reader key: CacheKey
13
+
14
+ # : (Store[V], CacheKey) -> void
15
+ def initialize: (Store[V], CacheKey) -> void
16
+
17
+ # Gets a value from the cache as a snapshot
18
+ # : -> either[Error, Snapshot[V]]
19
+ def get: () -> either[Error, Snapshot[V]]
20
+
21
+ # Sets a value in the cache and returns it as an updated snapshot
22
+ # : (V) -> either[Error, Snapshot[V]]
23
+ def set: (V) -> either[Error, Snapshot[V]]
24
+
25
+ # Deletes the value from the cache and returns the deleted value as a snapshot
26
+ # : -> either[Error, Snapshot[V]]
27
+ def delete: () -> either[Error, Snapshot[V]]
28
+
29
+ # Fetches a value from cache, computing and storing it if not found
30
+ # The snapshot indicates whether the value came from cache or was computed
31
+ # : () { -> V } -> either[Error, Snapshot[V]]
32
+ def fetch: () { () -> V } -> either[Error, Snapshot[V]]
33
+
34
+ # Checks if the cache contains a value for this key
35
+ # : -> bool
36
+ def present?: () -> bool
37
+
38
+ # Checks if the cache is empty for this key
39
+ # : -> bool
40
+ def empty?: () -> bool
41
+
42
+ # Maps over the cached value if it exists, preserving snapshot metadata
43
+ # : [R] () { (V) -> R } -> either[Error, Snapshot[R]]
44
+ def map: [R] () { (V) -> R } -> either[Error, Snapshot[R]]
45
+
46
+ # Binds over the cached value, allowing for monadic composition with snapshots
47
+ # : [R] () { (V) -> either[Error, R] } -> either[Error, Snapshot[R]]
48
+ def bind: [R] () { (V) -> either[Error, R] } -> either[Error, Snapshot[R]]
49
+
50
+ alias flat_map bind
51
+
52
+ # Updates the cached value using the provided block
53
+ # Returns the updated value as a snapshot with source=:updated
54
+ # : () { (V) -> V } -> either[Error, Snapshot[V]]
55
+ def update: () { (V) -> V } -> either[Error, Snapshot[V]]
56
+
57
+ # Returns the cached value or a default if the cache is empty/errored
58
+ # : (V) -> V
59
+ def value_or: (V) -> V
60
+
61
+ # Returns a Maybe containing the cached value, or None if not present
62
+ # This provides a more functional approach than value_or
63
+ # : -> maybe[V]
64
+ def value_maybe: () -> maybe[V]
65
+
66
+ # Computes and caches a value if the cache is currently empty
67
+ # Returns existing snapshot if present, computed snapshot if cache miss, error otherwise
68
+ # : () { -> V } -> either[Error, Snapshot[V]]
69
+ def compute_if_absent: () { () -> V } -> either[Error, Snapshot[V]]
70
+
71
+ # Creates a new CacheRef with the same store but different key
72
+ # : [R] (String) -> CacheRef[R]
73
+ def with_key: [R] (String) -> CacheRef[R]
74
+
75
+ # Creates a scoped CacheRef by appending to the current key path
76
+ # : [R] (String) -> CacheRef[R]
77
+ def scope: [R] (String) -> CacheRef[R]
78
+
79
+ # Pattern matching support for Either[Error, Snapshot[V]] results
80
+ # : [R] () { (Error) -> R } () { (Snapshot[V]) -> R } -> R
81
+ def fold: (untyped left_fn, untyped right_fn) -> untyped
82
+
83
+ # Convenience method to work with the snapshot directly
84
+ # : [R] () { (Snapshot[V]) -> R } -> either[Error, R]
85
+ def with_snapshot: [R] () { (Snapshot[V]) -> R } -> either[Error, R]
86
+
87
+ # Convenience method to work with just the value (losing snapshot context)
88
+ # : [R] () { (V) -> R } -> either[Error, R]
89
+ def with: [R] () { (V) -> R } -> either[Error, R]
90
+ end
91
+ end
@@ -0,0 +1,15 @@
1
+ # Generated from lib/typed_cache/clock.rb with RBS::Inline
2
+
3
+ module TypedCache
4
+ # A simple, testable wrapper around Time to provide a consistent way of
5
+ # getting the current time, respecting ActiveSupport's time zone when available.
6
+ class Clock
7
+ # Retrieves the current time. If ActiveSupport's `Time.current` is
8
+ # available, it will be used to respect the configured timezone. Otherwise,
9
+ # it falls back to the system's `Time.now`.
10
+ #
11
+ # @return [Time] The current time.
12
+ # @rbs () -> Time
13
+ def self.moment: () -> Time
14
+ end
15
+ end
@@ -0,0 +1,14 @@
1
+ # Generated from lib/typed_cache/decorator.rb with RBS::Inline
2
+
3
+ module TypedCache
4
+ # Marker mixin for cache store decorators. A decorator behaves exactly like a
5
+ # Store but must accept another Store instance in its constructor.
6
+ # @rbs generic V
7
+ module Decorator[V]
8
+ include Store[V]
9
+
10
+ include Store::_Store[V]
11
+
12
+ include Store::_Decorator[V]
13
+ end
14
+ end
@@ -0,0 +1,25 @@
1
+ # Generated from lib/typed_cache/decorators.rb with RBS::Inline
2
+
3
+ module TypedCache
4
+ # Holds store decorators (e.g., instrumentation wrappers) that can be composed
5
+ # by the CacheBuilder. Decorators must conform to the same API as the wrapped
6
+ # store (see `TypedCache::Store`) and accept the store instance as their first
7
+ # constructor argument.
8
+ #
9
+ # Example:
10
+ # Decorators.register(:my_decorator, MyDecorator)
11
+ # cache = TypedCache.builder
12
+ # .with_backend { |reg, ns| reg.resolve(:memory, ns).value }
13
+ # .with_decorator(:my_decorator)
14
+ # .build.value
15
+ module Decorators
16
+ # Default decorator set – starts with instrumentation only, but this registry
17
+ # lets end-users register their own via `Decorators.register`.
18
+ REGISTRY: untyped
19
+
20
+ extend Forwardable
21
+
22
+ # @rbs () -> Registry[Store[untyped]]
23
+ def self.registry: () -> Registry[Store[untyped]]
24
+ end
25
+ end