fix: bound blob cache during restore with LRU eviction to prevent OOM
The restore operation cached every downloaded blob in an unbounded map, which could exhaust system memory when restoring large backups with many unique blobs (each up to 10GB). Replaced with an LRU cache bounded to 1 GiB by default, evicting least-recently-used blobs when the limit is exceeded.
This commit is contained in:
parent
46c2ea3079
commit
0eb07b29d6
@ -109,7 +109,7 @@ func (v *Vaultik) Restore(opts *RestoreOptions) error {
|
|||||||
|
|
||||||
// Step 5: Restore files
|
// Step 5: Restore files
|
||||||
result := &RestoreResult{}
|
result := &RestoreResult{}
|
||||||
blobCache := make(map[string][]byte) // Cache downloaded and decrypted blobs
|
blobCache := newBlobLRUCache(defaultMaxBlobCacheBytes) // LRU cache bounded to ~1 GiB
|
||||||
|
|
||||||
for i, file := range files {
|
for i, file := range files {
|
||||||
if v.ctx.Err() != nil {
|
if v.ctx.Err() != nil {
|
||||||
@ -299,7 +299,7 @@ func (v *Vaultik) restoreFile(
|
|||||||
targetDir string,
|
targetDir string,
|
||||||
identity age.Identity,
|
identity age.Identity,
|
||||||
chunkToBlobMap map[string]*database.BlobChunk,
|
chunkToBlobMap map[string]*database.BlobChunk,
|
||||||
blobCache map[string][]byte,
|
blobCache *blobLRUCache,
|
||||||
result *RestoreResult,
|
result *RestoreResult,
|
||||||
) error {
|
) error {
|
||||||
// Calculate target path - use full original path under target directory
|
// Calculate target path - use full original path under target directory
|
||||||
@ -383,7 +383,7 @@ func (v *Vaultik) restoreRegularFile(
|
|||||||
targetPath string,
|
targetPath string,
|
||||||
identity age.Identity,
|
identity age.Identity,
|
||||||
chunkToBlobMap map[string]*database.BlobChunk,
|
chunkToBlobMap map[string]*database.BlobChunk,
|
||||||
blobCache map[string][]byte,
|
blobCache *blobLRUCache,
|
||||||
result *RestoreResult,
|
result *RestoreResult,
|
||||||
) error {
|
) error {
|
||||||
// Get file chunks in order
|
// Get file chunks in order
|
||||||
@ -417,13 +417,13 @@ func (v *Vaultik) restoreRegularFile(
|
|||||||
|
|
||||||
// Download and decrypt blob if not cached
|
// Download and decrypt blob if not cached
|
||||||
blobHashStr := blob.Hash.String()
|
blobHashStr := blob.Hash.String()
|
||||||
blobData, ok := blobCache[blobHashStr]
|
blobData, ok := blobCache.Get(blobHashStr)
|
||||||
if !ok {
|
if !ok {
|
||||||
blobData, err = v.downloadBlob(ctx, blobHashStr, blob.CompressedSize, identity)
|
blobData, err = v.downloadBlob(ctx, blobHashStr, blob.CompressedSize, identity)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("downloading blob %s: %w", blobHashStr[:16], err)
|
return fmt.Errorf("downloading blob %s: %w", blobHashStr[:16], err)
|
||||||
}
|
}
|
||||||
blobCache[blobHashStr] = blobData
|
blobCache.Put(blobHashStr, blobData)
|
||||||
result.BlobsDownloaded++
|
result.BlobsDownloaded++
|
||||||
result.BytesDownloaded += blob.CompressedSize
|
result.BytesDownloaded += blob.CompressedSize
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user