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,15 +20,38 @@ 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,
chErrorsIn <-chan ExtractorError,
chBatchesOut chan<- Batch,
chJobErrorsOut chan<- JobError,
) {
for {
if ctx.Err() != nil {
return
}
select {
case <-ctx.Done():
return
case err, ok := <-chErrorsIn:
if !ok {
return
}
if err.RetryCounter >= maxRetryAttempts { if err.RetryCounter >= maxRetryAttempts {
jobError := JobError{ jobError := JobError{
ShouldCancelJob: false, ShouldCancelJob: false,
Msg: fmt.Sprintf("batch %v reached max retries (%d)", err.Id, maxRetryAttempts), Msg: fmt.Sprintf("batch %v reached max retries (%d)", err.Id, maxRetryAttempts),
Prev: &err, Prev: &err,
} }
chJobErrorsOut <- jobError
select {
case chJobErrorsOut <- jobError:
case <-ctx.Done():
return
}
continue continue
} }
@@ -41,7 +65,12 @@ func extractorErrorHandler(chErrorsIn <-chan ExtractorError, chBatchesOut chan<-
newBatch.IsLowerLimitInclusive = false newBatch.IsLowerLimitInclusive = false
} }
chBatchesOut <- newBatch select {
case chBatchesOut <- newBatch:
case <-ctx.Done():
return
}
}
} }
} }

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"
@@ -20,14 +21,26 @@ func (e *JobError) Error() string {
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 ctx.Err() != nil {
return nil
}
select {
case <-ctx.Done():
return nil
case err, ok := <-chErrorsIn:
if !ok {
return nil
}
if err.ShouldCancelJob { if err.ShouldCancelJob {
return &err return &err
} }
log.Error(err) log.Error(err)
} }
}
return nil
} }

View File

@@ -36,16 +36,18 @@ 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 {
if ctx.Err() == nil {
cancel() cancel()
} }
}
}() }()
chBatches := make(chan Batch, len(batches)) chBatches := make(chan Batch, len(batches))
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)