refactor: remove legacy autoflush code paths (bd-xsl9)

Remove dual code paths in the autoflush system. FlushManager is now the
only code path for auto-flush operations.

Changes:
- Remove legacy globals: isDirty, needsFullExport, flushTimer
- Remove flushToJSONL() wrapper function (was backward-compat shim)
- Simplify markDirtyAndScheduleFlush/FullExport to just call FlushManager
- Update tests to use FlushManager or flushToJSONLWithState directly

FlushManager handles all flush state internally in its run() goroutine,
eliminating the need for global state. Sandbox mode and tests that do
not need flushing get a no-op when FlushManager is nil.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Steve Yegge
2025-12-23 01:56:04 -08:00
parent da15363e2b
commit 92e6f4c079
7 changed files with 48 additions and 199 deletions

View File

@@ -16,9 +16,9 @@ import (
"github.com/steveyegge/beads/internal/types"
)
// TestAutoFlushOnExit tests that PersistentPostRun performs final flush before exit
// TestAutoFlushOnExit tests that FlushManager.Shutdown() performs final flush before exit
func TestAutoFlushOnExit(t *testing.T) {
// FIX: Initialize rootCtx for flush operations
// Initialize rootCtx for flush operations
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
@@ -48,15 +48,16 @@ func TestAutoFlushOnExit(t *testing.T) {
storeActive = true
storeMutex.Unlock()
// Reset auto-flush state
// Initialize FlushManager for this test (short debounce for testing)
autoFlushEnabled = true
isDirty = false
if flushTimer != nil {
flushTimer.Stop()
flushTimer = nil
}
// ctx already declared above for rootCtx initialization
oldFlushManager := flushManager
flushManager = NewFlushManager(true, 50*time.Millisecond)
defer func() {
if flushManager != nil {
_ = flushManager.Shutdown()
}
flushManager = oldFlushManager
}()
// Create test issue
issue := &types.Issue{
@@ -75,50 +76,12 @@ func TestAutoFlushOnExit(t *testing.T) {
// Mark dirty (simulating CRUD operation)
markDirtyAndScheduleFlush()
// Simulate PersistentPostRun (exit behavior)
storeMutex.Lock()
storeActive = false
storeMutex.Unlock()
flushMutex.Lock()
needsFlush := isDirty && autoFlushEnabled
if needsFlush {
if flushTimer != nil {
flushTimer.Stop()
flushTimer = nil
}
isDirty = false
}
flushMutex.Unlock()
if needsFlush {
// Manually perform flush logic (simulating PersistentPostRun)
storeMutex.Lock()
storeActive = true // Temporarily re-enable for this test
storeMutex.Unlock()
issues, err := testStore.SearchIssues(ctx, "", types.IssueFilter{})
if err == nil {
allDeps, _ := testStore.GetAllDependencyRecords(ctx)
for _, iss := range issues {
iss.Dependencies = allDeps[iss.ID]
}
tempPath := jsonlPath + ".tmp"
f, err := os.Create(tempPath)
if err == nil {
encoder := json.NewEncoder(f)
for _, iss := range issues {
encoder.Encode(iss)
}
f.Close()
os.Rename(tempPath, jsonlPath)
}
}
storeMutex.Lock()
storeActive = false
storeMutex.Unlock()
// Simulate PersistentPostRun exit behavior - shutdown FlushManager
// This performs the final flush before exit
if err := flushManager.Shutdown(); err != nil {
t.Fatalf("FlushManager shutdown failed: %v", err)
}
flushManager = nil // Prevent double shutdown in defer
testStore.Close()
@@ -223,12 +186,8 @@ func TestAutoFlushJSONLContent(t *testing.T) {
}
}
// Mark dirty and flush immediately
flushMutex.Lock()
isDirty = true
flushMutex.Unlock()
flushToJSONL()
// Flush immediately (forces export)
flushToJSONLWithState(flushState{forceDirty: true})
// Verify JSONL file exists
if _, err := os.Stat(expectedJSONLPath); os.IsNotExist(err) {