From 6ec77fb159d4ca4c45c1d85fc132e2acca8c76b6 Mon Sep 17 00:00:00 2001 From: Simona Pencea Date: Wed, 12 Nov 2025 12:44:47 +0100 Subject: [PATCH] feat: add lastarchivedwaltime to the recoverywindow Signed-off-by: Simona Pencea --- Makefile | 2 +- api/v1/objectstore_types.go | 3 ++ api/v1/zz_generated.deepcopy.go | 4 ++ .../barmancloud.cnpg.io_objectstores.yaml | 5 +++ internal/cnpgi/common/wal.go | 45 +++++++++++++++++++ internal/cnpgi/instance/metrics.go | 18 ++++++++ 6 files changed, 76 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index a351bd3..46b728e 100644 --- a/Makefile +++ b/Makefile @@ -159,7 +159,7 @@ GOLANGCI_LINT = $(LOCALBIN)/golangci-lint ## Tool Versions KUSTOMIZE_VERSION ?= v5.4.3 -CONTROLLER_TOOLS_VERSION ?= v0.16.1 +CONTROLLER_TOOLS_VERSION ?= v0.19.0 ENVTEST_VERSION ?= release-0.19 GOLANGCI_LINT_VERSION ?= v1.64.8 diff --git a/api/v1/objectstore_types.go b/api/v1/objectstore_types.go index f179af9..3d5cfeb 100644 --- a/api/v1/objectstore_types.go +++ b/api/v1/objectstore_types.go @@ -94,6 +94,9 @@ type RecoveryWindow struct { // The last failed backup time LastFailedBackupTime *metav1.Time `json:"lastFailedBackupTime,omitempty"` + + // The last time a WAL file was successfully archived by this plugin + LastArchivedWALTime *metav1.Time `json:"lastArchivedWALTime,omitempty"` } // +kubebuilder:object:root=true diff --git a/api/v1/zz_generated.deepcopy.go b/api/v1/zz_generated.deepcopy.go index 05f7e61..2e9ca7c 100644 --- a/api/v1/zz_generated.deepcopy.go +++ b/api/v1/zz_generated.deepcopy.go @@ -169,6 +169,10 @@ func (in *RecoveryWindow) DeepCopyInto(out *RecoveryWindow) { in, out := &in.LastFailedBackupTime, &out.LastFailedBackupTime *out = (*in).DeepCopy() } + if in.LastArchivedWALTime != nil { + in, out := &in.LastArchivedWALTime, &out.LastArchivedWALTime + *out = (*in).DeepCopy() + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RecoveryWindow. diff --git a/config/crd/bases/barmancloud.cnpg.io_objectstores.yaml b/config/crd/bases/barmancloud.cnpg.io_objectstores.yaml index a141948..3715b4f 100644 --- a/config/crd/bases/barmancloud.cnpg.io_objectstores.yaml +++ b/config/crd/bases/barmancloud.cnpg.io_objectstores.yaml @@ -671,6 +671,11 @@ spec: restored. format: date-time type: string + lastArchivedWALTime: + description: The last time a WAL file was successfully archived + by this plugin + format: date-time + type: string lastFailedBackupTime: description: The last failed backup time format: date-time diff --git a/internal/cnpgi/common/wal.go b/internal/cnpgi/common/wal.go index 8e58cb4..3649897 100644 --- a/internal/cnpgi/common/wal.go +++ b/internal/cnpgi/common/wal.go @@ -38,7 +38,10 @@ import ( walUtils "github.com/cloudnative-pg/machinery/pkg/fileutils/wals" "github.com/cloudnative-pg/machinery/pkg/log" apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" + "k8s.io/client-go/util/retry" + "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/client" barmancloudv1 "github.com/cloudnative-pg/plugin-barman-cloud/api/v1" @@ -220,6 +223,21 @@ func (w WALServiceImplementation) Archive( } } + // Update the last archived WAL time in the ObjectStore status + contextLogger.Debug("Updating last archived WAL time", "serverName", configuration.ServerName) + if err := setLastArchivedWALTime( + ctx, + w.Client, + configuration.GetBarmanObjectKey(), + configuration.ServerName, + time.Now(), + ); err != nil { + // Log the error but don't fail the archive operation + contextLogger.Error(err, "Error updating last archived WAL time in ObjectStore status") + } else { + contextLogger.Debug("Successfully updated last archived WAL time") + } + return &wal.WALArchiveResult{}, nil } @@ -509,3 +527,30 @@ func isEndOfWALStream(results []barmanRestorer.Result) bool { return false } + +// SetLastArchivedWALTime sets the last archived WAL time in the +// passed object store, for the passed server name. +func setLastArchivedWALTime( + ctx context.Context, + c client.Client, + objectStoreKey client.ObjectKey, + serverName string, + lastArchivedWALTime time.Time, +) error { + return retry.RetryOnConflict(retry.DefaultBackoff, func() error { + var objectStore barmancloudv1.ObjectStore + + if err := c.Get(ctx, objectStoreKey, &objectStore); err != nil { + return err + } + recoveryWindow := objectStore.Status.ServerRecoveryWindow[serverName] + recoveryWindow.LastArchivedWALTime = ptr.To(metav1.NewTime(lastArchivedWALTime)) + + if objectStore.Status.ServerRecoveryWindow == nil { + objectStore.Status.ServerRecoveryWindow = make(map[string]barmancloudv1.RecoveryWindow) + } + objectStore.Status.ServerRecoveryWindow[serverName] = recoveryWindow + + return c.Status().Update(ctx, &objectStore) + }) +} diff --git a/internal/cnpgi/instance/metrics.go b/internal/cnpgi/instance/metrics.go index d21a49c..a58c02f 100644 --- a/internal/cnpgi/instance/metrics.go +++ b/internal/cnpgi/instance/metrics.go @@ -51,6 +51,7 @@ var ( firstRecoverabilityPointMetricName = buildFqName("first_recoverability_point") lastAvailableBackupTimestampMetricName = buildFqName("last_available_backup_timestamp") lastFailedBackupTimestampMetricName = buildFqName("last_failed_backup_timestamp") + lastArchivedWALTimestampMetricName = buildFqName("last_archived_wal_timestamp") ) func (m metricsImpl) GetCapabilities( @@ -97,6 +98,11 @@ func (m metricsImpl) Define( Help: "The last failed backup as a unix timestamp", ValueType: &metrics.MetricType{Type: metrics.MetricType_TYPE_GAUGE}, }, + { + FqName: lastArchivedWALTimestampMetricName, + Help: "The last archived WAL timestamp as a unix timestamp", + ValueType: &metrics.MetricType{Type: metrics.MetricType_TYPE_GAUGE}, + }, }, }, nil } @@ -136,6 +142,10 @@ func (m metricsImpl) Collect( FqName: lastFailedBackupTimestampMetricName, Value: 0, }, + { + FqName: lastArchivedWALTimestampMetricName, + Value: 0, + }, }, }, nil } @@ -143,6 +153,7 @@ func (m metricsImpl) Collect( var firstRecoverabilityPoint float64 var lastAvailableBackup float64 var lastFailedBackup float64 + var lastArchivedWAL float64 if x.FirstRecoverabilityPoint != nil { firstRecoverabilityPoint = float64(x.FirstRecoverabilityPoint.Unix()) } @@ -152,6 +163,9 @@ func (m metricsImpl) Collect( if x.LastFailedBackupTime != nil { lastFailedBackup = float64(x.LastFailedBackupTime.Unix()) } + if x.LastArchivedWALTime != nil { + lastArchivedWAL = float64(x.LastArchivedWALTime.Unix()) + } return &metrics.CollectMetricsResult{ Metrics: []*metrics.CollectMetric{ @@ -167,6 +181,10 @@ func (m metricsImpl) Collect( FqName: lastFailedBackupTimestampMetricName, Value: lastFailedBackup, }, + { + FqName: lastArchivedWALTimestampMetricName, + Value: lastArchivedWAL, + }, }, }, nil }