LastImportTime for resource. (#112153)

* LastImportTime for resource.

* Make StorageBackendImpl implement GetResourceLastImportTimes

* More missing implementations of GetResourceLastImportTimes

* Fix import.

* Skip TestGetResourceLastImportTime in TestBadgerKVStorageBackend.

* Implement GetResourceLastImportTimes by mockStorageBackend

* Bump test tolerance.

* Fix postgres query and timezone.

* Fix postgres query and timezone.

* Make linter happy.
This commit is contained in:
Peter Štibraný
2025-10-09 11:27:11 +02:00
committed by GitHub
parent 3cdae5d67d
commit d801b87db9
24 changed files with 476 additions and 8 deletions
+3 -2
View File
@@ -33,12 +33,13 @@ func grpcMetaValueIsTrue(vals []string) bool {
}
type BulkRequestIterator interface {
// Next advances the iterator to the next element if one exists.
Next() bool
// The next event we should process
// Request returns the current element. Only valid after Next() returns true.
Request() *resourcepb.BulkRequest
// Rollback requested
// RollbackRequested returns true if there was an error advancing the iterator. Checked after Next() returns true.
RollbackRequested() bool
}
@@ -75,6 +75,12 @@ type cdkBackend struct {
stream chan<- *WrittenEvent
}
func (s *cdkBackend) GetResourceLastImportTimes(ctx context.Context) iter.Seq2[ResourceLastImportTime, error] {
return func(yield func(ResourceLastImportTime, error) bool) {
yield(ResourceLastImportTime{}, errors.New("not implemented"))
}
}
func (s *cdkBackend) ListModifiedSince(ctx context.Context, key NamespacedResource, sinceRv int64) (int64, iter.Seq2[*ModifiedResource, error]) {
return 0, func(yield func(*ModifiedResource, error) bool) {
yield(nil, errors.New("not implemented"))
@@ -129,6 +129,12 @@ func (m *mockStorageBackend) ListModifiedSince(ctx context.Context, key Namespac
}
}
func (m *mockStorageBackend) GetResourceLastImportTimes(ctx context.Context) iter.Seq2[ResourceLastImportTime, error] {
return func(yield func(ResourceLastImportTime, error) bool) {
yield(ResourceLastImportTime{}, errors.New("not implemented"))
}
}
// mockSearchBackend implements SearchBackend for testing with tracking capabilities
type mockSearchBackend struct {
openIndexes []NamespacedResource
+8
View File
@@ -86,6 +86,11 @@ type BackendReadResponse struct {
Error *resourcepb.ErrorResult
}
type ResourceLastImportTime struct {
NamespacedResource
LastImportTime time.Time
}
// The StorageBackend is an internal abstraction that supports interacting with
// the underlying raw storage medium. This interface is never exposed directly,
// it is provided by concrete instances that actually write values.
@@ -118,6 +123,9 @@ type StorageBackend interface {
// Get resource stats within the storage backend. When namespace is empty, it will apply to all
GetResourceStats(ctx context.Context, namespace string, minCount int) ([]ResourceStats, error)
// GetResourceLastImportTimes returns import times for all namespaced resources in the backend.
GetResourceLastImportTimes(ctx context.Context) iter.Seq2[ResourceLastImportTime, error]
}
type ModifiedResource struct {
@@ -15,12 +15,13 @@ import (
"github.com/bwmarrin/snowflake"
"github.com/grafana/grafana-app-sdk/logging"
"github.com/grafana/grafana/pkg/apimachinery/utils"
"github.com/grafana/grafana/pkg/storage/unified/resourcepb"
"github.com/grafana/grafana/pkg/util/debouncer"
"github.com/prometheus/client_golang/prometheus"
"go.opentelemetry.io/otel/trace"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"github.com/grafana/grafana/pkg/apimachinery/utils"
"github.com/grafana/grafana/pkg/storage/unified/resourcepb"
"github.com/grafana/grafana/pkg/util/debouncer"
)
const (
@@ -1076,6 +1077,12 @@ func (k *kvStorageBackend) GetResourceStats(ctx context.Context, namespace strin
return k.dataStore.GetResourceStats(ctx, namespace, minCount)
}
func (k *kvStorageBackend) GetResourceLastImportTimes(ctx context.Context) iter.Seq2[ResourceLastImportTime, error] {
return func(yield func(ResourceLastImportTime, error) bool) {
yield(ResourceLastImportTime{}, fmt.Errorf("not implemented"))
}
}
// readAndClose reads all data from a ReadCloser and ensures it's closed,
// combining any errors from both operations.
func readAndClose(r io.ReadCloser) ([]byte, error) {