Wait for the interrupted operation to clean up before exit (closes #159)
On SIGINT/SIGTERM the process could exit before the interrupted command cleanup defers ran, leaving decrypted data in the temp directory (the blob cache and the decrypted snapshot database). RunApp now mirrors fx run sequence: start, block on app.Wait(), then app.Stop(), returning only after Stop completes. fx delivers both an OS interrupt and the finished operation Shutdowner.Shutdown() on one channel. Stop runs the OnStop hooks; the operation hook cancels the command and waits for its goroutine to return (bounded by shutdownTimeout) before exit. The old code returned as soon as app.Done fired, without Stop, so a real interrupt unwound to os.Exit while cleanup still ran. Restore loops check the context between chunks and blobs so the wait ends promptly. A cli test drives RunApp through the OnStop hook. Model: opus-4-8
This commit was merged in pull request #189.
This commit is contained in:
@@ -402,6 +402,12 @@ func (s *restoreSession) downloadNextBlobSet(plan *restorePlan) (bool, error) {
|
||||
}
|
||||
|
||||
for _, hash := range plan.blobsNeeded(next) {
|
||||
// Stop between blobs on cancel so an interrupt ends the download
|
||||
// phase promptly rather than fetching the rest of the set.
|
||||
if s.ctx.Err() != nil {
|
||||
return false, s.ctx.Err()
|
||||
}
|
||||
|
||||
blob, ok := s.blobByHash[hash]
|
||||
if !ok {
|
||||
return false, fmt.Errorf("%w: %s", errBlobMissingFromIndex, hash[:16])
|
||||
@@ -1077,6 +1083,12 @@ func (s *restoreSession) writeFileChunks(
|
||||
)
|
||||
|
||||
for _, fc := range fileChunks {
|
||||
// Stop between chunks on cancel so an interrupt does not keep
|
||||
// writing a large file after the operation has been told to stop.
|
||||
if s.ctx.Err() != nil {
|
||||
return bytesWritten, timings, s.ctx.Err()
|
||||
}
|
||||
|
||||
chunkHashStr := fc.ChunkHash.String()
|
||||
|
||||
blobChunk, ok := s.chunkToBlobMap[chunkHashStr]
|
||||
|
||||
Reference in New Issue
Block a user