fix(drivers): mid-connect ApplyDelta adopts config in Calculation, refuses it in Galaxy (#664)

AdoptConfigDuringInit re-runs InitializeAsync(newConfig) and acks success, but
Calculation and Galaxy ignored the JSON there: Calculation kept its old tag
set, and Galaxy connected on its old endpoint. Calculation now rebuilds its tag
table from a config with a body (sharing AdoptConfig with ReinitializeAsync and
stopping any running timer scheduler first). Galaxy, which cannot hot-swap its
options, refuses a non-equivalent one the way ReinitializeAsync does. The actor
now sends DeltaApplied once the adopted init succeeds, so a dependency
consumer's mux interest is re-registered. Unreachable from deploys since #516.

Claude-Session: https://claude.ai/code/session_01Ef2ozxS7QPanGT8uoATbTe
This commit is contained in:
Joseph Doherty
2026-10-09 11:05:58 -04:00
parent 1355049f50
commit 97fcf624ae
8 changed files with 234 additions and 52 deletions
+10
View File
@@ -264,6 +264,16 @@ Things to know before touching any of this:
Calculation and Galaxy take their config at construction and ignore the JSON passed to `InitializeAsync`.
Not reachable from a deploy since #516 (a DriverConfig change respawns). Pin:
`An_in_place_ApplyDelta_leaves_one_live_data_and_one_live_alarm_subscription` (one case per wrong fix).
- **A mid-connect `ApplyDelta` re-runs `InitializeAsync(newConfig)` — so every driver's `InitializeAsync` must
honour the JSON (#664).** `AdoptConfigDuringInit` adopts a delta that lands while Connecting/Reconnecting by
re-initialising, and acks on adoption. Every driver re-parses a config with a body (#516/#630) except two that
used to ignore it: **Calculation** now rebuilds its tag table from it (sharing `AdoptConfig` with
`ReinitializeAsync`, and disposing any running timer scheduler first), and **Galaxy**, which cannot hot-swap
its options, now **refuses** a non-equivalent config with the same `NotSupportedException` its
`ReinitializeAsync` throws — it used to connect on the old endpoint while the deploy reported success. A
`"{}"`/empty document still keeps the constructor options. Once the adopted init succeeds the actor sends
`DeltaApplied`, so the host re-registers a dependency consumer's mux interest — the mid-connect path used to
send nothing. A new driver must follow the same rule. Unreachable from a deploy since #516.
- **Restart tests must assert a FUNCTION, never existence.** `RestartDriver_respawns_the_child_without_an_actor_name_collision`
asserts only that a child exists after a restart, and it passed green against the dead driver 03/S16
describes. It is kept — its own subject, the `InvalidActorNameException`, is real — but the load-bearing