From 2cfc06a7568659cb7583e91c73022b026d41219f Mon Sep 17 00:00:00 2001
From: aeneasr <3372410+aeneasr@users.noreply.github.com>
Date: Mon, 25 Nov 2024 11:13:59 +0100
Subject: [PATCH] feat: retry crdb serializable errors

---
 go.mod                              | 2 +-
 go.sum                              | 4 ++--
 oauth2/oauth2_refresh_token_test.go | 4 +++-
 persistence/sql/persister_oauth2.go | 8 ++++----
 4 files changed, 10 insertions(+), 8 deletions(-)

diff --git a/go.mod b/go.mod
index 26adbfc96ce..8092bf8a20a 100644
--- a/go.mod
+++ b/go.mod
@@ -13,7 +13,7 @@ replace github.com/gobuffalo/pop/v6 => github.com/ory/pop/v6 v6.2.0
 //
 // This is needed until we release the next version of the master branch, as that branch already contains the redirect URI validation fix, which
 // may be breaking for some users.
-replace github.com/ory/fosite => github.com/ory/fosite v0.47.1-0.20241101073333-eab241e153a4
+replace github.com/ory/fosite => github.com/ory/fosite v0.47.1-0.20241125094724-b6468e644902
 
 require (
 	github.com/ThalesIgnite/crypto11 v1.2.5
diff --git a/go.sum b/go.sum
index 5f7a2ba7603..a81e9e76d2b 100644
--- a/go.sum
+++ b/go.sum
@@ -378,8 +378,8 @@ github.com/ory/analytics-go/v5 v5.0.1 h1:LX8T5B9FN8KZXOtxgN+R3I4THRRVB6+28IKgKBp
 github.com/ory/analytics-go/v5 v5.0.1/go.mod h1:lWCiCjAaJkKfgR/BN5DCLMol8BjKS1x+4jxBxff/FF0=
 github.com/ory/dockertest/v3 v3.10.1-0.20240704115616-d229e74b748d h1:By96ZSVuH5LyjXLVVMfvJoLVGHaT96LdOnwgFSLVf0E=
 github.com/ory/dockertest/v3 v3.10.1-0.20240704115616-d229e74b748d/go.mod h1:F2FIjwwAk6CsNAs//B8+aPFQF0t84pbM8oliyNXwQrk=
-github.com/ory/fosite v0.47.1-0.20241101073333-eab241e153a4 h1:1pEVHGC+Dx2xMPMgpRgG3lyejyK8iU9KKfSnLowLYd8=
-github.com/ory/fosite v0.47.1-0.20241101073333-eab241e153a4/go.mod h1:AZyn1jrABUaGN12RHcWorRLbqLn52gTdHaIYY81m5J0=
+github.com/ory/fosite v0.47.1-0.20241125094724-b6468e644902 h1:X0ngo+uPWCw90ueY3Kh6q8IyF2fbwkJ8bf9RvAmD71U=
+github.com/ory/fosite v0.47.1-0.20241125094724-b6468e644902/go.mod h1:AZyn1jrABUaGN12RHcWorRLbqLn52gTdHaIYY81m5J0=
 github.com/ory/go-acc v0.2.9-0.20230103102148-6b1c9a70dbbe h1:rvu4obdvqR0fkSIJ8IfgzKOWwZ5kOT2UNfLq81Qk7rc=
 github.com/ory/go-acc v0.2.9-0.20230103102148-6b1c9a70dbbe/go.mod h1:z4n3u6as84LbV4YmgjHhnwtccQqzf4cZlSk9f1FhygI=
 github.com/ory/go-convenience v0.1.0 h1:zouLKfF2GoSGnJwGq+PE/nJAE6dj2Zj5QlTgmMTsTS8=
diff --git a/oauth2/oauth2_refresh_token_test.go b/oauth2/oauth2_refresh_token_test.go
index 849fae06460..ffabb0dd2a0 100644
--- a/oauth2/oauth2_refresh_token_test.go
+++ b/oauth2/oauth2_refresh_token_test.go
@@ -172,8 +172,10 @@ func TestCreateRefreshTokenSessionStress(t *testing.T) {
 									"RETRY_WRITE_TOO_OLD",
 									// refresh token reuse detection
 									"token_inactive",
+									// Failed to refresh token because of multiple concurrent requests using the same token which is not allowed.
+									"multiple concurrent requests",
 								} {
-									if strings.Contains(e.DebugField, errSubstr) {
+									if strings.Contains(e.DebugField+e.HintField, errSubstr) {
 										matched = true
 										break
 									}
diff --git a/persistence/sql/persister_oauth2.go b/persistence/sql/persister_oauth2.go
index 083e67ac5da..b67b6ae17ed 100644
--- a/persistence/sql/persister_oauth2.go
+++ b/persistence/sql/persister_oauth2.go
@@ -254,7 +254,7 @@ func (p *Persister) createSession(ctx context.Context, signature string, request
 	}
 
 	if err = sqlcon.HandleError(p.CreateWithNetwork(ctx, req)); errors.Is(err, sqlcon.ErrConcurrentUpdate) {
-		return errors.Wrap(fosite.ErrSerializationFailure, err.Error())
+		return fosite.ErrSerializationFailure.WithWrap(err)
 	} else if err != nil {
 		return err
 	}
@@ -293,7 +293,7 @@ func (p *Persister) deleteSessionBySignature(ctx context.Context, signature stri
 		return errorsx.WithStack(fosite.ErrNotFound)
 	}
 	if errors.Is(err, sqlcon.ErrConcurrentUpdate) {
-		return errors.Wrap(fosite.ErrSerializationFailure, err.Error())
+		return fosite.ErrSerializationFailure.WithWrap(err)
 	}
 	return err
 }
@@ -310,7 +310,7 @@ func (p *Persister) deleteSessionByRequestID(ctx context.Context, id string, tab
 	}
 	if err := sqlcon.HandleError(err); err != nil {
 		if errors.Is(err, sqlcon.ErrConcurrentUpdate) {
-			return errors.Wrap(fosite.ErrSerializationFailure, err.Error())
+			return fosite.ErrSerializationFailure.WithWrap(err)
 		}
 		if strings.Contains(err.Error(), "Error 1213") { // InnoDB Deadlock?
 			return errors.Wrap(fosite.ErrSerializationFailure, err.Error())
@@ -426,7 +426,7 @@ func (p *Persister) DeleteAccessTokenSession(ctx context.Context, signature stri
 		}
 	}
 	if errors.Is(err, sqlcon.ErrConcurrentUpdate) {
-		return errors.Wrap(fosite.ErrSerializationFailure, err.Error())
+		return fosite.ErrSerializationFailure.WithWrap(err)
 	}
 	return err
 }