fix: broker cannot gracefully shutdown when fenced by a duplicate node#3465
fix: broker cannot gracefully shutdown when fenced by a duplicate node#3465vishalmaurya850 wants to merge 3 commits into
Conversation
Added exception handling for force upload and stream closing. Signed-off-by: Vishal Maurya <vishalmaurya850@gmail.com>
Signed-off-by: Vishal Maurya <vishalmaurya850@gmail.com>
|
@vishalmaurya850 May I ask what scenario caused the duplicate nodeId? Theoretically, nodeId should not be duplicated during deployment. |
|
@superhx Thanks for having a look on my PR Most common cause: Kubernetes pod restart races — the new pod starts before the old one fully terminates, briefly creating two brokers with the same node ID. Also: operator config mistakes, VM clones, or rolling upgrade timing issues. It's an edge case, but the broker shouldn't hang forever when it happens. |
|
@vishalmaurya850 Judging from the problem description, can it be shut down successfully as long as this issue 'Pending WAL appends never complete (WAL is fenced)' is resolved? |
|
@superhx Yes, largely. The main blocker is the hanging pending WAL appends. Once those complete or fail fast, StreamWrapper.close() removes the stream from tracking even if closeStream returns NODE_EPOCH_EXPIRED, so shutdown proceeds. The NODE_EPOCH_EXPIRED handling is just for cleaner logs, and the force-close timeout is the safety net to guarantee appends don't hang. |
Could we adjust this to fix the issue where Pending WAL appends never complete? Right now it mostly acts as a fallback measure. |
|
@superhx Let me deep dive in the code and will let you know If we can solve it. |
Signed-off-by: Vishal Maurya <vishalmaurya850@gmail.com>
|
Complete request.cf exceptionally when the WAL append fails, so pending appends drain on fencing instead of blocking shutdown indefinitely. |
|
@superhx I have created the fix |
Great, after this fix, do we still need to modify the existing S3Stream and S3StreamClient? |
|
@superhx The S3Storage fix is necessary but not sufficient — the S3Stream and S3StreamClient changes remain essential for shutdown resilience. |
Could you please describe why these fixes are necessary? |
|
The S3Storage fix only covers the append path — it doesn't touch the close path, which has its own independent failure points:
|
If we fix the append stuck issue, close should theoretically not get stuck. |
You are right. We can remove it if you prefer; however, I believe it should remain as a fallback mechanism to ensure that shutdown is handled gracefully under all circumstances. |
Fixes #718
When a duplicate broker with the same node ID starts, it can fence the original broker by overwriting the S3 WAL reservation object or bumping the node epoch. The original broker then hangs indefinitely during shutdown because:
S3Stream.close()blocks waiting for pending requestscloseStreamRPC fails withNODE_EPOCH_EXPIRED, but the error is treated as fatal rather than terminalS3StreamClient.closeStreams()loops forever waiting for streams that can never closeChanges:
S3Stream.close0(): MakeforceUploadbest-effort — catch and log failures rather than blocking the close path. HandleNODE_EPOCH_EXPIRED/NODE_FENCEDerrors fromcloseStreamas successful close, since the new epoch owner is responsible for stream lifecycle.S3StreamClient.closeStreams(): Add a configurable timeout (default 30s, viaAUTOMQ_STREAM_GRACEFUL_CLOSE_TIMEOUT_MSenv var). If graceful close does not complete in time, escalate to force close — force-completing pending requests and unblocking shutdown.Testing strategy:
S3StreamClientandS3Streamunit tests continue to pass, confirming no regression in the happy-path close flow.Committer Checklist (excluded from commit message)