mirror of
https://github.com/restic/restic.git
synced 2025-08-14 04:27:42 +00:00
repository: Rework blob saving to use an async pack uploader
Previously, SaveAndEncrypt would assemble blobs into packs and either return immediately if the pack is not yet full or upload the pack file otherwise. The upload will block the current goroutine until it finishes. Now, the upload is done using separate goroutines. This requires changes to the error handling. As uploads are no longer tied to a SaveAndEncrypt call, failed uploads are signaled using an errgroup. To count the uploaded amount of data, the pack header overhead is no longer returned by `packer.Finalize` but rather by `packer.HeaderOverhead`. This helper method is necessary to continue returning the pack header overhead directly to the responsible call to `repository.SaveBlob`. Without the method this would not be possible, as packs are finalized asynchronously.
This commit is contained in:
@@ -22,6 +22,7 @@ import (
|
||||
"github.com/restic/restic/internal/restic"
|
||||
"github.com/restic/restic/internal/test"
|
||||
rtest "github.com/restic/restic/internal/test"
|
||||
"golang.org/x/sync/errgroup"
|
||||
)
|
||||
|
||||
var testSizes = []int{5, 23, 2<<18 + 23, 1 << 20}
|
||||
@@ -43,6 +44,9 @@ func testSave(t *testing.T, version uint) {
|
||||
|
||||
id := restic.Hash(data)
|
||||
|
||||
var wg errgroup.Group
|
||||
repo.StartPackUploader(context.TODO(), &wg)
|
||||
|
||||
// save
|
||||
sid, _, _, err := repo.SaveBlob(context.TODO(), restic.DataBlob, data, restic.ID{}, false)
|
||||
rtest.OK(t, err)
|
||||
@@ -82,6 +86,9 @@ func testSaveFrom(t *testing.T, version uint) {
|
||||
|
||||
id := restic.Hash(data)
|
||||
|
||||
var wg errgroup.Group
|
||||
repo.StartPackUploader(context.TODO(), &wg)
|
||||
|
||||
// save
|
||||
id2, _, _, err := repo.SaveBlob(context.TODO(), restic.DataBlob, data, id, false)
|
||||
rtest.OK(t, err)
|
||||
@@ -187,6 +194,9 @@ func testLoadBlob(t *testing.T, version uint) {
|
||||
_, err := io.ReadFull(rnd, buf)
|
||||
rtest.OK(t, err)
|
||||
|
||||
var wg errgroup.Group
|
||||
repo.StartPackUploader(context.TODO(), &wg)
|
||||
|
||||
id, _, _, err := repo.SaveBlob(context.TODO(), restic.DataBlob, buf, restic.ID{}, false)
|
||||
rtest.OK(t, err)
|
||||
rtest.OK(t, repo.Flush(context.Background()))
|
||||
@@ -220,6 +230,9 @@ func benchmarkLoadBlob(b *testing.B, version uint) {
|
||||
_, err := io.ReadFull(rnd, buf)
|
||||
rtest.OK(b, err)
|
||||
|
||||
var wg errgroup.Group
|
||||
repo.StartPackUploader(context.TODO(), &wg)
|
||||
|
||||
id, _, _, err := repo.SaveBlob(context.TODO(), restic.DataBlob, buf, restic.ID{}, false)
|
||||
rtest.OK(b, err)
|
||||
rtest.OK(b, repo.Flush(context.Background()))
|
||||
@@ -389,6 +402,9 @@ func benchmarkLoadIndex(b *testing.B, version uint) {
|
||||
|
||||
// saveRandomDataBlobs generates random data blobs and saves them to the repository.
|
||||
func saveRandomDataBlobs(t testing.TB, repo restic.Repository, num int, sizeMax int) {
|
||||
var wg errgroup.Group
|
||||
repo.StartPackUploader(context.TODO(), &wg)
|
||||
|
||||
for i := 0; i < num; i++ {
|
||||
size := rand.Int() % sizeMax
|
||||
|
||||
|
Reference in New Issue
Block a user