mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2026-11-06 03:57:48 +01:00
filer: deliver meta-log events under their stream position, not their stamp (#12084)
* filer: deliver meta-log events under their stream position, not their stamp A mutation's event timestamp is stamped before the filer store write so the entry and its event share a commit time, while the log-buffer append happens after the write. A write delayed behind later-stamped mutations keeps its early stamp in the payload while AddDataToBuffer bumps LogEntry.TsNs to keep the stream monotone - so subscribers could receive events whose payload TsNs arrives out of order. Consumers treat the delivered TsNs as a stream position (cursors, watermarks, replay windows). The s3 lifecycle daily-run drains events in order and pins its per-shard cursor behind the first not-yet-due match; an event delivered with a stale stamp after the cursor already passed it is filtered out forever and its pending match silently never fires - the flaky test_lifecyclev2_expiration signature of exactly one object of a same-rule pair surviving, with errors=0 on every pass. Normalize event.TsNs to logEntry.TsNs at delivery (and for the skeleton-filtered heartbeat) so delivered timestamps are monotone by construction. The commit-time stamp remains available on the entries themselves via CommitTsNs. * pb,filer: stamp metadata events with a mutation timestamp TsNs on the wire now carries the delivery stream position, so the mutation's commit stamp needs its own field. Add mutation_ts_ns to SubscribeMetadataResponse and set it when the event is created. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com> * filer: carry the mutation stamp through event delivery Delivery rewrites TsNs to the stream position; the payload stamp survives in MutationTsNs, backfilled from TsNs for payloads written before the field existed. The notification callback forwards it to the wire message. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com> * pb: normalize chunk-replay timestamps like eachLogEntryFn ReadLogFileRefs bypasses the server decode path, so a delayed append still arrived under its stale payload stamp and could hide behind a subscriber cursor. Deliver the stream position and preserve the stamp in MutationTsNs. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com> * filer: order replay and tombstones by the mutation stamp Replay treated the delivered TsNs as the commit time, so a peer write delayed in its own log could overwrite a newer local entry. Compare and stamp with MutationTsNs, falling back to TsNs for older peers. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com> * remote.sync: carry the mutation stamp through reshaped renames Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com> * filer: test replay ordering on the mutation stamp * filer: tombstone remote deletes by delivery position, order by commit stamp * filer: keep the peer commit stamp when restamping aggregated events * pb: keep the log cursor on the entry position past callback restamps --------- Co-authored-by: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
1 parent
68565fa883
commit
72ac424198
16 files changed
+469
-139
No files matched your search
@@ -558,6 +558,14 @@ func (logBuffer *LogBuffer) AddLogEntryToBuffer(logEntry *filer_pb.LogEntry) err
|
||||
}
|
||||
|
||||
func (logBuffer *LogBuffer) AddDataToBuffer(partitionKey, data []byte, processingTsNs int64) error {
|
||||
_, err := logBuffer.AddDataToBufferAndGetTs(partitionKey, data, processingTsNs)
|
||||
return err
|
||||
}
|
||||
|
||||
// AddDataToBufferAndGetTs appends like AddDataToBuffer and returns the
|
||||
// position the entry was assigned, bumped past processingTsNs when the
|
||||
// buffer must stay monotone.
|
||||
func (logBuffer *LogBuffer) AddDataToBufferAndGetTs(partitionKey, data []byte, processingTsNs int64) (int64, error) {
|
||||
|
||||
// An entry this large gets a window to itself, so it will seal and copy one;
|
||||
// wait for the queue to have room before joining the queue for the lock.
|
||||
@@ -582,7 +590,7 @@ func (logBuffer *LogBuffer) AddDataToBuffer(partitionKey, data []byte, processin
|
||||
}
|
||||
|
||||
if !logBuffer.beginWrite() {
|
||||
return ErrBufferStopped
|
||||
return 0, ErrBufferStopped
|
||||
}
|
||||
var toFlush *dataToFlush
|
||||
var marshalErr error
|
||||
@@ -653,7 +661,7 @@ func (logBuffer *LogBuffer) AddDataToBuffer(partitionKey, data []byte, processin
|
||||
if size < 0 || size > math.MaxInt-4 || size > maxBufferSize-4 {
|
||||
marshalErr = fmt.Errorf("message size %d exceeds maximum allowed size", size)
|
||||
glog.Errorf("%v", marshalErr)
|
||||
return marshalErr
|
||||
return 0, marshalErr
|
||||
}
|
||||
// Fit the entry exactly. Doubling left room for a second oversized
|
||||
// record in the same window, which only doubles the flush copy and
|
||||
@@ -669,7 +677,7 @@ func (logBuffer *LogBuffer) AddDataToBuffer(partitionKey, data []byte, processin
|
||||
if _, err := logEntry.MarshalToSizedBufferVT(logBuffer.buf[logBuffer.pos+4 : logBuffer.pos+4+size]); err != nil {
|
||||
marshalErr = fmt.Errorf("failed to marshal LogEntry: %w", err)
|
||||
glog.Errorf("%v", marshalErr)
|
||||
return marshalErr
|
||||
return 0, marshalErr
|
||||
}
|
||||
logBuffer.idx = append(logBuffer.idx, logBuffer.pos)
|
||||
util.Uint32toBytes(logBuffer.sizeBuf, uint32(size))
|
||||
@@ -684,7 +692,7 @@ func (logBuffer *LogBuffer) AddDataToBuffer(partitionKey, data []byte, processin
|
||||
}
|
||||
|
||||
logBuffer.offset++
|
||||
return nil
|
||||
return logEntry.TsNs, nil
|
||||
}
|
||||
|
||||
func (logBuffer *LogBuffer) IsStopping() bool {
|
||||
|
||||
Reference in new issue
Block a user