# SPDX-FileCopyrightText: ☭ Emery Hemingway # SPDX-License-Identifier: Unlicense import std/times import preserves, syndicate, syndicate/durings, syndicate/drivers/timers import ../schema/config proc afterTimeout(n: float64): LaterThan = ## Get a `LaterThan` record for `n` seconds in the future. result.seconds = getTime().toUnixFloat() + n type CacheEntity {.final.} = ref object of Entity timeouts, target: Cap # dataspaces for observing timeouts and publishing values pattern: Pattern lifetime: float64 method publish(cache: CacheEntity; turn: var Turn; ass: AssertionRef; h: Handle) = ## Re-assert pattern captures in a sub-facet. discard inFacet(turn) do (turn: var Turn): # TODO: a seperate facet for every assertion, too much? var ass = depattern(cache.pattern, ass.value.sequence) # Build an assertion with what he have of the pattern and capture. discard publish(turn, cache.target, ass) let timeout = afterTimeout(cache.lifetime) onPublish(turn, cache.timeouts, ?timeout) do: stop(turn) # end this facet proc isObserve(pat: Pattern): bool = pat.orKind == PatternKind.DCompound and pat.dcompound.orKind == DCompoundKind.rec and pat.dcompound.rec.label.isSymbol"Observe" proc spawnCacheActor*(turn: var Turn; root: Cap): Actor = spawnActor(turn, "cache_actor") do (turn: var Turn): during(turn, root, ?:CacheArguments) do (ds: Cap, lifetime: float64): onPublish(turn, ds, ?:Observe) do (pat: Pattern, obs: Cap): var cache: CacheEntity if obs.relay != turn.facet and not(pat.isObserve): # Watch pattern if the observer is not us # and if the pattern isn't a recursive observe cache = CacheEntity( timeouts: root, target: ds, pattern: pat, lifetime: lifetime, ) discard observe(turn, ds, pat, cache) when isMainModule: import syndicate/relays runActor("main") do (turn: var Turn): resolveEnvironment(turn) do (turn: var Turn; ds: Cap): discard spawnTimerDriver(turn, ds) discard spawnCacheActor(turn, ds)