Skip to content

fix(kick): drop the kicked participant from cached membership - #386

Open
schronck wants to merge 2 commits into
mainfrom
fix/kick/prune-cached-membership
Open

fix(kick): drop the kicked participant from cached membership#386
schronck wants to merge 2 commits into
mainfrom
fix/kick/prune-cached-membership

Conversation

@schronck

Copy link
Copy Markdown
Collaborator

Summary

The add_party_missing_dar integration phase has been failing on main roughly every other run, always at the same step:

Scenario "re-add P3 while it is missing the contracts' DAR" failed at WHEN "P1 re-adds P3"
POST /add-party returned 409 Conflict: {"error":"Participant sv::1220... is already a member of test-network-1::1220..."}

It is not the test. POST /add-party validates membership against the cached dec_party_participants table, and the only production writer of that table is store_parties_to_db, reached solely from the /decentralized-parties refresh path. The kick workflow never touched it, so after a kick completed the coordinator still held the removed participant as a member. The phase was green only when an unrelated refresh happened to land between the kick and the re-add, which is exactly the alternating pass/fail we saw.

The same staleness inflates post_add_member_count, so the new_threshold upper bound was one member too high after any kick.

An operator scripting kick then add-party hits the same 409, so this is a product bug rather than test flake.

Related issues

Surfaced while chasing the red Integration Tests job on #385.

Type of change

  • Bug fix
  • New feature
  • Refactor
  • Documentation
  • Build / CI / chore

Checklist

  • cargo fmt -- --check passes
  • cargo clippy --all-targets --all-features -- -D warnings is clean
  • cargo test passes
  • Added/updated tests where appropriate
  • Updated documentation where appropriate
  • Commits follow the <type>(<scope>): <subject> convention

Notes for reviewers

The prune runs on the coordinator right after submit_kick has confirmed both topology mappings, so it only fires once the kick is actually durable.

It is deliberately surgical rather than a full /decentralized-parties refresh: the workflow already knows exactly which participant it removed, so no extra network call is needed and there is nothing to fail on a flaky admin API.

Two gaps I did not close here, happy to follow up:

  • Peers. P2 signs the kick but keeps its own stale cache. Only the coordinator is fixed, because only the coordinator's view blocks the observed flow.
  • Cached threshold. dec_party.threshold is also stale after a kick. Nothing validates against it today (previous_threshold is display-only and carried in the request), so it is latent rather than live.

Worth merging before #385, whose Integration Tests job is red on this and nothing else.

`POST /add-party` and `POST /kick` validate against
`dec_party_participants`, whose only production writer is the
`/decentralized-parties` refresh. A completed kick left the coordinator
still holding the removed participant, so an immediate re-add was
rejected with "already a member" and the post-add threshold bound was
computed one member too high.

This is what fails the add_party_missing_dar phase in CI. That phase
kicks P3, waits for /kick/status to report completed, then re-adds P3 —
green only when an unrelated refresh happened to land in between, which
is why the job alternated pass/fail on main.
@schronck
schronck requested review from a team and sosaucily August 27, 2026 12:57
@schronck schronck self-assigned this Aug 27, 2026
@schronck
schronck requested review from scolear and a lite review from Copilot August 27, 2026 12:57

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes a kick/add-party workflow bug where the coordinator’s cached decentralized-party membership (dec_party_participant) remained stale after a successful kick, causing immediate re-adds to fail with a 409 “already a member” and inflating post-add threshold bounds.

Changes:

  • Adds a new kick step helper (prune_cached_membership) to remove the kicked participant from the coordinator’s cached membership.
  • Invokes the cache-prune immediately after submit_kick in the coordinator kick workflow.
  • Adds SQLx integration tests covering both “kicked member removed” and “absent member is a no-op” behavior.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

File Description
crates/decman/src/workflow/kick/steps/mod.rs Exposes the new cache-pruning step module and re-exports its entrypoint.
crates/decman/src/workflow/kick/steps/cache.rs Implements cache pruning for kicked participants and adds integration tests.
crates/decman/src/workflow/kick/mod.rs Re-exports prune_cached_membership from the kick module API surface.
crates/decman/src/workflow/kick/coordinator.rs Calls cache pruning after submit_kick in the coordinator workflow.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread crates/decman/src/workflow/kick/steps/cache.rs Outdated
Comment thread crates/decman/src/workflow/kick/coordinator.rs
Two review findings.

Rebuilding the participant set re-upserted every surviving row, and
`replace_dec_party_participants` overwrites `permission` unconditionally,
so a permission change landed by a concurrent /decentralized-parties
refresh between the read and the write was reverted. Delete the single
row instead; nothing here needs the others.

Pruning also ran with `?` inside SubmitKick, so a DB error after the
topology transactions were already durable left the workflow on that
step and a resume resubmitted them. Log and continue: a stale cache is
recoverable by the next refresh, a rewound kick is not.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants