diff --git a/internal/api/v1beta1/org.go b/internal/api/v1beta1/org.go index 2558f5173..87b598652 100644 --- a/internal/api/v1beta1/org.go +++ b/internal/api/v1beta1/org.go @@ -3,6 +3,8 @@ package v1beta1 import ( "context" + "github.com/raystack/frontier/core/serviceuser" + "github.com/raystack/frontier/core/authenticate" "go.uber.org/zap" @@ -318,13 +320,15 @@ func (h Handler) ListOrganizationServiceUsers(ctx context.Context, request *fron } } - users, err := h.serviceUserService.ListByOrg(ctx, orgResp.ID) + usersList, err := h.serviceUserService.List(ctx, serviceuser.Filter{ + OrgID: orgResp.ID, + }) if err != nil { return nil, err } var usersPB []*frontierv1beta1.ServiceUser - for _, rel := range users { + for _, rel := range usersList { u, err := transformServiceUserToPB(rel) if err != nil { return nil, err diff --git a/internal/api/v1beta1/org_test.go b/internal/api/v1beta1/org_test.go index e2299bc13..416d19c5b 100644 --- a/internal/api/v1beta1/org_test.go +++ b/internal/api/v1beta1/org_test.go @@ -790,7 +790,9 @@ func TestHandler_ListOrganizationServiceUsers(t *testing.T) { for _, u := range testUserMap { testUserList = append(testUserList, u) } - us.EXPECT().ListByOrg(mock.AnythingOfType("context.backgroundCtx"), testOrgID).Return([]serviceuser.ServiceUser{ + us.EXPECT().List(mock.AnythingOfType("context.backgroundCtx"), serviceuser.Filter{ + OrgID: testOrgID, + }).Return([]serviceuser.ServiceUser{ { ID: "9f256f86-31a3-11ec-8d3d-0242ac130003", Title: "Sample Service User", diff --git a/internal/store/postgres/billing_transactions_repository.go b/internal/store/postgres/billing_transactions_repository.go index 2ca78bc95..a19504794 100644 --- a/internal/store/postgres/billing_transactions_repository.go +++ b/internal/store/postgres/billing_transactions_repository.go @@ -6,10 +6,12 @@ import ( "encoding/json" "errors" "fmt" + "math/rand" "strings" "time" "github.com/raystack/frontier/billing/customer" + "github.com/raystack/frontier/internal/bootstrap/schema" "github.com/jackc/pgconn" @@ -81,131 +83,143 @@ func NewBillingTransactionRepository(dbc *db.Client) *BillingTransactionReposito } } +var ( + maxRetries = 5 + // Error codes from https://www.postgresql.org/docs/current/errcodes-appendix.html + serializationFailureCode = "40001" + deadlockDetectedCode = "40P01" +) + +func (r BillingTransactionRepository) withRetry(ctx context.Context, fn func() error) error { + var lastErr error + for i := 0; i < maxRetries && ctx.Err() == nil; i++ { + err := fn() + if err == nil { + return nil + } + + var pqErr *pgconn.PgError + if errors.As(err, &pqErr) { + // Retry on serialization failures or deadlocks + if pqErr.Code == serializationFailureCode || pqErr.Code == deadlockDetectedCode { + lastErr = err + // Exponential backoff with jitter + backoff := time.Duration(1<