Implement ModelStore delete functions (#264)
* Implement ModelStore delete functions * Add tests for ModelStore.Delete()
This commit is contained in:
parent
5ec6d4f286
commit
cdf368ad20
@ -15,6 +15,7 @@ const stableIDKey = "stableID"
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
errNoModelStoreID = errors.New("model has no ModelStoreID")
|
errNoModelStoreID = errors.New("model has no ModelStoreID")
|
||||||
|
errNoStableID = errors.New("model has no StableID")
|
||||||
errBadTagKey = errors.New("tag key overlaps with required key")
|
errBadTagKey = errors.New("tag key overlaps with required key")
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -67,7 +68,7 @@ func tagsForModelWithID(
|
|||||||
tags map[string]string,
|
tags map[string]string,
|
||||||
) (map[string]string, error) {
|
) (map[string]string, error) {
|
||||||
if len(id) == 0 {
|
if len(id) == 0 {
|
||||||
return nil, errors.New("missing ID for model")
|
return nil, errors.WithStack(errNoStableID)
|
||||||
}
|
}
|
||||||
|
|
||||||
res, err := tagsForModel(t, tags)
|
res, err := tagsForModel(t, tags)
|
||||||
@ -149,6 +150,31 @@ func (ms *ModelStore) GetIDsForType(
|
|||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getModelStoreID gets the ModelStoreID of the model with the given
|
||||||
|
// StableID. Returns github.com/kopia/kopia/repo/manifest.ErrNotFound if no
|
||||||
|
// model was found. Returns an error if the given StableID is empty or more than
|
||||||
|
// one model has the same StableID.
|
||||||
|
func (ms *ModelStore) getModelStoreID(ctx context.Context, id model.ID) (manifest.ID, error) {
|
||||||
|
if len(id) == 0 {
|
||||||
|
return "", errors.WithStack(errNoStableID)
|
||||||
|
}
|
||||||
|
|
||||||
|
tags := map[string]string{stableIDKey: string(id)}
|
||||||
|
metadata, err := ms.wrapper.rep.FindManifests(ctx, tags)
|
||||||
|
if err != nil {
|
||||||
|
return "", errors.Wrap(err, "getting ModelStoreID")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(metadata) == 0 {
|
||||||
|
return "", errors.Wrap(manifest.ErrNotFound, "getting ModelStoreID")
|
||||||
|
}
|
||||||
|
if len(metadata) != 1 {
|
||||||
|
return "", errors.New("multiple models with same StableID")
|
||||||
|
}
|
||||||
|
|
||||||
|
return metadata[0].ID, nil
|
||||||
|
}
|
||||||
|
|
||||||
// Get deserializes the model with the given ID into data.
|
// Get deserializes the model with the given ID into data.
|
||||||
func (ms *ModelStore) Get(ctx context.Context, id model.ID, data any) error {
|
func (ms *ModelStore) Get(ctx context.Context, id model.ID, data any) error {
|
||||||
return nil
|
return nil
|
||||||
@ -195,7 +221,37 @@ func (ms *ModelStore) Update(
|
|||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete deletes the model with the given ID from the model store.
|
// Delete deletes the model with the given StableID. Turns into a noop if id is
|
||||||
|
// not empty but the model does not exist.
|
||||||
func (ms *ModelStore) Delete(ctx context.Context, id model.ID) error {
|
func (ms *ModelStore) Delete(ctx context.Context, id model.ID) error {
|
||||||
|
latest, err := ms.getModelStoreID(ctx, id)
|
||||||
|
if err != nil {
|
||||||
|
if errors.Is(err, manifest.ErrNotFound) {
|
||||||
return nil
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return ms.DeleteWithModelStoreID(ctx, latest)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeletWithModelStoreID deletes the model with the given ModelStoreID from the
|
||||||
|
// model store. Turns into a noop if id is not empty but the model does not
|
||||||
|
// exist.
|
||||||
|
func (ms *ModelStore) DeleteWithModelStoreID(ctx context.Context, id manifest.ID) error {
|
||||||
|
if len(id) == 0 {
|
||||||
|
return errors.WithStack(errNoModelStoreID)
|
||||||
|
}
|
||||||
|
|
||||||
|
err := repo.WriteSession(
|
||||||
|
ctx,
|
||||||
|
ms.wrapper.rep,
|
||||||
|
repo.WriteSessionOptions{Purpose: "ModelStoreDelete"},
|
||||||
|
func(innerCtx context.Context, w repo.RepositoryWriter) error {
|
||||||
|
return w.DeleteManifest(innerCtx, id)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
return errors.Wrap(err, "deleting model")
|
||||||
}
|
}
|
||||||
|
|||||||
@ -96,14 +96,17 @@ func (suite *ModelStoreIntegrationSuite) TestNoIDsErrors() {
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
noStableID := &fooModel{Bar: uuid.NewString()}
|
noStableID := &fooModel{Bar: uuid.NewString()}
|
||||||
noStableID.Base().StableID = ""
|
noStableID.StableID = ""
|
||||||
noStableID.Base().ModelStoreID = manifest.ID(uuid.NewString())
|
noStableID.ModelStoreID = manifest.ID(uuid.NewString())
|
||||||
|
|
||||||
noModelStoreID := &fooModel{Bar: uuid.NewString()}
|
noModelStoreID := &fooModel{Bar: uuid.NewString()}
|
||||||
noModelStoreID.Base().StableID = model.ID(uuid.NewString())
|
noModelStoreID.StableID = model.ID(uuid.NewString())
|
||||||
noModelStoreID.Base().ModelStoreID = ""
|
noModelStoreID.ModelStoreID = ""
|
||||||
|
|
||||||
assert.Error(t, m.GetWithModelStoreID(ctx, "", nil))
|
assert.Error(t, m.GetWithModelStoreID(ctx, "", nil))
|
||||||
|
|
||||||
|
assert.Error(t, m.Delete(ctx, ""))
|
||||||
|
assert.Error(t, m.DeleteWithModelStoreID(ctx, ""))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *ModelStoreIntegrationSuite) TestPutGet() {
|
func (suite *ModelStoreIntegrationSuite) TestPutGet() {
|
||||||
@ -155,11 +158,11 @@ func (suite *ModelStoreIntegrationSuite) TestPutGet() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
require.NotEmpty(t, foo.Base().ModelStoreID)
|
require.NotEmpty(t, foo.ModelStoreID)
|
||||||
require.NotEmpty(t, foo.Base().StableID)
|
require.NotEmpty(t, foo.StableID)
|
||||||
|
|
||||||
returned := &fooModel{}
|
returned := &fooModel{}
|
||||||
err = m.GetWithModelStoreID(ctx, foo.Base().ModelStoreID, returned)
|
err = m.GetWithModelStoreID(ctx, foo.ModelStoreID, returned)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, foo, returned)
|
assert.Equal(t, foo, returned)
|
||||||
})
|
})
|
||||||
@ -182,11 +185,11 @@ func (suite *ModelStoreIntegrationSuite) TestPutGet_WithTags() {
|
|||||||
|
|
||||||
require.NoError(t, m.Put(ctx, BackupOpModel, foo))
|
require.NoError(t, m.Put(ctx, BackupOpModel, foo))
|
||||||
|
|
||||||
require.NotEmpty(t, foo.Base().ModelStoreID)
|
require.NotEmpty(t, foo.ModelStoreID)
|
||||||
require.NotEmpty(t, foo.Base().StableID)
|
require.NotEmpty(t, foo.StableID)
|
||||||
|
|
||||||
returned := &fooModel{}
|
returned := &fooModel{}
|
||||||
err := m.GetWithModelStoreID(ctx, foo.Base().ModelStoreID, returned)
|
err := m.GetWithModelStoreID(ctx, foo.ModelStoreID, returned)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, foo, returned)
|
assert.Equal(t, foo, returned)
|
||||||
}
|
}
|
||||||
@ -202,3 +205,36 @@ func (suite *ModelStoreIntegrationSuite) TestGet_NotFoundErrors() {
|
|||||||
|
|
||||||
assert.ErrorIs(t, m.GetWithModelStoreID(ctx, "baz", nil), manifest.ErrNotFound)
|
assert.ErrorIs(t, m.GetWithModelStoreID(ctx, "baz", nil), manifest.ErrNotFound)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (suite *ModelStoreIntegrationSuite) TestPutDelete() {
|
||||||
|
ctx := context.Background()
|
||||||
|
t := suite.T()
|
||||||
|
|
||||||
|
m := getModelStore(t, ctx)
|
||||||
|
defer func() {
|
||||||
|
assert.NoError(t, m.wrapper.Close(ctx))
|
||||||
|
}()
|
||||||
|
|
||||||
|
foo := &fooModel{Bar: uuid.NewString()}
|
||||||
|
|
||||||
|
require.NoError(t, m.Put(ctx, BackupOpModel, foo))
|
||||||
|
|
||||||
|
require.NoError(t, m.Delete(ctx, foo.StableID))
|
||||||
|
|
||||||
|
returned := &fooModel{}
|
||||||
|
err := m.GetWithModelStoreID(ctx, foo.ModelStoreID, returned)
|
||||||
|
assert.ErrorIs(t, err, manifest.ErrNotFound)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *ModelStoreIntegrationSuite) TestPutDelete_BadIDsNoop() {
|
||||||
|
ctx := context.Background()
|
||||||
|
t := suite.T()
|
||||||
|
|
||||||
|
m := getModelStore(t, ctx)
|
||||||
|
defer func() {
|
||||||
|
assert.NoError(t, m.wrapper.Close(ctx))
|
||||||
|
}()
|
||||||
|
|
||||||
|
assert.NoError(t, m.Delete(ctx, "foo"))
|
||||||
|
assert.NoError(t, m.DeleteWithModelStoreID(ctx, "foo"))
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user