corso/src/pkg/store/backup.go
ashmrtn 9eed02013e
Batch deletion of individual backup components (#4023)
Reduce the number of kopia manifest blobs
created during backup deletion by batching
the deletion of snapshots and the backup
model into a single kopia operation

Also reorangizes/updates test code for
backup deletion

---

#### Does this PR need a docs update or release note?

- [ ]  Yes, it's included
- [ ] 🕐 Yes, but in a later PR
- [x]  No

#### Type of change

- [ ] 🌻 Feature
- [ ] 🐛 Bugfix
- [ ] 🗺️ Documentation
- [x] 🤖 Supportability/Tests
- [ ] 💻 CI/Deployment
- [x] 🧹 Tech Debt/Cleanup

#### Issue(s)

* #4019

#### Test Plan

- [ ] 💪 Manual
- [x]  Unit test
- [x] 💚 E2E
2023-08-14 19:38:43 +00:00

140 lines
3.0 KiB
Go

package store
import (
"context"
"github.com/alcionai/clues"
"github.com/kopia/kopia/repo/manifest"
"github.com/alcionai/corso/src/internal/model"
"github.com/alcionai/corso/src/pkg/backup"
"github.com/alcionai/corso/src/pkg/path"
)
type queryFilters struct {
tags map[string]string
}
type FilterOption func(*queryFilters)
func (q *queryFilters) populate(qf ...FilterOption) {
if len(qf) == 0 {
return
}
q.tags = map[string]string{}
for _, fn := range qf {
fn(q)
}
}
// Service ensures the retrieved backups only match
// the specified service.
func Service(pst path.ServiceType) FilterOption {
return func(qf *queryFilters) {
qf.tags[model.ServiceTag] = pst.String()
}
}
type (
BackupWrapper interface {
BackupGetterDeleter
GetBackups(
ctx context.Context,
filters ...FilterOption,
) ([]*backup.Backup, error)
}
BackupGetterDeleter interface {
BackupGetter
BackupDeleter
}
BackupGetter interface {
GetBackup(ctx context.Context, backupID model.StableID) (*backup.Backup, error)
}
BackupDeleter interface {
DeleteBackup(ctx context.Context, backupID model.StableID) error
}
ModelDeleter interface {
DeleteWithModelStoreIDs(ctx context.Context, ids ...manifest.ID) error
}
BackupGetterModelDeleter interface {
BackupGetter
ModelDeleter
}
Storer interface {
Delete(ctx context.Context, s model.Schema, id model.StableID) error
Get(ctx context.Context, s model.Schema, id model.StableID, data model.Model) error
GetIDsForType(ctx context.Context, s model.Schema, tags map[string]string) ([]*model.BaseModel, error)
GetWithModelStoreID(ctx context.Context, s model.Schema, id manifest.ID, data model.Model) error
Put(ctx context.Context, s model.Schema, m model.Model) error
Update(ctx context.Context, s model.Schema, m model.Model) error
ModelDeleter
}
BackupStorer interface {
Storer
BackupWrapper
}
)
type wrapper struct {
Storer
}
func NewWrapper(s Storer) *wrapper {
return &wrapper{Storer: s}
}
// GetBackup gets a single backup by id.
func (w wrapper) GetBackup(ctx context.Context, backupID model.StableID) (*backup.Backup, error) {
b := backup.Backup{}
err := w.Get(ctx, model.BackupSchema, backupID, &b)
if err != nil {
return nil, clues.Wrap(err, "getting backup")
}
return &b, nil
}
// GetDetailsFromBackupID retrieves all backups in the model store.
func (w wrapper) GetBackups(
ctx context.Context,
filters ...FilterOption,
) ([]*backup.Backup, error) {
q := &queryFilters{}
q.populate(filters...)
bms, err := w.GetIDsForType(ctx, model.BackupSchema, q.tags)
if err != nil {
return nil, err
}
bs := make([]*backup.Backup, len(bms))
for i, bm := range bms {
b := &backup.Backup{}
err := w.GetWithModelStoreID(ctx, model.BackupSchema, bm.ModelStoreID, b)
if err != nil {
return nil, err
}
bs[i] = b
}
return bs, nil
}
// DeleteBackup deletes the backup and its details entry from the model store.
func (w wrapper) DeleteBackup(ctx context.Context, backupID model.StableID) error {
return w.Delete(ctx, model.BackupSchema, backupID)
}