fix(inbound-api): API-method recompile/invalidate reaches the peer central node; stale doc; locked-override name rule (ScadaBridge#103)
(a) Inbound API compile state (#75) is per central node: a recompile cleared the known-bad record only on the node that answered, and the peer kept refusing the unchanged script with SCRIPT_COMPILE_FAILED (the per-request revision check only notices a changed script). Create / update / delete (ManagementActor post-commit), RecompileApiMethod, and API methods written by a Transport bundle import now publish InboundApiMethodInvalidated on the central cache-invalidation topic (#100 item 3). The new InboundApiCacheInvalidationHandler drops that method's compiled handler, known-bad record and cached ApiMethod row on the peer, which compiles the current text on its next request. (b) docs/components/InboundAPI.md no longer claims a direct DB edit stays stale until restart: the per-request revision check picks it up once the node's cached row expires (ApiMethodCacheTtl, 5 s). Component-InboundAPI, Component-Host and the #85 cache audit describe the peer invalidation. (c) Decision: the import's locked-override warnings keep EXACT (ordinal) name matching, because FlatteningService matches override names ordinally. An override differing from a locked member only by case never reaches that member's lock check (the flattener drops it as unresolved), so a "targets a LOCKED member" warning for it would be false. The comparer is now named (LockedOverrideNameComparer) and documented, and pinned by tests on both sides (flattener + import). Tests: the peer's known-bad record is cleared by a recompile (and validate leaves it alone); create/update/delete and the import publish the invalidation; the handler drops only the named method; composition root registers the handler; case-only override gets no lock warning; the flattener matches override names exactly. Claude-Session: https://claude.ai/code/session_01GT67AEHd2Acv1YPwGfXEoV
This commit is contained in:
@@ -22,7 +22,7 @@ node after a change is made through the other one. Same defect class as #83
|
||||
| Cache | Holds | Local invalidation | Peer staleness bound | Verdict |
|
||||
|---|---|---|---|---|
|
||||
| `InboundScriptExecutor` compiled handlers (InboundAPI) | Compiled method delegates | `InvalidateMethod` on delete; change bus on import | **None** — every request revision-checks the cached handler against the resolved `ApiMethod.Script` and recompiles on mismatch | OK |
|
||||
| `ApiMethodCache` (InboundAPI) | `ApiMethod` rows, incl. not-found | Change bus (bundle import); **management create/update/delete — added by #85** | `InboundApi:ApiMethodCacheTtl`, default **5 s** | OK (local gap fixed, see below) |
|
||||
| `ApiMethodCache` (InboundAPI) | `ApiMethod` rows, incl. not-found | Change bus (bundle import); **management create/update/delete — added by #85** | Change through the other node: **none** (`InboundApiMethodInvalidated`, #103); direct SQL: `InboundApi:ApiMethodCacheTtl`, default **5 s** | OK (local gap fixed by #85, peer by #103) |
|
||||
| `ExternalDefinitionLookupCache` (ESG, central only) | External systems / methods / DB connections (found only) | 9 ManagementActor handlers (#65); bundle import (#83) | Edit or import through the other node: **none** (`ExternalDefinitionsInvalidated` on `central-cache-invalidation`, #100); direct SQL: `ExternalSystemGateway:DefinitionCacheTtl`, **10 s** on central | Fixed — #100 item 3 (see D3) |
|
||||
| `RoleMappingCache` (Security) — the cache at `ManagementActor` `InvalidateRoleMappingCacheAfterCommit` | LDAP group → role map + Deployer site scopes | Mapping / scope-rule commands, post-commit | **None** (`RoleMappingsInvalidated` on `central-cache-invalidation`, #100); TTL `Security:RoleMappingCacheSeconds` (**30 s**) only if the broadcast is lost | Fixed — #100 item 3 (see D1) |
|
||||
| `PendingUpdatesCache` (DeploymentManager, #91) | Fleet pending-updates snapshot | Deployment finished on this node | `DeploymentManager:PendingUpdatesCacheTtl`, default **60 s** | OK — display only |
|
||||
@@ -84,7 +84,9 @@ messages (`ICentralCacheInvalidation`: `SitePskInvalidated`, `RoleMappingsInvali
|
||||
The #96 topic was migrated onto it: `SitePskInvalidated` travels on the shared topic, and for one
|
||||
release is also published bare on `site-psk-invalidation` (still subscribed), so a mixed-version
|
||||
central pair keeps working. Each envelope carries the publisher's origin id and the subscriber
|
||||
skips its own. Publishers: ManagementActor post-commit (role mappings, external definitions),
|
||||
the Transport bundle importer (external definitions) and the PSK invalidator. Every cache keeps its TTL / revision check as the fallback for a
|
||||
skips its own. Publishers: ManagementActor post-commit (role mappings, external definitions,
|
||||
API methods), the Transport bundle importer (external definitions, API methods), the API-method
|
||||
recompile (#103: a recompile now clears a stale known-bad record on the peer too) and the PSK
|
||||
invalidator. Every cache keeps its TTL / revision check as the fallback for a
|
||||
lost broadcast or an out-of-band (SQL) edit. Design: Component-Host.md → *Central cache
|
||||
invalidation*; tests include a real two-node cluster (`CentralCacheInvalidationTwoNodeTests`).
|
||||
|
||||
Reference in New Issue
Block a user