Compare commits

...

3 Commits

Author SHA1 Message Date
Gabriel José Mouallem Rodrigues
71ff5cc4b6
Merge eefb45ca5a into 77118ed413 2026-08-20 16:13:37 +02:00
renovate[bot]
77118ed413
chore(deps): update all cloudnative-pg daggerverse dependencies to 26cd57f (#1072)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-08-19 13:01:46 +02:00
Gabriel Jose Mouallem Rodrigues
eefb45ca5a fix: add retry logic to updateRecoveryWindow for concurrent status updates
When backup completion and retention policy enforcement run concurrently,
both call updateRecoveryWindow to update the ObjectStore status. This can
cause "object has been modified" errors due to Kubernetes optimistic
concurrency control.

This change wraps the status update in retry.RetryOnConflict, matching
the pattern already used in setLastFailedBackupTime in the same file.
The retry logic fetches a fresh copy of the ObjectStore before each
update attempt, ensuring the resourceVersion is current.

Fixes #758

Signed-off-by: Gabriel Mouallem <gabriel@latitude.sh>
2026-02-03 15:01:30 -03:00
2 changed files with 30 additions and 20 deletions

View File

@ -46,7 +46,7 @@ tasks:
- wordlist-ordered
env:
# renovate: datasource=git-refs depName=spellcheck lookupName=https://github.com/cloudnative-pg/daggerverse currentValue=main
DAGGER_SPELLCHECK_SHA: 7174b66d283da487638a98b431b7707b311a9a32
DAGGER_SPELLCHECK_SHA: 26cd57fb6ad66e88c036b675b0478d38df93962d
cmds:
- >
GITHUB_REF= dagger -s call -m github.com/cloudnative-pg/daggerverse/spellcheck@${DAGGER_SPELLCHECK_SHA}
@ -60,7 +60,7 @@ tasks:
desc: Check for conventional commits
env:
# renovate: datasource=git-refs depName=commitlint lookupName=https://github.com/cloudnative-pg/daggerverse currentValue=main
DAGGER_COMMITLINT_SHA: 7174b66d283da487638a98b431b7707b311a9a32
DAGGER_COMMITLINT_SHA: 26cd57fb6ad66e88c036b675b0478d38df93962d
cmds:
- >
GITHUB_REF= dagger -s call -m github.com/cloudnative-pg/daggerverse/commitlint@${DAGGER_COMMITLINT_SHA}
@ -74,7 +74,7 @@ tasks:
- wordlist-ordered
env:
# renovate: datasource=git-refs depName=uncommitted lookupName=https://github.com/cloudnative-pg/daggerverse currentValue=main
DAGGER_UNCOMMITTED_SHA: 7174b66d283da487638a98b431b7707b311a9a32
DAGGER_UNCOMMITTED_SHA: 26cd57fb6ad66e88c036b675b0478d38df93962d
cmds:
- GITHUB_REF= dagger -s call -m github.com/cloudnative-pg/daggerverse/uncommitted@${DAGGER_UNCOMMITTED_SHA} check-uncommitted --source . stdout
sources:
@ -86,7 +86,7 @@ tasks:
- controller-gen
env:
# renovate: datasource=git-refs depName=crd-gen-refs lookupName=https://github.com/cloudnative-pg/daggerverse currentValue=main
DAGGER_CRDGENREF_SHA: 7174b66d283da487638a98b431b7707b311a9a32
DAGGER_CRDGENREF_SHA: 26cd57fb6ad66e88c036b675b0478d38df93962d
# renovate: datasource=go depName=github.com/elastic/crd-ref-docs
CRDREFDOCS_VERSION: v0.3.0
cmds:
@ -383,7 +383,7 @@ tasks:
run: once
env:
# renovate: datasource=git-refs depName=controller-gen lookupName=https://github.com/cloudnative-pg/daggerverse currentValue=main
DAGGER_CONTROLLER_GEN_SHA: 7174b66d283da487638a98b431b7707b311a9a32
DAGGER_CONTROLLER_GEN_SHA: 26cd57fb6ad66e88c036b675b0478d38df93962d
cmds:
- >
GITHUB_REF= dagger -s call -m github.com/cloudnative-pg/daggerverse/controller-gen@${DAGGER_CONTROLLER_GEN_SHA}

View File

@ -33,7 +33,8 @@ import (
)
// updateRecoveryWindow updates the recovery window inside the object
// store status subresource
// store status subresource. It uses retry logic to handle concurrent
// updates from backup completion and retention policy enforcement.
func updateRecoveryWindow(
ctx context.Context,
c client.Client,
@ -41,24 +42,33 @@ func updateRecoveryWindow(
objectStore *barmancloudv1.ObjectStore,
serverName string,
) error {
// Set the recovery window inside the barman object store object
convertTime := func(t *time.Time) *metav1.Time {
if t == nil {
return nil
objectStoreKey := client.ObjectKeyFromObject(objectStore)
return retry.RetryOnConflict(retry.DefaultBackoff, func() error {
var freshObjectStore barmancloudv1.ObjectStore
if err := c.Get(ctx, objectStoreKey, &freshObjectStore); err != nil {
return err
}
return ptr.To(metav1.NewTime(*t))
}
recoveryWindow := objectStore.Status.ServerRecoveryWindow[serverName]
recoveryWindow.FirstRecoverabilityPoint = convertTime(backupList.GetFirstRecoverabilityPoint())
recoveryWindow.LastSuccessfulBackupTime = convertTime(backupList.GetLastSuccessfulBackupTime())
// Set the recovery window inside the barman object store object
convertTime := func(t *time.Time) *metav1.Time {
if t == nil {
return nil
}
return ptr.To(metav1.NewTime(*t))
}
if objectStore.Status.ServerRecoveryWindow == nil {
objectStore.Status.ServerRecoveryWindow = make(map[string]barmancloudv1.RecoveryWindow)
}
objectStore.Status.ServerRecoveryWindow[serverName] = recoveryWindow
recoveryWindow := freshObjectStore.Status.ServerRecoveryWindow[serverName]
recoveryWindow.FirstRecoverabilityPoint = convertTime(backupList.GetFirstRecoverabilityPoint())
recoveryWindow.LastSuccessfulBackupTime = convertTime(backupList.GetLastSuccessfulBackupTime())
return c.Status().Update(ctx, objectStore)
if freshObjectStore.Status.ServerRecoveryWindow == nil {
freshObjectStore.Status.ServerRecoveryWindow = make(map[string]barmancloudv1.RecoveryWindow)
}
freshObjectStore.Status.ServerRecoveryWindow[serverName] = recoveryWindow
return c.Status().Update(ctx, &freshObjectStore)
})
}
// setLastFailedBackupTime sets the last failed backup time in the