mbproxy/docs: pivot design contract for Phase 11 response cache
Lands the design-contract pivot ahead of any cache implementation code so reviewers can evaluate the change to the "purely transparent proxy" stance independently of the Phase-11 code that depends on it. - docs/design.md: rewrite "What this is" / Read-coalescing / Failure-modes sections to acknowledge the opt-in cache; add new "Response cache (Phase 11)" section covering lookup order (cache -> coalesce -> backend), multi- tag range TTL = min, post-rewriter storage, address-range-overlap write invalidation, hot-reload PLC-wide flush, no-persistence, AllowLongTtl gate, and LRU-bounded capacity. Extend log event table with mbproxy.cache.* events. Extend per-PLC status field table with cacheHitCount / cacheMissCount / cacheInvalidations / cacheEntryCount / cacheBytes. Extend hot-reload propagation table with CacheTtlMs / Cache.* rows. - docs/kpi.md: graduate Tier 1.8 (response cache) from "requires Phase 11" to "shipped in Phase 11" and add Tier 2.4a cache-memory section. - CLAUDE.md (mbproxy): update Purpose paragraph and the Architecture headline bullets to reflect the transparent-by-default + opt-in-cache contract; flip "Implementation complete through Phase 10" to "through Phase 11". - install/mbproxy.config.template.json: add a fully-commented Mbproxy.Cache block and a CacheTtlMs example on a BcdTags.Global entry, with prominent staleness commentary documenting the design contract. No code changes in this commit - implementation lands in a follow-up. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -33,7 +33,13 @@
|
||||
{ "Address": 1056, "Width": 32 },
|
||||
|
||||
// V2100 (octal) = decimal address 1088. 16-bit BCD setpoint.
|
||||
{ "Address": 1088, "Width": 16 }
|
||||
//
|
||||
// Phase 11: CacheTtlMs (optional) opts this tag into the response cache. With
|
||||
// CacheTtlMs > 0 set, upstream clients reading this register will see values up
|
||||
// to CacheTtlMs MILLISECONDS OLD — explicit acknowledgement of the staleness
|
||||
// window is required by enabling it. Default (omitted or 0) = cache disabled
|
||||
// for this tag. The cache is OFF by default for every tag.
|
||||
{ "Address": 1088, "Width": 16 /* , "CacheTtlMs": 1000 */ }
|
||||
]
|
||||
},
|
||||
|
||||
@@ -143,6 +149,40 @@
|
||||
"Enabled": true,
|
||||
"MaxParties": 32
|
||||
}
|
||||
},
|
||||
|
||||
// ── Response cache (Phase 11) — opt-in bounded-staleness cache ──────────────────
|
||||
//
|
||||
// ⚠ DESIGN-CONTRACT PIVOT: with caching enabled the proxy is no longer purely
|
||||
// transparent. Upstream FC03/FC04 reads for cache-enabled tags may return values
|
||||
// up to CacheTtlMs MILLISECONDS OLD. Operators opt tags in by setting a non-zero
|
||||
// CacheTtlMs on a BcdTagOptions entry (or DefaultCacheTtlMs on a PlcOptions entry).
|
||||
//
|
||||
// The cache is OFF BY DEFAULT for every tag. A deployment with NO TTL config (this
|
||||
// section entirely absent and no BcdTags.*.CacheTtlMs / Plcs[i].DefaultCacheTtlMs)
|
||||
// behaves IDENTICALLY to a pre-Phase-11 deployment — no behaviour change.
|
||||
//
|
||||
// AllowLongTtl — gate for any CacheTtlMs > 60_000. Reload validation
|
||||
// rejects configs that exceed 60 s without this opt-in,
|
||||
// to prevent accidentally-stale-for-an-hour deployments.
|
||||
// MaxEntriesPerPlc — LRU cap per-PLC. Past this cap, the next insert evicts
|
||||
// the least-recently-used entry. Defaults to 1000.
|
||||
// EvictionIntervalMs — background eviction tick. Scans each PLC's cache and
|
||||
// removes entries past their TTL. Defaults to 5000.
|
||||
//
|
||||
// Properties (full text in docs/design.md → "Response cache"):
|
||||
// * Cache hits SHORT-CIRCUIT coalescing entirely (cache → coalesce → backend).
|
||||
// * Successful FC06/FC16 write responses invalidate every cached FC03/FC04 entry
|
||||
// whose address range OVERLAPS the write — not just exact-key match.
|
||||
// * Multi-tag read range: effective TTL = min(TTLs). Any tag with TTL=0 in the
|
||||
// range disables caching for the whole read.
|
||||
// * Cache stores POST-rewriter bytes; hits never re-invoke the BCD rewriter.
|
||||
// * Tag-list hot-reload flushes the affected PLC's whole cache.
|
||||
// * No persistence — process restart wipes the cache.
|
||||
"Cache": {
|
||||
"AllowLongTtl": false,
|
||||
"MaxEntriesPerPlc": 1000,
|
||||
"EvictionIntervalMs": 5000
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
Reference in New Issue
Block a user