Class: TypedCache::CacheRef
- Inherits:
-
Object
- Object
- TypedCache::CacheRef
- Defined in:
- lib/typed_cache/cache_ref.rb
Overview
A monadic wrapper for cached values that provides safe access with rich error context. All operations return Either[Error, Snapshot] to provide detailed information about cache operations and the source of values.
Instance Attribute Summary collapse
-
#key ⇒ Object
readonly
: CacheKey.
-
#store ⇒ Object
readonly
: Store.
Instance Method Summary collapse
-
#compute_if_absent(&block) ⇒ Object
Computes and caches a value if the cache is currently empty Returns existing snapshot if present, computed snapshot if cache miss, error otherwise : () { -> V? } -> either[Error, Snapshot[maybe]].
-
#delete ⇒ Object
Deletes the value from the cache and returns the deleted value as a snapshot : -> either[Error, maybe].
-
#empty? ⇒ Boolean
Checks if the cache is empty for this key : -> bool.
-
#fetch(&block) ⇒ Object
Fetches a value from cache, computing and storing it if not found The snapshot indicates whether the value came from cache or was computed : () { -> V? } -> either[Error, Snapshot[maybe]].
-
#initialize(store, key) ⇒ CacheRef
constructor
: (Store, CacheKey) -> void.
- #inspect ⇒ Object
-
#map(&block) ⇒ Object
Maps over the cached value if it exists, preserving snapshot metadata : [R] () { (V) -> R } -> either[Error, Snapshot].
-
#present? ⇒ Boolean
Checks if the cache contains a value for this key : -> bool.
-
#read ⇒ Object
Gets a value from the cache as a snapshot : -> either[Error, Snapshot[maybe]].
- #to_s ⇒ Object
-
#update(&block) ⇒ Object
Updates the cached value using the provided block Returns the updated value as a snapshot with source=:updated : () { (V) -> V? } -> either[Error, Snapshot[maybe]].
-
#with(&block) ⇒ Object
Convenience method to work with just the value (losing snapshot context) : [R] () { (V) -> R } -> either[Error, R].
-
#with_snapshot(&block) ⇒ Object
Convenience method to work with the snapshot directly : [R] () { (Snapshot) -> R } -> either[Error, R].
-
#write(value) ⇒ Object
Sets a value in the cache and returns it as an updated snapshot : (V) -> either[Error, Snapshot].
Constructor Details
Instance Attribute Details
#key ⇒ Object (readonly)
: CacheKey
15 16 17 |
# File 'lib/typed_cache/cache_ref.rb', line 15 def key @key end |
#store ⇒ Object (readonly)
: Store
14 15 16 |
# File 'lib/typed_cache/cache_ref.rb', line 14 def store @store end |
Instance Method Details
#compute_if_absent(&block) ⇒ Object
Computes and caches a value if the cache is currently empty Returns existing snapshot if present, computed snapshot if cache miss, error otherwise : () { -> V? } -> either[Error, Snapshot[maybe]]
96 97 98 99 100 101 102 103 104 105 106 107 108 |
# File 'lib/typed_cache/cache_ref.rb', line 96 def compute_if_absent(&block) fetch(&block).fold( ->(error) { Either.left(StoreError.new( :compute_if_absent, key, "Failed to compute value: #{error.message}", error, )) }, ->(snapshot) { Either.right(snapshot) }, ) end |
#delete ⇒ Object
Deletes the value from the cache and returns the deleted value as a snapshot : -> either[Error, maybe]
37 38 39 |
# File 'lib/typed_cache/cache_ref.rb', line 37 def delete store.delete(key) end |
#empty? ⇒ Boolean
Checks if the cache is empty for this key : -> bool
56 57 58 |
# File 'lib/typed_cache/cache_ref.rb', line 56 def empty? store.read(key).left? end |
#fetch(&block) ⇒ Object
Fetches a value from cache, computing and storing it if not found The snapshot indicates whether the value came from cache or was computed : () { -> V? } -> either[Error, Snapshot[maybe]]
44 45 46 |
# File 'lib/typed_cache/cache_ref.rb', line 44 def fetch(&block) store.fetch(key, &block) end |
#inspect ⇒ Object
126 |
# File 'lib/typed_cache/cache_ref.rb', line 126 def inspect = "CacheRef(#{key}, #{store.inspect})" |
#map(&block) ⇒ Object
Maps over the cached value if it exists, preserving snapshot metadata : [R] () { (V) -> R } -> either[Error, Snapshot]
62 63 64 |
# File 'lib/typed_cache/cache_ref.rb', line 62 def map(&block) read.map { |snapshot| snapshot.map { |mb| mb.map(&block) } } end |
#present? ⇒ Boolean
Checks if the cache contains a value for this key : -> bool
50 51 52 |
# File 'lib/typed_cache/cache_ref.rb', line 50 def present? store.read(key).right? end |
#read ⇒ Object
Gets a value from the cache as a snapshot : -> either[Error, Snapshot[maybe]]
25 26 27 |
# File 'lib/typed_cache/cache_ref.rb', line 25 def read store.read(key) end |
#to_s ⇒ Object
123 |
# File 'lib/typed_cache/cache_ref.rb', line 123 def to_s = "CacheRef(#{key} from #{store.namespace})" |
#update(&block) ⇒ Object
Updates the cached value using the provided block Returns the updated value as a snapshot with source=:updated : () { (V) -> V? } -> either[Error, Snapshot[maybe]]
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
# File 'lib/typed_cache/cache_ref.rb', line 69 def update(&block) read.bind do |snapshot| new_value = snapshot.value.bind do |value| new_value = yield(value) Maybe.wrap(new_value) end if new_value.some? write(new_value.value).map do |snapshot| snapshot.map { new_value } end else delete.map { snapshot } end rescue => e Either.left(StoreError.new( :update, key, "Failed to update value: #{e.message}", e, )) end end |
#with(&block) ⇒ Object
Convenience method to work with just the value (losing snapshot context) : [R] () { (V) -> R } -> either[Error, R]
118 119 120 |
# File 'lib/typed_cache/cache_ref.rb', line 118 def with(&block) read.map { |snapshot| yield(snapshot.value) } end |
#with_snapshot(&block) ⇒ Object
Convenience method to work with the snapshot directly : [R] () { (Snapshot) -> R } -> either[Error, R]
112 113 114 |
# File 'lib/typed_cache/cache_ref.rb', line 112 def with_snapshot(&block) read.map(&block) end |
#write(value) ⇒ Object
Sets a value in the cache and returns it as an updated snapshot : (V) -> either[Error, Snapshot]
31 32 33 |
# File 'lib/typed_cache/cache_ref.rb', line 31 def write(value) store.write(key, value) end |