diff --git a/db.go b/db.go index 4deca94..cfc848c 100644 --- a/db.go +++ b/db.go @@ -163,6 +163,11 @@ func (db *DB) Open() (err error) { m[r.Name()] = struct{}{} } + // Clear old temporary files that my have been left from a crash. + if err := removeTmpFiles(db.MetaPath()); err != nil { + return fmt.Errorf("cannot remove tmp files: %w", err) + } + // Start monitoring SQLite database in a separate goroutine. db.wg.Add(1) go func() { defer db.wg.Done(); db.monitor() }() diff --git a/litestream.go b/litestream.go index 3e53d29..44e8b3d 100644 --- a/litestream.go +++ b/litestream.go @@ -7,6 +7,7 @@ import ( "fmt" "io" "os" + "path/filepath" "strconv" "strings" @@ -123,6 +124,20 @@ func FormatWALFilename(index int) string { return fmt.Sprintf("%016x%s", index, WALExt) } +// removeTmpFiles recursively finds and removes .tmp files. +func removeTmpFiles(root string) error { + return filepath.Walk(root, func(path string, info os.FileInfo, err error) error { + if err != nil { + return nil // skip errored files + } else if info.IsDir() { + return nil // skip directories + } else if !strings.HasSuffix(path, ".tmp") { + return nil // skip non-temp files + } + return os.Remove(path) + }) +} + // HexDump returns hexdump output but with duplicate lines removed. func HexDump(b []byte) string { const prefixN = len("00000000") diff --git a/replicator.go b/replicator.go index 4c5ba2c..2f4dabc 100644 --- a/replicator.go +++ b/replicator.go @@ -92,6 +92,11 @@ func (r *FileReplicator) Stop() { // monitor runs in a separate goroutine and continuously replicates the DB. func (r *FileReplicator) monitor(ctx context.Context) { + // Clear old temporary files that my have been left from a crash. + if err := removeTmpFiles(r.dst); err != nil { + log.Printf("%s(%s): cannot remove tmp files: %w", r.db.Path(), r.Name(), err) + } + // Continuously check for new data to replicate. ch := make(chan struct{}) close(ch)