Understanding the Agentsview Resync Process and Its Triggers
The agentsview resync process is an atomic, heavyweight rebuild of the SQLite database that re-parses every session file from source, copies protection metadata to a temporary database, and swaps it into production, triggered by CLI flags, HTTP API calls, data-version changes, or file-watcher mass-change events.
Agentsview stores session metadata in a SQLite database and normally performs incremental syncs using file fingerprints to skip unchanged content. When the database diverges from source files, after storage backend migrations, or when permanent exclusions need reconciliation, the resync process safely rebuilds the entire index without per-row deletion overhead.
What Is the Agentsview Resync Process?
Unlike the standard SyncAll flow, which parses only changed files and updates the database incrementally, a full resync is a complete reconstruction that guarantees consistency between the filesystem and the database.
The Eight-Step Atomic Rebuild
The implementation in internal/sync/engine.go follows a strict pipeline to ensure safety and atomicity:
-
Lock the sync pipeline – The engine acquires
e.syncMuto block concurrent sync operations for the duration of the rebuild.e.syncMu.Lock() defer e.syncMu.Unlock() -
Create a temporary database – The original database path is preserved while a new file at
<orig-path>-resyncis opened for the rebuild.origPath := origDB.Path() tempPath := origPath + "-resync" newDB, err := db.Open(tempPath) -
Copy protection data – Excluded session IDs and trashed sessions are copied from the original database via
CopyExcludedSessionsFromto ensure permanent deletions are respected in the new build. -
Disable full-text search (FTS) during bulk loading – The temporary database drops its FTS index, processes all insertions via
syncWriteBulk, then rebuilds the index once after bulk completion to avoid trigger overhead. -
Run full-file discovery and bulk parse – The engine calls
e.syncAllLocked(..., syncWriteBulk, true)to parse every discoverable session file, ignoring the skip-cache and treating the operation as a fresh import. -
Evaluate swap conditions – After loading, the engine aborts the swap if the resync was cancelled, if discovery yielded no new data while the old database held non-OpenCode sessions, or if parse failures outnumbered successes. Certain "preserved-only" outcomes are allowed to proceed.
-
Atomic database replacement – Upon successful validation, the temporary file is renamed over the original database using atomic filesystem operations, and the original database handle is reopened. This avoids the performance cost of deleting and reinserting millions of rows.
-
Restore runtime state – The engine restores the in-memory skip-cache (or clears it if the resync succeeded), updates
lastSyncandlastSyncStats, and notifies theEmitter(SSE broadcaster) of completion.
What Triggers the Agentsview Resync?
The resync process can be initiated through five distinct mechanisms, each targeting different operational scenarios.
Manual CLI Invocation
Users can force a full rebuild via command-line flags. The cmd/agentsview/sync.go handler parses --full (or --resync) and forwards the request to Engine.ResyncAll.
agentsview sync --full
# Equivalent to:
agentsview sync --resync
The underlying Go invocation:
engine.ResyncAll(ctx, nil) // Full rebuild with no progress callback
HTTP API Endpoint
The server exposes a synchronous endpoint at POST /api/v1/sync that accepts a full query parameter. When internal/server/sync.go detects ?full=true, it invokes engine.ResyncAll instead of the standard sync.
POST /api/v1/sync?full=true HTTP/1.1
Host: localhost:8080
Periodic Data-Version Checks
A background ticker runs every 15 minutes in cmd/agentsview/serve_lifecycle.go. Normally triggering SyncAll, it calls ResyncAll when the storage backend's data-version has changed (e.g., after migrations), detected via engine.DataVersionChanged().
// Runs every 15 minutes
if engine.DataVersionChanged() {
engine.ResyncAll(ctx, nil) // Automatic full rebuild
}
File-Watcher Mass-Change Detection
When the file-watcher detects a mass-change pattern (such as an entire directory being replaced), it sets engine.forceParse in internal/sync/engine.go. This forces a bulk parse operation functionally equivalent to a resync, clearing stale skip-cache entries to prevent missed updates.
Crash Recovery and Corruption Handling
On startup, the engine checks for stale temporary databases (*-resync) from previous crashed resyncs and removes them via removeTempDB(tempPath). If e.db.IsCorrupt() returns true, the server may automatically invoke ResyncAll to rebuild the database from source files rather than attempting repair.
Summary
- Atomic rebuild: The agentsview resync process constructs a new database in a temporary file and performs an atomic rename to eliminate partial-state risks.
- Protection preservation: Excluded sessions and trash markers are explicitly copied to the temporary database before the swap.
- Performance optimization: FTS indexes are dropped during bulk loading and rebuilt once afterward to minimize trigger overhead.
- Multiple triggers: Resyncs can be initiated manually via CLI (
--full), HTTP API (?full=true), periodic data-version checks, file-watcher mass-change detection, or automatic corruption recovery. - Concurrency safety: The entire operation is guarded by
Engine.syncMuto prevent race conditions with standard sync operations.
Frequently Asked Questions
How does agentsview ensure atomicity during a resync?
The engine writes to a temporary database file suffixed with -resync and performs a filesystem rename operation only after successful validation. This atomic swap ensures that the production database is never in a partially-rebuilt state, and concurrent readers see either the old complete database or the new complete database, never a hybrid.
What happens if a resync is cancelled mid-operation?
If the context is cancelled or validation fails (such as when parse failures exceed successes), the engine aborts the swap and deletes the temporary database. The original database remains untouched and continues serving requests, preserving data integrity.
Can I trigger a resync programmatically from Go code?
Yes. Import the sync package and call ResyncAll with a context and optional progress callback. This is useful for testing or building custom orchestration tools.
ctx := context.Background()
stats := engine.ResyncAll(ctx, func(p sync.Progress) {
fmt.Printf("resync %d of %d files\n", p.Done, p.Total)
})
if stats.Aborted {
log.Fatalf("Resync failed: %v", stats.Warnings)
}
Why does agentsview disable FTS during bulk loading?
Dropping the FTS index before bulk insertion and rebuilding it afterward prevents SQLite from executing per-row trigger updates during the millions of writes typical in a full resync. According to the internal/db/db.go implementation, this strategy reduces total resync time significantly compared to incremental index maintenance.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →