forked from TrueCloudLab/restic
65 lines
1.7 KiB
Go
65 lines
1.7 KiB
Go
package repository
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/restic/restic/internal/debug"
|
|
"github.com/restic/restic/internal/restic"
|
|
"golang.org/x/sync/errgroup"
|
|
)
|
|
|
|
// ParallelWorkFunc gets one file ID to work on. If an error is returned,
|
|
// processing stops. When the contect is cancelled the function should return.
|
|
type ParallelWorkFunc func(ctx context.Context, id string) error
|
|
|
|
// ParallelIDWorkFunc gets one restic.ID to work on. If an error is returned,
|
|
// processing stops. When the context is cancelled the function should return.
|
|
type ParallelIDWorkFunc func(ctx context.Context, id restic.ID) error
|
|
|
|
// FilesInParallel runs n workers of f in parallel, on the IDs that
|
|
// repo.List(t) yields. If f returns an error, the process is aborted and the
|
|
// first error is returned.
|
|
func FilesInParallel(ctx context.Context, repo restic.Lister, t restic.FileType, n int, f ParallelWorkFunc) error {
|
|
g, ctx := errgroup.WithContext(ctx)
|
|
|
|
ch := make(chan string, n)
|
|
g.Go(func() error {
|
|
defer close(ch)
|
|
return repo.List(ctx, t, func(fi restic.FileInfo) error {
|
|
select {
|
|
case <-ctx.Done():
|
|
case ch <- fi.Name:
|
|
}
|
|
return nil
|
|
})
|
|
})
|
|
|
|
for i := 0; i < n; i++ {
|
|
g.Go(func() error {
|
|
for name := range ch {
|
|
err := f(ctx, name)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
})
|
|
}
|
|
|
|
return g.Wait()
|
|
}
|
|
|
|
// ParallelWorkFuncParseID converts a function that takes a restic.ID to a
|
|
// function that takes a string. Filenames that do not parse as a restic.ID
|
|
// are ignored.
|
|
func ParallelWorkFuncParseID(f ParallelIDWorkFunc) ParallelWorkFunc {
|
|
return func(ctx context.Context, s string) error {
|
|
id, err := restic.ParseID(s)
|
|
if err != nil {
|
|
debug.Log("invalid ID %q: %v", id, err)
|
|
return nil
|
|
}
|
|
|
|
return f(ctx, id)
|
|
}
|
|
}
|