diff --git a/integrations/access/common/app.go b/integrations/access/common/app.go index 5eaacf4061922..93e996d7da3aa 100644 --- a/integrations/access/common/app.go +++ b/integrations/access/common/app.go @@ -419,7 +419,7 @@ func (a *BaseApp) updateMessages(ctx context.Context, reqID string, tag pd.Resol // If resolution field is not empty then we already resolved the incident before. In this case we just quit. if existing.AccessRequestData.ResolutionTag != pd.Unresolved { - return GenericPluginData{}, trace.CompareFailed("request is already resolved") + return GenericPluginData{}, trace.AlreadyExists("request is already resolved") } // Mark plugin data as resolved. @@ -432,6 +432,15 @@ func (a *BaseApp) updateMessages(ctx context.Context, reqID string, tag pd.Resol log.Debug("Failed to update messages: plugin data is missing") return nil } + if trace.IsAlreadyExists(err) { + if tag != pluginData.ResolutionTag { + return trace.WrapWithMessage(err, + "cannot change the resolution tag of an already resolved request, existing: %s, event: %s", + pluginData.ResolutionTag, tag) + } + log.Debug("Request is already resolved, ignoring event") + return nil + } if err != nil { return trace.Wrap(err) } diff --git a/integrations/lib/plugindata/cas.go b/integrations/lib/plugindata/cas.go index 50b09374735b6..041df7a1172d2 100644 --- a/integrations/lib/plugindata/cas.go +++ b/integrations/lib/plugindata/cas.go @@ -101,10 +101,10 @@ func (c *CompareAndSwap[T]) Create( // Update tries to perform compare-and-swap update of a plugin data assuming that it exist // // modifyT will receive existing plugin data and should return a modified version of the data. - +// // If existing plugin data does not match expected data, then a trace.CompareFailed error should // be returned to backoff and try again. - +// // To abort the update, modifyT should return an error other, than trace.CompareFailed, which // will be propagated back to the caller of `Update`. func (c *CompareAndSwap[T]) Update( @@ -131,6 +131,7 @@ func (c *CompareAndSwap[T]) Update( if trace.IsCompareFailed(err) { failedAttempts = append(failedAttempts, trace.Wrap(err)) backoffErr := backoff.Do(ctx) + // backoffErr is not nil when the context has expired and we must return if backoffErr != nil { failedAttempts = append(failedAttempts, trace.Wrap(backoffErr)) return emptyData, trace.NewAggregate(failedAttempts...) @@ -152,6 +153,7 @@ func (c *CompareAndSwap[T]) Update( // A conflict happened, we register the failed attempt and wait before retrying failedAttempts = append(failedAttempts, trace.Wrap(err)) backoffErr := backoff.Do(ctx) + // backoffErr is not nil when the context has expired and we must return if backoffErr != nil { failedAttempts = append(failedAttempts, trace.Wrap(backoffErr)) return emptyData, trace.NewAggregate(failedAttempts...)