Repository navigation
fix(pushsync): prevent silent chunk loss on shallow receipts - #5390
gacevicljubisa wants to merge 21 commits into
Conversation
| // error budget and wait for any other inflight parallel pushes | ||
| // (e.g. multiplex forwards) before giving up. Only return | ||
| // ErrShallowReceipt once the entire budget is spent. | ||
| shallowReceiptResult = result.receipt |
There was a problem hiding this comment.
you've removed the skiplist addition line that was on the left side of the diff (L493). any particular reason?
There was a problem hiding this comment.
actually it is not removed, it is on the common failure path at pushsync.go:524
| // (e.g. multiplex forwards) before giving up. Only return | ||
| // ErrShallowReceipt once the entire budget is spent. | ||
| shallowReceiptResult = result.receipt | ||
| result.err = err |
There was a problem hiding this comment.
not sure if I understand this fully, but this statement and the next one in the else block seem like assigned but never used where is result.err used?
| // Retry budget exhausted: no peer in the correct neighborhood stored the | ||
| // chunk. Report CouldNotSync rather than Synced to avoid falsely marking | ||
| // the chunk as delivered. | ||
| if err := s.storer.Report(ctx, op.Chunk, storage.ChunkCouldNotSync); err != nil { |
There was a problem hiding this comment.
Changing to ChunkCouldNotSync, will cause some false reporting because the ChunkCouldNotSync state is not checked and updated in uploadstore.go ->Report function. Maybe you would need to alsi include in that switch statement also ChunkCouldNotSync.
| // is outside our AOR we would store it in a low bin and unreserve() | ||
| // would evict it almost immediately, leaving the chunk nowhere on the | ||
| // network while the origin believes it was delivered. | ||
| if swarm.Proximity(ps.address.Bytes(), chunkAddress.Bytes()) < rad { |
There was a problem hiding this comment.
What happens if you have doubling set on, and the chunk is saved into a sister neighborhood? Should we have here a check based on the committed depth?
Updated comments to correct formatting and clarity.
1e13f0a to
99a2bc6
Compare
|
This looks good to me still. |
… to be the closest
…-depth-chunk-loss
…of-depth refusals
Checklist
Description
On master, pushsync can report a chunk as synced when no node in its neighborhood stores it. The upload returns 201 and the tag says Synced. No other node can retrieve such a chunk, and the storer evicts it when its reserve runs over capacity. This PR turns that false success into an error or a retry.
What changes
po >= r. Master also acceptedpo >= r - 1on a node without capacity doubling. The tolerance is removed fromnode.go, andcheckReceiptalso returns the PO.ErrShallowReceiptonly when the budget or the peer list runs out. On master the first shallow receipt ended the call.ErrWantSelfa forwarder now widens the peer filter, like onErrNotFound, and waits 600 ms when peers are skipped for overdraft. A forwarder stores the chunk only inside its own AOR. Outside its AOR it returnsErrOutOfDepthStoringto the previous hop. On master it stored the chunk and signed a receipt.ErrOutOfDepthStoring. The deferred pusher counts it as one of its 6 calls. A direct upload fails at once. On master the origin stored the chunk on itself.ChunkCouldNotSyncinstead ofChunkSynced. The tag's Synced count stays below Split. A direct upload returnsErrCouldNotSync, so the API answers 500 instead of 201.ErrNotFoundbefore it submits the chunk again, instead of a tight loop.out_of_depth_storingandorigin_no_peers_leftin pushsync,total_could_not_syncin pusher.total_syncednow counts only chunks with a valid receipt or stored by this node.What does not change
errSkip.ErrShallowReceipt.Follow-up
PR #5667 is stacked on this PR. It gives a chunk one more round when a direct upload gets
ErrOutOfDepthStoring, so the two PRs go together.Open API Spec Version Changes (if applicable)
Motivation and Context (Optional)
Related Issue (Optional)
Screenshots (if appropriate):