Summary
On a replicated: true set_configuration, the origin applies locally, fans out, and then overwrites the fan-out response's message with the unconditional success string. A peer that rejected the change is only visible if the caller reads response.replicated.
const response = await server.replication.replicateOperation(setConfigJson);
response.message = CONFIGURE_SUCCESS_RESPONSE; // overwrites, regardless of per-node outcomes
return response;
Failure scenario
A rolling upgrade, made concrete by #2266's fix. Before it, a peer whose CONFIG_PARAM_MAP lacks a param silently ignored it; after it, that peer returns a hard 400. So during a mixed-version window:
- The origin (new version) accepts a param the not-yet-upgraded peers don't know.
- It applies locally and fans out.
- Each peer 400s the name.
response.message still reads Configuration successfully set. You must restart Harper for new config settings to take effect.
The cluster is now divergently configured, and the top-level response says it worked. The same shape applies to any per-node failure — an unwritable config file, a peer mid-restart — not just a version skew.
Scope
Pre-existing, introduced with replicated: true support (#660), and independent of #2266 — but #2266 makes it materially more likely to fire, because a peer that used to ignore an unknown name now fails on it. Worth deciding together with #2266's release line.
The local write also lands before the fan-out (origin-first, pinned by integrationTests/apiTests/configuration.test.mjs), so there is no rollback of the origin when peers reject. That ordering is deliberate and not what this issue asks to change; the ask is that the response stop claiming success when it has per-node failures in hand.
Suggested shape
Derive message from the per-node outcomes rather than assigning the success constant unconditionally — success only when every node succeeded, otherwise a message that says how many nodes failed and points at replicated. Alternatively return a non-2xx when any peer failed, though that is a bigger contract change for callers that currently treat 200 as "origin applied".
Related
Summary
On a
replicated: trueset_configuration, the origin applies locally, fans out, and then overwrites the fan-out response'smessagewith the unconditional success string. A peer that rejected the change is only visible if the caller readsresponse.replicated.Failure scenario
A rolling upgrade, made concrete by #2266's fix. Before it, a peer whose
CONFIG_PARAM_MAPlacks a param silently ignored it; after it, that peer returns a hard 400. So during a mixed-version window:response.messagestill readsConfiguration successfully set. You must restart Harper for new config settings to take effect.The cluster is now divergently configured, and the top-level response says it worked. The same shape applies to any per-node failure — an unwritable config file, a peer mid-restart — not just a version skew.
Scope
Pre-existing, introduced with
replicated: truesupport (#660), and independent of #2266 — but #2266 makes it materially more likely to fire, because a peer that used to ignore an unknown name now fails on it. Worth deciding together with #2266's release line.The local write also lands before the fan-out (origin-first, pinned by
integrationTests/apiTests/configuration.test.mjs), so there is no rollback of the origin when peers reject. That ordering is deliberate and not what this issue asks to change; the ask is that the response stop claiming success when it has per-node failures in hand.Suggested shape
Derive
messagefrom the per-node outcomes rather than assigning the success constant unconditionally — success only when every node succeeded, otherwise a message that says how many nodes failed and points atreplicated. Alternatively return a non-2xx when any peer failed, though that is a bigger contract change for callers that currently treat 200 as "origin applied".Related