You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
allways/utils/misc.py carries a generic @ttl_cache decorator plus a ttl_hash_gen generator — roughly 30 lines of cache machinery whose only purpose is to back one function:
Single caller.ttl_get_block is referenced exactly once in the codebase — neurons/base/neuron.py:40, inside BaseNeuron.block. Grep for ttl_get_block | ttl_cache | ttl_hash_gen returns hits in utils/misc.py itself and that one import line.
Free-standing self.ttl_get_block(self) takes self as an ordinary positional arg because @ttl_cache can't cleanly wrap bound methods — the decorator caches on the argument tuple, and passing a method through the decorator would need an update_wrapper dance that isn't there. So the function exists in utils/misc.py as a non-method that happens to accept a BaseNeuron instance, then is called from a class property. That's the abstraction leaking.
Impact
Readability. A reader tracing BaseNeuron.block has to cross a module boundary into utils/misc.py, follow the decorator through ttl_cache → ttl_hash_gen → lru_cache, and work out that the whole stack collapses to "cache the result for 12 seconds." That's five levels of indirection for a one-line cache.
Dead-flavored code.ttl_cache and ttl_hash_gen are exported as if they're general-purpose utilities, but nothing else uses them. Anyone reusing them would be building on a pattern the codebase has otherwise avoided. Fits the tone of refactor: remove dead read_result_option_swap and read_result_u128 #49's "remove dead abstractions that pretend to be reusable."
Module sprawl.utils/misc.py is the classic grab-bag — once the one useful thing is removed, there's no reason to keep the file.
Proposed fix
Inline an instance-level cache into BaseNeuron:
_BLOCK_CACHE_TTL_SECONDS=12classBaseNeuron(ABC):
...
@propertydefblock(self):
"""Current chain head, cached for one block (~12 s) to amortize the RPC round-trip."""now=time.monotonic()
ifnow-self._cached_block_at>=_BLOCK_CACHE_TTL_SECONDS:
self._cached_block=self.subtensor.get_current_block()
self._cached_block_at=nowreturnself._cached_blockdef__init__(self, config=None):
...
self._cached_block: int=0self._cached_block_at: float=0.0
Then delete allways/utils/misc.py entirely — no callers remain.
time.monotonic() replaces the time.time() used inside ttl_hash_gen. This is strictly more robust (immune to wall-clock jumps, NTP slew, and leap seconds) and has identical semantics for a 12-second TTL — nothing in the codebase cares about wall vs. monotonic time at this granularity.
Problem
allways/utils/misc.pycarries a generic@ttl_cachedecorator plus attl_hash_gengenerator — roughly 30 lines of cache machinery whose only purpose is to back one function:Two things make this abstraction awkward:
ttl_get_blockis referenced exactly once in the codebase — neurons/base/neuron.py:40, insideBaseNeuron.block. Grep forttl_get_block | ttl_cache | ttl_hash_genreturns hits inutils/misc.pyitself and that one import line.self.ttl_get_block(self)takesselfas an ordinary positional arg because@ttl_cachecan't cleanly wrap bound methods — the decorator caches on the argument tuple, and passing a method through the decorator would need anupdate_wrapperdance that isn't there. So the function exists inutils/misc.pyas a non-method that happens to accept aBaseNeuroninstance, then is called from a class property. That's the abstraction leaking.Impact
BaseNeuron.blockhas to cross a module boundary intoutils/misc.py, follow the decorator throughttl_cache→ttl_hash_gen→lru_cache, and work out that the whole stack collapses to "cache the result for 12 seconds." That's five levels of indirection for a one-line cache.ttl_cacheandttl_hash_genare exported as if they're general-purpose utilities, but nothing else uses them. Anyone reusing them would be building on a pattern the codebase has otherwise avoided. Fits the tone of refactor: remove dead read_result_option_swap and read_result_u128 #49's "remove dead abstractions that pretend to be reusable."utils/misc.pyis the classic grab-bag — once the one useful thing is removed, there's no reason to keep the file.Proposed fix
Inline an instance-level cache into
BaseNeuron:Then delete
allways/utils/misc.pyentirely — no callers remain.time.monotonic()replaces thetime.time()used insidettl_hash_gen. This is strictly more robust (immune to wall-clock jumps, NTP slew, and leap seconds) and has identical semantics for a 12-second TTL — nothing in the codebase cares about wall vs. monotonic time at this granularity.