First pass for updating code outside of the path package to comply with ServiceResource tuple slices. Compliance is still incomplete, so the build and tests will still fail. Changes in this PR are focused on the easier-to-make changes, mostly generating ServiceResources where there were previously manual declarations of service and resource.
158 lines
3.7 KiB
Go
158 lines
3.7 KiB
Go
package graph
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/alcionai/clues"
|
|
|
|
"github.com/alcionai/corso/src/internal/data"
|
|
"github.com/alcionai/corso/src/internal/m365/support"
|
|
"github.com/alcionai/corso/src/pkg/fault"
|
|
"github.com/alcionai/corso/src/pkg/path"
|
|
)
|
|
|
|
var _ data.BackupCollection = prefixCollection{}
|
|
|
|
// TODO: move this out of graph. /data would be a much better owner
|
|
// for a generic struct like this. However, support.StatusUpdater makes
|
|
// it difficult to extract from this package in a generic way.
|
|
type prefixCollection struct {
|
|
full path.Path
|
|
prev path.Path
|
|
su support.StatusUpdater
|
|
state data.CollectionState
|
|
}
|
|
|
|
func (c prefixCollection) Items(ctx context.Context, _ *fault.Bus) <-chan data.Stream {
|
|
res := make(chan data.Stream)
|
|
close(res)
|
|
|
|
s := support.CreateStatus(ctx, support.Backup, 0, support.CollectionMetrics{}, "")
|
|
c.su(s)
|
|
|
|
return res
|
|
}
|
|
|
|
func (c prefixCollection) FullPath() path.Path {
|
|
return c.full
|
|
}
|
|
|
|
func (c prefixCollection) PreviousPath() path.Path {
|
|
return c.prev
|
|
}
|
|
|
|
func (c prefixCollection) State() data.CollectionState {
|
|
return c.state
|
|
}
|
|
|
|
func (c prefixCollection) DoNotMergeItems() bool {
|
|
return false
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// base collections
|
|
// ---------------------------------------------------------------------------
|
|
|
|
func BaseCollections(
|
|
ctx context.Context,
|
|
colls []data.BackupCollection,
|
|
tenant, rOwner string,
|
|
service path.ServiceType,
|
|
categories map[path.CategoryType]struct{},
|
|
su support.StatusUpdater,
|
|
errs *fault.Bus,
|
|
) ([]data.BackupCollection, error) {
|
|
var (
|
|
res = []data.BackupCollection{}
|
|
el = errs.Local()
|
|
lastErr error
|
|
collKeys = map[string]struct{}{}
|
|
)
|
|
|
|
// won't catch deleted collections, since they have no FullPath
|
|
for _, c := range colls {
|
|
if c.FullPath() != nil {
|
|
collKeys[c.FullPath().String()] = struct{}{}
|
|
}
|
|
}
|
|
|
|
for cat := range categories {
|
|
ictx := clues.Add(ctx, "base_service", service, "base_category", cat)
|
|
|
|
full, err := path.BuildPrefix(
|
|
tenant,
|
|
[]path.ServiceResource{{
|
|
Service: service,
|
|
ProtectedResource: rOwner,
|
|
}},
|
|
cat)
|
|
if err != nil {
|
|
// Shouldn't happen.
|
|
err = clues.Wrap(err, "making path").WithClues(ictx)
|
|
el.AddRecoverable(ctx, err)
|
|
lastErr = err
|
|
|
|
continue
|
|
}
|
|
|
|
// only add this collection if it doesn't already exist in the set.
|
|
if _, ok := collKeys[full.String()]; !ok {
|
|
res = append(res, &prefixCollection{
|
|
prev: full,
|
|
full: full,
|
|
su: su,
|
|
state: data.StateOf(full, full),
|
|
})
|
|
}
|
|
}
|
|
|
|
return res, lastErr
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// prefix migration
|
|
// ---------------------------------------------------------------------------
|
|
|
|
// Creates a new collection that only handles prefix pathing.
|
|
func NewPrefixCollection(
|
|
prev, full path.Path,
|
|
su support.StatusUpdater,
|
|
) (*prefixCollection, error) {
|
|
if prev != nil {
|
|
if len(prev.Item()) > 0 {
|
|
return nil, clues.New("prefix collection previous path contains an item")
|
|
}
|
|
|
|
if len(prev.Folders()) > 0 {
|
|
return nil, clues.New("prefix collection previous path contains folders")
|
|
}
|
|
}
|
|
|
|
if full != nil {
|
|
if len(full.Item()) > 0 {
|
|
return nil, clues.New("prefix collection full path contains an item")
|
|
}
|
|
|
|
if len(full.Folders()) > 0 {
|
|
return nil, clues.New("prefix collection full path contains folders")
|
|
}
|
|
}
|
|
|
|
pc := &prefixCollection{
|
|
prev: prev,
|
|
full: full,
|
|
su: su,
|
|
state: data.StateOf(prev, full),
|
|
}
|
|
|
|
if pc.state == data.DeletedState {
|
|
return nil, clues.New("collection attempted to delete prefix")
|
|
}
|
|
|
|
if pc.state == data.NewState {
|
|
return nil, clues.New("collection attempted to create a new prefix")
|
|
}
|
|
|
|
return pc, nil
|
|
}
|