Unified Storage: Add ListSinceModified to StorageBackend (#109697)

* WIP added ListSinceModified to StorageBackend interface

* fix compile time check

* Fix method name

* Fix naming

* fix the rest of the ListSinceModified names

* Uses resource key without name field

* get latest rv from resource_version. Update test.

* adds moar tests

* adds method stub for ListModifiedSince to other StorageBackend implementations

* adds dummy impl to noop storage backend for ListModifiedSince

* skip tests for badger kv backend for now

* fixes tests and adds badgerkv impl for ListModifiedSince

* add badger kv impl

* adds test for new query

* adds test data for new query

* adds ListModifiedSince stub to mockStorageBackend

* uncomment tests

* refactors ListModifiedSince to return an iter.seq2 and handles deduplication. Updates tests. Updates query result sorting.

* remove comments

* remove folder from query (dont need it, yet?)

* regen test queries

* updates test

* updates function comment

* use resourcepb.ResourceKey instead of ModifiedResourceKey

* wrap seq in single transaction. Rollback transaction after 30s if iterator never used. Only track last seen event. Formatting.

* skip TestListModifiedSince for kv backend

* use WatchEvent_Type for action type

* remove redundant fields from order by clause and regen test data for query

* remove redundant fields from order by clause and regen test data for query
This commit is contained in:
owensmallwood
2025-08-20 11:54:31 -06:00
committed by GitHub
parent 49739618fa
commit cace999671
15 changed files with 329 additions and 19 deletions
@@ -35,6 +35,7 @@ const (
TestGetResourceStats = "get resource stats"
TestListHistory = "list history"
TestListHistoryErrorReporting = "list history error reporting"
TestListModifiedSince = "list events since rv"
TestListTrash = "list trash"
TestCreateNewResource = "create new resource"
)
@@ -78,6 +79,7 @@ func RunStorageBackendTest(t *testing.T, newBackend NewBackendFunc, opts *TestOp
{TestListHistoryErrorReporting, runTestIntegrationBackendListHistoryErrorReporting},
{TestListTrash, runTestIntegrationBackendTrash},
{TestCreateNewResource, runTestIntegrationBackendCreateNewResource},
{TestListModifiedSince, runTestIntegrationBackendListModifiedSince},
}
for _, tc := range cases {
@@ -482,6 +484,77 @@ func runTestIntegrationBackendList(t *testing.T, backend resource.StorageBackend
})
}
func runTestIntegrationBackendListModifiedSince(t *testing.T, backend resource.StorageBackend, nsPrefix string) {
ctx := testutil.NewTestContext(t, time.Now().Add(30*time.Second))
ns := nsPrefix + "-history-ns"
rvCreated, _ := writeEvent(ctx, backend, "item1", resourcepb.WatchEvent_ADDED, WithNamespace(ns))
require.Greater(t, rvCreated, int64(0))
rvUpdated, err := writeEvent(ctx, backend, "item1", resourcepb.WatchEvent_MODIFIED, WithNamespace(ns))
require.NoError(t, err)
require.Greater(t, rvUpdated, rvCreated)
rvDeleted, err := writeEvent(ctx, backend, "item1", resourcepb.WatchEvent_DELETED, WithNamespace(ns))
require.NoError(t, err)
require.Greater(t, rvDeleted, rvUpdated)
t.Run("will list latest modified event when resource has multiple events", func(t *testing.T) {
key := resource.NamespacedResource{
Namespace: ns,
Group: "group",
Resource: "resource",
}
latestRv, seq := backend.ListModifiedSince(ctx, key, rvCreated)
require.Greater(t, latestRv, rvCreated)
counter := 0
for res, err := range seq {
require.NoError(t, err)
require.Equal(t, rvDeleted, res.ResourceVersion)
counter++
}
require.Equal(t, 1, counter) // only one event should be returned
})
t.Run("no events if none after the given resource version", func(t *testing.T) {
key := resource.NamespacedResource{
Namespace: ns,
Group: "group",
Resource: "resource",
}
latestRv, seq := backend.ListModifiedSince(ctx, key, rvDeleted)
require.GreaterOrEqual(t, latestRv, rvDeleted)
counter := 0
for _, _ = range seq {
counter++
}
require.Equal(t, 0, counter) // no events should be returned
})
t.Run("will only return modified events for the given key", func(t *testing.T) {
key := resource.NamespacedResource{
Namespace: "other-ns",
Group: "group",
Resource: "resource",
}
// Write an event for another tenant for the same resource
rvCreatedOtherTenant, err := writeEvent(ctx, backend, "item2", resourcepb.WatchEvent_ADDED, WithNamespace("other-ns"))
require.NoError(t, err)
latestRv, seq := backend.ListModifiedSince(ctx, key, rvCreated)
require.Greater(t, latestRv, rvCreated)
counter := 0
for res, err := range seq {
require.NoError(t, err)
require.Equal(t, rvCreatedOtherTenant, res.ResourceVersion)
require.Equal(t, key.Namespace, res.Key.Namespace)
counter++
}
require.Equal(t, 1, counter) // only one event should be returned
})
}
func runTestIntegrationBackendListHistory(t *testing.T, backend resource.StorageBackend, nsPrefix string) {
ctx := testutil.NewTestContext(t, time.Now().Add(30*time.Second))
server := newServer(t, backend)
@@ -23,7 +23,8 @@ func TestBadgerKVStorageBackend(t *testing.T) {
NSPrefix: "kvstorage-test",
SkipTests: map[string]bool{
// TODO: fix these tests and remove this skip
TestBlobSupport: true,
TestBlobSupport: true,
TestListModifiedSince: true,
},
})
}