feat: add context support to error handlers for improved cancellation and error management

This commit is contained in:
2026-04-08 23:07:41 -05:00
parent d3a3b26bb3
commit 0ee5d9032c
3 changed files with 76 additions and 32 deletions

View File

@@ -1,6 +1,7 @@
package main package main
import ( import (
"context"
"fmt" "fmt"
"github.com/google/uuid" "github.com/google/uuid"
@@ -19,29 +20,57 @@ func (e *ExtractorError) Error() string {
const maxRetryAttempts = 3 const maxRetryAttempts = 3
func extractorErrorHandler(chErrorsIn <-chan ExtractorError, chBatchesOut chan<- Batch, chJobErrorsOut chan<- JobError) { func extractorErrorHandler(
for err := range chErrorsIn { ctx context.Context,
if err.RetryCounter >= maxRetryAttempts { chErrorsIn <-chan ExtractorError,
jobError := JobError{ chBatchesOut chan<- Batch,
ShouldCancelJob: false, chJobErrorsOut chan<- JobError,
Msg: fmt.Sprintf("batch %v reached max retries (%d)", err.Id, maxRetryAttempts), ) {
Prev: &err, for {
if ctx.Err() != nil {
return
}
select {
case <-ctx.Done():
return
case err, ok := <-chErrorsIn:
if !ok {
return
}
if err.RetryCounter >= maxRetryAttempts {
jobError := JobError{
ShouldCancelJob: false,
Msg: fmt.Sprintf("batch %v reached max retries (%d)", err.Id, maxRetryAttempts),
Prev: &err,
}
select {
case chJobErrorsOut <- jobError:
case <-ctx.Done():
return
}
continue
}
newBatch := err.Batch
newBatch.RetryCounter++
if err.HasLastId {
newBatch.ParentId = err.Id
newBatch.Id = uuid.New()
newBatch.LowerLimit = err.LastId
newBatch.IsLowerLimitInclusive = false
}
select {
case chBatchesOut <- newBatch:
case <-ctx.Done():
return
} }
chJobErrorsOut <- jobError
continue
} }
newBatch := err.Batch
newBatch.RetryCounter++
if err.HasLastId {
newBatch.ParentId = err.Id
newBatch.Id = uuid.New()
newBatch.LowerLimit = err.LastId
newBatch.IsLowerLimitInclusive = false
}
chBatchesOut <- newBatch
} }
} }

View File

@@ -1,6 +1,7 @@
package main package main
import ( import (
"context"
"fmt" "fmt"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
@@ -16,18 +17,30 @@ func (e *JobError) Error() string {
if e.Prev != nil { if e.Prev != nil {
return fmt.Sprintf("%s: %v", e.Msg, e.Prev) return fmt.Sprintf("%s: %v", e.Msg, e.Prev)
} }
return e.Msg return e.Msg
} }
func jobErrorHandler(chErrorsIn <-chan JobError) error { func jobErrorHandler(ctx context.Context, chErrorsIn <-chan JobError) error {
for err := range chErrorsIn { for {
if err.ShouldCancelJob { if ctx.Err() != nil {
return &err return nil
} }
log.Error(err) select {
} case <-ctx.Done():
return nil
return nil case err, ok := <-chErrorsIn:
if !ok {
return nil
}
if err.ShouldCancelJob {
return &err
}
log.Error(err)
}
}
} }

View File

@@ -36,8 +36,10 @@ func processMigrationJob(sourceDb *sql.DB, targetDb *pgxpool.Pool, job Migration
defer close(chJobErrors) defer close(chJobErrors)
go func() { go func() {
if err := jobErrorHandler(chJobErrors); err != nil { if err := jobErrorHandler(ctx, chJobErrors); err != nil {
cancel() if ctx.Err() == nil {
cancel()
}
} }
}() }()
@@ -45,7 +47,7 @@ func processMigrationJob(sourceDb *sql.DB, targetDb *pgxpool.Pool, job Migration
chExtractorErrors := make(chan ExtractorError, len(batches)) chExtractorErrors := make(chan ExtractorError, len(batches))
go func() { go func() {
extractorErrorHandler(chExtractorErrors, chBatches, chJobErrors) extractorErrorHandler(ctx, chExtractorErrors, chBatches, chJobErrors)
}() }()
chChunks := make(chan Chunk, QueueSize) chChunks := make(chan Chunk, QueueSize)