Files
DECNET/decnet/ttp/store/impl/database.py
anti bcd1f14cd3 feat(ttp): E.1.11 RuleStore contract — base ABC, factory, filesystem + database stubs
Adds decnet/ttp/store/ subpackage:
- base.py: RuleState frozen dataclass, RuleChange NamedTuple, RuleStore ABC
- factory.py: get_rule_store() reading DECNET_TTP_RULE_STORE_TYPE
- impl/filesystem.py: FilesystemRuleStore with sys.platform=='linux'
  fail-fast guard, allowlist filename regex, raw inotify mask bits
  (lib import deferred to E.3 so contract phase compiles without the
  asyncinotify dep installed)
- impl/database.py: DatabaseRuleStore stub (no platform guard)

TTPRule + TTPRuleState SQLModels were already shipped at E.1.1; this
commit closes the type-only TYPE_CHECKING forward-ref in
rule_engine.py via real runtime imports through the new package.
2026-05-01 07:25:09 -04:00

61 lines
1.9 KiB
Python

"""Database-backed rule store — ``ttp_rule`` + ``ttp_rule_state``.
Contract step E.1.11. Bodies raise ``NotImplementedError``; the
backing tables (:class:`TTPRule`, :class:`TTPRuleState`) shipped at
E.1.1.
Right for swarm: master syncs filesystem changes into ``ttp_rule``,
workers tail the DB, state in ``ttp_rule_state`` survives restart and
propagates to every worker. Pick via
``DECNET_TTP_RULE_STORE_TYPE=database``.
No platform guard — works on macOS / Windows where the filesystem
backend's inotify dependency is unavailable.
"""
from __future__ import annotations
from collections.abc import AsyncIterator
from decnet.ttp.impl.rule_engine import CompiledRule
from decnet.ttp.store.base import RuleChange, RuleState, RuleStore
class DatabaseRuleStore(RuleStore):
"""``ttp_rule`` content + ``ttp_rule_state`` operational state.
Contract phase: every method raises ``NotImplementedError``. The
impl step (E.3) implements DB-tail subscription + master-side
filesystem→DB sync. Worker-side tailing reads via the existing
repository pattern; the master's filesystem-watch sync is
structurally a delta from :class:`FilesystemRuleStore` plus a
``ttp_rule`` upsert.
"""
async def load_compiled(self) -> list[CompiledRule]:
raise NotImplementedError(
"DatabaseRuleStore.load_compiled lands at E.3",
)
async def get_state(self, rule_id: str) -> RuleState:
raise NotImplementedError(
"DatabaseRuleStore.get_state lands at E.3",
)
async def set_state(
self,
rule_id: str,
state: RuleState,
set_by: str,
) -> None:
raise NotImplementedError(
"DatabaseRuleStore.set_state lands at E.3",
)
def subscribe_changes(self) -> AsyncIterator[RuleChange]:
raise NotImplementedError(
"DatabaseRuleStore.subscribe_changes lands at E.3",
)
__all__ = ["DatabaseRuleStore"]