From 1d31f50502715668abb90667f24a299c5e6ef407 Mon Sep 17 00:00:00 2001 From: Piotr Stachyra Date: Mon, 11 Mar 2024 12:19:19 +0100 Subject: [PATCH] add exponential backoff when doing updates --- src/cassandra.go | 12 +++++++++++- src/operation.go | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 src/operation.go diff --git a/src/cassandra.go b/src/cassandra.go index 4aacbc8..c912ce9 100644 --- a/src/cassandra.go +++ b/src/cassandra.go @@ -157,7 +157,7 @@ func (kc *CassandraContext) selectRange(startTime, endTime time.Time) ([]Submiss return submissions, nil } -func (kc *CassandraContext) updateSubmissions(submissions []Submission) error { +func (kc *CassandraContext) tryUpdateSubmissions(submissions []Submission) error { // Define your dummy values here dummyStateHash := "dummy_state_hash" dummyParent := "dummy_parent" @@ -182,6 +182,16 @@ func (kc *CassandraContext) updateSubmissions(submissions []Submission) error { return nil } +func (kc *CassandraContext) updateSubmissions(submissions []Submission) error { + return ExponentialBackoff(func() error { + if err := kc.tryUpdateSubmissions(submissions); err != nil { + kc.Log.Errorf("Error updating submissions (trying again): %v", err) + return err + } + return nil + }, maxRetries, initialBackoff) +} + // func (kc *CassandraContext) updateSubmissionsBatch(submissions []Submission) error { // batch := kc.Session.NewBatch(gocql.LoggedBatch) // Use gocql.UnloggedBatch for unlogged batches diff --git a/src/operation.go b/src/operation.go new file mode 100644 index 0000000..c0bf875 --- /dev/null +++ b/src/operation.go @@ -0,0 +1,34 @@ +package main + +import ( + "fmt" + "time" +) + +// Operation is a function type that represents an operation that might fail and need a retry. +type Operation func() error + +const ( + maxRetries = 5 + initialBackoff = 300 * time.Millisecond +) + +// ExponentialBackoff retries the provided operation with an exponential backoff strategy. +func ExponentialBackoff(operation Operation, maxRetries int, initialBackoff time.Duration) error { + backoff := initialBackoff + var err error + for i := 0; i < maxRetries; i++ { + err = operation() + if err == nil { + return nil // Success + } + + if i < maxRetries-1 { + // If not the last retry, wait for a bit + time.Sleep(backoff) + backoff *= 2 // Exponential increase + } + } + + return fmt.Errorf("operation failed after %d retries, returned error: %s", maxRetries, err) +}