-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add DLQ for reprocessing of failed blocks
- Loading branch information
1 parent
67dbd31
commit fd79804
Showing
14 changed files
with
578 additions
and
19 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,4 +22,7 @@ go.work | |
go.work.sum | ||
|
||
# Binary | ||
indexer | ||
indexer | ||
bin | ||
|
||
.idea |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
package ingester | ||
|
||
import ( | ||
"fmt" | ||
"slices" | ||
"sync" | ||
"time" | ||
|
||
"github.com/duneanalytics/blockchain-ingester/models" | ||
pq "github.com/emirpasic/gods/queues/priorityqueue" | ||
"github.com/emirpasic/gods/utils" | ||
) | ||
|
||
type DLQ struct { | ||
priorityQueue pq.Queue // structure not thread safe | ||
mutex sync.Mutex | ||
retryDelay func(int) time.Duration | ||
} | ||
|
||
// DLQBlock This is generic so that metadata about retries can be maintained in an envelope during processing for when | ||
// a block needs to make its way back onto the DLQ later | ||
type DLQBlock[T any] struct { | ||
Value T | ||
Retries int | ||
nextRunTime time.Time | ||
} | ||
|
||
func (b *DLQBlock[T]) String() string { | ||
return fmt.Sprintf("%+v", *b) | ||
} | ||
|
||
func MapDLQBlock[T, U any](b DLQBlock[T], mapper func(T) U) DLQBlock[U] { | ||
return DLQBlock[U]{ | ||
Value: mapper(b.Value), | ||
Retries: b.Retries, | ||
} | ||
} | ||
|
||
func NewDLQ() *DLQ { | ||
return &DLQ{priorityQueue: *pq.NewWith(byNextRunTime), retryDelay: retryDelayLinear} | ||
} | ||
|
||
func retryDelayLinear(retries int) time.Duration { | ||
return time.Duration(retries) * time.Minute | ||
} | ||
|
||
func NewDLQWithDelay(retryDelay func(int) time.Duration) *DLQ { | ||
return &DLQ{priorityQueue: *pq.NewWith(byNextRunTime), retryDelay: retryDelay} | ||
} | ||
|
||
// Comparator function (sort by retry count in ascending order) | ||
func byRetries(a, b interface{}) int { | ||
return utils.IntComparator(a.(DLQBlock[int64]).Retries, b.(DLQBlock[int64]).Retries) | ||
} | ||
|
||
// Comparator function (sort by nextRunTime in ascending order) | ||
func byNextRunTime(a, b interface{}) int { | ||
return utils.TimeComparator(a.(DLQBlock[int64]).nextRunTime, b.(DLQBlock[int64]).nextRunTime) | ||
} | ||
|
||
func (dlq *DLQ) AddBlockGaps(gaps []models.BlockGap) { | ||
// queue these in reverse so that recent blocks are retried first | ||
slices.SortFunc(gaps, func(a, b models.BlockGap) int { | ||
return -utils.Int64Comparator(a.FirstMissing, b.FirstMissing) | ||
}) | ||
|
||
dlq.mutex.Lock() | ||
defer dlq.mutex.Unlock() | ||
|
||
for _, gap := range gaps { | ||
for i := gap.FirstMissing; i <= gap.LastMissing; i++ { | ||
dlq.priorityQueue.Enqueue(DLQBlock[int64]{Value: i}) | ||
} | ||
} | ||
} | ||
|
||
func (dlq *DLQ) AddBlock(blockNumber int64, retries int) { | ||
nextRunTime := time.Now().Add(dlq.retryDelay(retries + 1)) | ||
|
||
dlq.mutex.Lock() | ||
defer dlq.mutex.Unlock() | ||
|
||
dlq.priorityQueue.Enqueue(DLQBlock[int64]{Value: blockNumber, Retries: retries + 1, nextRunTime: nextRunTime}) | ||
} | ||
|
||
func (dlq *DLQ) GetNextBlock() (value *DLQBlock[int64], ok bool) { | ||
dlq.mutex.Lock() | ||
defer dlq.mutex.Unlock() | ||
|
||
peek, ok := dlq.priorityQueue.Peek() | ||
if !ok || peek.(DLQBlock[int64]).nextRunTime.After(time.Now()) { | ||
return nil, false | ||
} | ||
|
||
block, ok := dlq.priorityQueue.Dequeue() | ||
if ok { | ||
blockCasted := block.(DLQBlock[int64]) | ||
return &blockCasted, ok | ||
} else { | ||
return nil, ok | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.