I found this pretty easy to read through. I'd suggest setting a description on the repo too so it's easy to find.
https://github.com/mishalzaman/memo_ttl/blob/main/lib/memo_t...
Only suggestion is to not wrap the error of the caller in your memo wrapper.
> raise MemoTTL::Error, "Failed to execute memoized method '#{method_name}': #{e.message}"
It doesn't look like you need to catch this for any operational or state tracking reason so IMO you should not catch and wrap. When errors are wrapped with a string like this (and caught/ re-raised) you lose the original stacktrace which make debugging challenging. Especially when your error is like, "pg condition failed for select" and you can't see where it failed in the driver.
raise "Failed to execute memoized method '#{method_name}'"
And ruby will set `cause` for youhttps://pablofernandez.tech/2014/02/05/wrapped-exceptions-in...
Anyway, I ended up with a hack like this, which works fine but didn't feel great.
def some_method(arg)
@_memo_wise[__method__].tap { _1.clear if _1.length > 100 }
...
end
memo_wise :some_method
@lock.synchronize do
entry = @store[key]
return nil unless entry
...
you can do entry = @store[key]
return nil unless entry
@lock.synchronize do
entry = @store[key]
And similarly for other codepaths``` return nil unless entry ```
memoize def expensive_calculation(arg)
@calculation_count += 1
arg * 2
end, ttl: 10, max_size: 2
memoize def nil_returning_method
@calculation_count += 1
nil
end
locofocos•3h ago
film42•3h ago
thomascountz•3h ago
hp_hovercraft84•3h ago
- Local and zero-dependency. It caches per object in memory, so no Redis setup, no serialization, no network latency. -Isolated and self-managed. Caches aren’t global. Each object/method manages its own LRU + TTL lifecycle and can be cleared with instance helpers. - Easy to use — You just declare the method, set the TTL and max size, and you're done. No key names, no block wrapping, no external config.
JamesSwift•2h ago
EDIT: see https://github.com/rails/rails/blob/main/activesupport/lib/a...