diff --git a/cmd/ocm-agent/main.go b/cmd/ocm-agent/main.go index 936f119f04108652933e4ac8fa745f32d1bd7d54..3ca68ac97a1720d6dea9d258e47b382838b93d5b 100644 --- a/cmd/ocm-agent/main.go +++ b/cmd/ocm-agent/main.go @@ -353,7 +353,7 @@ func connectionSupervisor( // 恢复大数据进行中会话 if largeReporter != nil { - go largeReporter.Resume(quit) + go largeReporter.Resume(epochCtx.Done()) } // 数据通道服务器 diff --git a/internal/data/large_reporter.go b/internal/data/large_reporter.go index 9e243610a052533270329bbd45a30492b059ba4b..92152d64c40a0ffcc4d31ac6bd7303699805fefb 100644 --- a/internal/data/large_reporter.go +++ b/internal/data/large_reporter.go @@ -772,7 +772,7 @@ func (r *LargeReporter) onError(frame *protocol.Frame) { // // Resume 是尽力而为的:单条失败仅以 WARN 记录,不会中断扫描。它应当 // 在 cmd/ocm-agent/main.go 中、connector 完全建立之后调用一次。 -func (r *LargeReporter) Resume(agentDone <-chan struct{}) { +func (r *LargeReporter) Resume(epochDone <-chan struct{}) { if r.store == nil { return } @@ -783,7 +783,7 @@ func (r *LargeReporter) Resume(agentDone <-chan struct{}) { } for _, row := range rows { select { - case <-agentDone: + case <-epochDone: return default: } diff --git a/internal/data/large_reporter_test.go b/internal/data/large_reporter_test.go index 941a3edcb83a511bbc173ab598fcde6c7b4a4d43..643a9ec170fc9501b431affc59f47e1a30da27c6 100644 --- a/internal/data/large_reporter_test.go +++ b/internal/data/large_reporter_test.go @@ -7,6 +7,7 @@ import ( "crypto/md5" "encoding/hex" "errors" + "os" "path/filepath" "sync" "testing" @@ -165,6 +166,31 @@ func TestLargeReporter_HappyPath_TwoFragments(t *testing.T) { } } +func TestLargeReporter_ResumeStopsWhenEpochEnds(t *testing.T) { + cfg := DefaultLargeReporterConfig() + reporter, sender, store := newTestLargeReporter(t, cfg) + source := filepath.Join(t.TempDir(), "resume.bin") + if err := os.WriteFile(source, []byte("resume payload"), 0o600); err != nil { + t.Fatalf("write source: %v", err) + } + if err := store.Upsert(OngoingTask{ + TaskID: 1, DataID: 2, TotalSize: 14, MD5: "unused", SourcePath: source, + }); err != nil { + t.Fatalf("upsert ongoing task: %v", err) + } + epochDone := make(chan struct{}) + close(epochDone) + + reporter.Resume(epochDone) + + sender.mu.Lock() + sent := len(sender.sent) + sender.mu.Unlock() + if sent != 0 { + t.Fatalf("Resume sent %d frames after epoch cancellation", sent) + } +} + func TestLargeReporter_DirectRequireFragAfterUpload(t *testing.T) { cfg := DefaultLargeReporterConfig() cfg.PerFragmentTimeout = 100 * time.Millisecond