refactor(daemon): consolidate sync functions to reduce duplication
Consolidate createSyncFunc and createLocalSyncFunc into a shared performSync function, following the same pattern used for: - performExport (used by createExportFunc and createLocalExportFunc) - performAutoImport (used by createAutoImportFunc and createLocalAutoImportFunc) The new performSync takes a skipGit bool parameter that skips all git operations (commits, pulls, pushes) and 3-way merge when true. This reduces ~60 lines of duplicated code and provides a single implementation to maintain. Closes: bd-73u 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
+23
-77
@@ -608,11 +608,27 @@ func performAutoImport(ctx context.Context, store storage.Storage, skipGit bool,
|
|||||||
|
|
||||||
// createSyncFunc creates a function that performs full sync cycle (export, commit, pull, import, push)
|
// createSyncFunc creates a function that performs full sync cycle (export, commit, pull, import, push)
|
||||||
func createSyncFunc(ctx context.Context, store storage.Storage, autoCommit, autoPush bool, log daemonLogger) func() {
|
func createSyncFunc(ctx context.Context, store storage.Storage, autoCommit, autoPush bool, log daemonLogger) func() {
|
||||||
|
return performSync(ctx, store, autoCommit, autoPush, false, log)
|
||||||
|
}
|
||||||
|
|
||||||
|
// createLocalSyncFunc creates a function that performs local-only sync (export only, no git).
|
||||||
|
// Used when daemon is started with --local flag.
|
||||||
|
func createLocalSyncFunc(ctx context.Context, store storage.Storage, log daemonLogger) func() {
|
||||||
|
return performSync(ctx, store, false, false, true, log)
|
||||||
|
}
|
||||||
|
|
||||||
|
// performSync is the shared implementation for sync functions.
|
||||||
|
// skipGit: if true, skips all git operations (commits, pulls, pushes, 3-way merge).
|
||||||
|
func performSync(ctx context.Context, store storage.Storage, autoCommit, autoPush, skipGit bool, log daemonLogger) func() {
|
||||||
return func() {
|
return func() {
|
||||||
syncCtx, syncCancel := context.WithTimeout(ctx, 2*time.Minute)
|
syncCtx, syncCancel := context.WithTimeout(ctx, 2*time.Minute)
|
||||||
defer syncCancel()
|
defer syncCancel()
|
||||||
|
|
||||||
log.log("Starting sync cycle...")
|
mode := "sync cycle"
|
||||||
|
if skipGit {
|
||||||
|
mode = "local sync cycle"
|
||||||
|
}
|
||||||
|
log.log("Starting %s...", mode)
|
||||||
|
|
||||||
jsonlPath := findJSONLPath()
|
jsonlPath := findJSONLPath()
|
||||||
if jsonlPath == "" {
|
if jsonlPath == "" {
|
||||||
@@ -682,6 +698,12 @@ func createSyncFunc(ctx context.Context, store storage.Storage, autoCommit, auto
|
|||||||
log.log("Warning: failed to update database mtime: %v", err)
|
log.log("Warning: failed to update database mtime: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Skip git operations and 3-way merge in local mode
|
||||||
|
if skipGit {
|
||||||
|
log.log("Local %s complete", mode)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Capture left snapshot (pre-pull state) for 3-way merge
|
// Capture left snapshot (pre-pull state) for 3-way merge
|
||||||
// This is mandatory for deletion tracking integrity
|
// This is mandatory for deletion tracking integrity
|
||||||
// In multi-repo mode, capture snapshots for all JSONL files
|
// In multi-repo mode, capture snapshots for all JSONL files
|
||||||
@@ -836,79 +858,3 @@ func createSyncFunc(ctx context.Context, store storage.Storage, autoCommit, auto
|
|||||||
log.log("Sync cycle complete")
|
log.log("Sync cycle complete")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// createLocalSyncFunc creates a function that performs local-only sync (export only, no git).
|
|
||||||
// Used when daemon is started with --local flag.
|
|
||||||
func createLocalSyncFunc(ctx context.Context, store storage.Storage, log daemonLogger) func() {
|
|
||||||
return func() {
|
|
||||||
syncCtx, syncCancel := context.WithTimeout(ctx, 2*time.Minute)
|
|
||||||
defer syncCancel()
|
|
||||||
|
|
||||||
log.log("Starting local sync cycle...")
|
|
||||||
|
|
||||||
jsonlPath := findJSONLPath()
|
|
||||||
if jsonlPath == "" {
|
|
||||||
log.log("Error: JSONL path not found")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for exclusive lock before processing database
|
|
||||||
beadsDir := filepath.Dir(jsonlPath)
|
|
||||||
skip, holder, err := types.ShouldSkipDatabase(beadsDir)
|
|
||||||
if skip {
|
|
||||||
if err != nil {
|
|
||||||
log.log("Skipping database (lock check failed: %v)", err)
|
|
||||||
} else {
|
|
||||||
log.log("Skipping database (locked by %s)", holder)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if holder != "" {
|
|
||||||
log.log("Removed stale lock (%s), proceeding with sync", holder)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Integrity check: validate before export
|
|
||||||
if err := validatePreExport(syncCtx, store, jsonlPath); err != nil {
|
|
||||||
log.log("Pre-export validation failed: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for duplicate IDs (database corruption)
|
|
||||||
if err := checkDuplicateIDs(syncCtx, store); err != nil {
|
|
||||||
log.log("Duplicate ID check failed: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for orphaned dependencies (warns but doesn't fail)
|
|
||||||
if orphaned, err := checkOrphanedDeps(syncCtx, store); err != nil {
|
|
||||||
log.log("Orphaned dependency check failed: %v", err)
|
|
||||||
} else if len(orphaned) > 0 {
|
|
||||||
log.log("Found %d orphaned dependencies: %v", len(orphaned), orphaned)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := exportToJSONLWithStore(syncCtx, store, jsonlPath); err != nil {
|
|
||||||
log.log("Export failed: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
log.log("Exported to JSONL")
|
|
||||||
|
|
||||||
// Update export metadata
|
|
||||||
multiRepoPaths := getMultiRepoJSONLPaths()
|
|
||||||
if multiRepoPaths != nil {
|
|
||||||
for _, path := range multiRepoPaths {
|
|
||||||
repoKey := getRepoKeyForPath(path)
|
|
||||||
updateExportMetadata(syncCtx, store, path, log, repoKey)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
updateExportMetadata(syncCtx, store, jsonlPath, log, "")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update database mtime to be >= JSONL mtime
|
|
||||||
dbPath := filepath.Join(beadsDir, "beads.db")
|
|
||||||
if err := TouchDatabaseFile(dbPath, jsonlPath); err != nil {
|
|
||||||
log.log("Warning: failed to update database mtime: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
log.log("Local sync cycle complete")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user