Add and populate mod time for BaseModel (#4065)
Get the last time a model was modified and return it in BaseModel. This will help with discovering what items can be garbage collected during incomplete backup cleanup as we don't want to accidentally delete in-flight backups. --- #### 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 - [x] 🌻 Feature - [ ] 🐛 Bugfix - [ ] 🗺️ Documentation - [ ] 🤖 Supportability/Tests - [ ] 💻 CI/Deployment - [ ] 🧹 Tech Debt/Cleanup #### Issue(s) * #3217 #### Test Plan - [ ] 💪 Manual - [x] ⚡ Unit test - [ ] 💚 E2E
This commit is contained in:
parent
5808797fc6
commit
99edf7d5b0
@ -210,6 +210,7 @@ func (ms ModelStore) populateBaseModelFromMetadata(
|
|||||||
base.ID = model.StableID(id)
|
base.ID = model.StableID(id)
|
||||||
base.ModelVersion = v
|
base.ModelVersion = v
|
||||||
base.Tags = m.Labels
|
base.Tags = m.Labels
|
||||||
|
base.ModTime = m.ModTime
|
||||||
|
|
||||||
stripHiddenTags(base.Tags)
|
stripHiddenTags(base.Tags)
|
||||||
|
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"sync"
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/alcionai/clues"
|
"github.com/alcionai/clues"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
@ -34,6 +35,18 @@ func getModelStore(t *testing.T, ctx context.Context) *ModelStore {
|
|||||||
return &ModelStore{c: c, modelVersion: globalModelVersion}
|
return &ModelStore{c: c, modelVersion: globalModelVersion}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func assertEqualNoModTime(t *testing.T, expected, got *fooModel) {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
expectedClean := *expected
|
||||||
|
gotClean := *got
|
||||||
|
|
||||||
|
expectedClean.ModTime = time.Time{}
|
||||||
|
gotClean.ModTime = time.Time{}
|
||||||
|
|
||||||
|
assert.Equal(t, expectedClean, gotClean)
|
||||||
|
}
|
||||||
|
|
||||||
// ---------------
|
// ---------------
|
||||||
// unit tests
|
// unit tests
|
||||||
// ---------------
|
// ---------------
|
||||||
@ -259,6 +272,8 @@ func (suite *ModelStoreIntegrationSuite) TestPutGet() {
|
|||||||
// Avoid some silly test errors from comparing nil to empty map.
|
// Avoid some silly test errors from comparing nil to empty map.
|
||||||
foo.Tags = map[string]string{}
|
foo.Tags = map[string]string{}
|
||||||
|
|
||||||
|
startTime := time.Now()
|
||||||
|
|
||||||
err := suite.m.Put(suite.ctx, test.s, foo)
|
err := suite.m.Put(suite.ctx, test.s, foo)
|
||||||
test.check(t, err, clues.ToCore(err))
|
test.check(t, err, clues.ToCore(err))
|
||||||
|
|
||||||
@ -273,11 +288,17 @@ func (suite *ModelStoreIntegrationSuite) TestPutGet() {
|
|||||||
returned := &fooModel{}
|
returned := &fooModel{}
|
||||||
err = suite.m.Get(suite.ctx, test.s, foo.ID, returned)
|
err = suite.m.Get(suite.ctx, test.s, foo.ID, returned)
|
||||||
require.NoError(t, err, clues.ToCore(err))
|
require.NoError(t, err, clues.ToCore(err))
|
||||||
assert.Equal(t, foo, returned)
|
|
||||||
|
assertEqualNoModTime(t, foo, returned)
|
||||||
|
assert.WithinDuration(t, startTime, returned.ModTime, 5*time.Second)
|
||||||
|
|
||||||
|
returned = &fooModel{}
|
||||||
|
|
||||||
err = suite.m.GetWithModelStoreID(suite.ctx, test.s, foo.ModelStoreID, returned)
|
err = suite.m.GetWithModelStoreID(suite.ctx, test.s, foo.ModelStoreID, returned)
|
||||||
require.NoError(t, err, clues.ToCore(err))
|
require.NoError(t, err, clues.ToCore(err))
|
||||||
assert.Equal(t, foo, returned)
|
|
||||||
|
assertEqualNoModTime(t, foo, returned)
|
||||||
|
assert.WithinDuration(t, startTime, returned.ModTime, 5*time.Second)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -324,11 +345,11 @@ func (suite *ModelStoreIntegrationSuite) TestPutGet_PreSetID() {
|
|||||||
|
|
||||||
err = suite.m.Get(suite.ctx, mdl, foo.ID, returned)
|
err = suite.m.Get(suite.ctx, mdl, foo.ID, returned)
|
||||||
require.NoError(t, err, clues.ToCore(err))
|
require.NoError(t, err, clues.ToCore(err))
|
||||||
assert.Equal(t, foo, returned)
|
assertEqualNoModTime(t, foo, returned)
|
||||||
|
|
||||||
err = suite.m.GetWithModelStoreID(suite.ctx, mdl, foo.ModelStoreID, returned)
|
err = suite.m.GetWithModelStoreID(suite.ctx, mdl, foo.ModelStoreID, returned)
|
||||||
require.NoError(t, err, clues.ToCore(err))
|
require.NoError(t, err, clues.ToCore(err))
|
||||||
assert.Equal(t, foo, returned)
|
assertEqualNoModTime(t, foo, returned)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -350,11 +371,11 @@ func (suite *ModelStoreIntegrationSuite) TestPutGet_WithTags() {
|
|||||||
returned := &fooModel{}
|
returned := &fooModel{}
|
||||||
err = suite.m.Get(suite.ctx, theModelType, foo.ID, returned)
|
err = suite.m.Get(suite.ctx, theModelType, foo.ID, returned)
|
||||||
require.NoError(t, err, clues.ToCore(err))
|
require.NoError(t, err, clues.ToCore(err))
|
||||||
assert.Equal(t, foo, returned)
|
assertEqualNoModTime(t, foo, returned)
|
||||||
|
|
||||||
err = suite.m.GetWithModelStoreID(suite.ctx, theModelType, foo.ModelStoreID, returned)
|
err = suite.m.GetWithModelStoreID(suite.ctx, theModelType, foo.ModelStoreID, returned)
|
||||||
require.NoError(t, err, clues.ToCore(err))
|
require.NoError(t, err, clues.ToCore(err))
|
||||||
assert.Equal(t, foo, returned)
|
assertEqualNoModTime(t, foo, returned)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *ModelStoreIntegrationSuite) TestGet_NotFoundErrors() {
|
func (suite *ModelStoreIntegrationSuite) TestGet_NotFoundErrors() {
|
||||||
@ -559,7 +580,16 @@ func (suite *ModelStoreIntegrationSuite) TestGetOfTypeWithTags() {
|
|||||||
ids, err := suite.m.GetIDsForType(suite.ctx, test.s, test.tags)
|
ids, err := suite.m.GetIDsForType(suite.ctx, test.s, test.tags)
|
||||||
require.NoError(t, err, clues.ToCore(err))
|
require.NoError(t, err, clues.ToCore(err))
|
||||||
|
|
||||||
assert.ElementsMatch(t, expected, ids)
|
cleanIDs := make([]*model.BaseModel, 0, len(ids))
|
||||||
|
|
||||||
|
for _, id := range ids {
|
||||||
|
id2 := *id
|
||||||
|
id2.ModTime = time.Time{}
|
||||||
|
|
||||||
|
cleanIDs = append(cleanIDs, &id2)
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.ElementsMatch(t, expected, cleanIDs)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -627,7 +657,7 @@ func (suite *ModelStoreIntegrationSuite) TestPutUpdate() {
|
|||||||
|
|
||||||
err = m.GetWithModelStoreID(ctx, theModelType, foo.ModelStoreID, returned)
|
err = m.GetWithModelStoreID(ctx, theModelType, foo.ModelStoreID, returned)
|
||||||
require.NoError(t, err, clues.ToCore(err))
|
require.NoError(t, err, clues.ToCore(err))
|
||||||
assert.Equal(t, foo, returned)
|
assertEqualNoModTime(t, foo, returned)
|
||||||
|
|
||||||
ids, err := m.GetIDsForType(ctx, theModelType, nil)
|
ids, err := m.GetIDsForType(ctx, theModelType, nil)
|
||||||
require.NoError(t, err, clues.ToCore(err))
|
require.NoError(t, err, clues.ToCore(err))
|
||||||
@ -822,7 +852,7 @@ func (suite *ModelStoreRegressionSuite) TestFailDuringWriteSessionHasNoVisibleEf
|
|||||||
|
|
||||||
err = m.GetWithModelStoreID(ctx, theModelType, foo.ModelStoreID, returned)
|
err = m.GetWithModelStoreID(ctx, theModelType, foo.ModelStoreID, returned)
|
||||||
require.NoError(t, err, clues.ToCore(err))
|
require.NoError(t, err, clues.ToCore(err))
|
||||||
assert.Equal(t, foo, returned)
|
assertEqualNoModTime(t, foo, returned)
|
||||||
}
|
}
|
||||||
|
|
||||||
func openConnAndModelStore(
|
func openConnAndModelStore(
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
package model
|
package model
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/kopia/kopia/repo/manifest"
|
"github.com/kopia/kopia/repo/manifest"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -68,7 +70,8 @@ type BaseModel struct {
|
|||||||
// Tags associated with this model in the store to facilitate lookup. Tags in
|
// Tags associated with this model in the store to facilitate lookup. Tags in
|
||||||
// the struct are not serialized directly into the stored model, but are part
|
// the struct are not serialized directly into the stored model, but are part
|
||||||
// of the metadata for the model.
|
// of the metadata for the model.
|
||||||
Tags map[string]string `json:"-"`
|
Tags map[string]string `json:"-"`
|
||||||
|
ModTime time.Time `json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bm *BaseModel) Base() *BaseModel {
|
func (bm *BaseModel) Base() *BaseModel {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user