2023-02-15 08:05:43 +01:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
2023-03-06 09:18:41 +01:00
|
|
|
"context"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/bsm/redislock"
|
2023-02-20 10:56:30 +01:00
|
|
|
"github.com/grassrootseconomics/cic-custodial/internal/custodial"
|
2023-02-15 08:05:43 +01:00
|
|
|
"github.com/grassrootseconomics/cic-custodial/internal/tasker"
|
|
|
|
"github.com/grassrootseconomics/cic-custodial/internal/tasker/task"
|
|
|
|
"github.com/grassrootseconomics/cic-custodial/pkg/redis"
|
|
|
|
"github.com/hibiken/asynq"
|
2023-03-06 09:18:41 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
fixedRetryCount = 25
|
|
|
|
fixedRetryPeriod = time.Second * 1
|
2023-02-15 08:05:43 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
// Load tasker handlers, injecting any necessary handler dependencies from the system container.
|
2023-02-20 10:56:30 +01:00
|
|
|
func initTasker(custodialContainer *custodial.Custodial, redisPool *redis.RedisPool) *tasker.TaskerServer {
|
2023-02-15 08:05:43 +01:00
|
|
|
taskerServerOpts := tasker.TaskerServerOpts{
|
2023-03-06 09:18:41 +01:00
|
|
|
Concurrency: ko.MustInt("asynq.worker_count"),
|
|
|
|
IsFailureHandler: isFailureHandler,
|
|
|
|
Logg: lo,
|
|
|
|
LogLevel: asynq.InfoLevel,
|
|
|
|
RedisPool: redisPool,
|
|
|
|
RetryHandler: retryHandler,
|
2023-02-15 08:05:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
taskerServer := tasker.NewTaskerServer(taskerServerOpts)
|
|
|
|
|
2023-03-06 09:18:41 +01:00
|
|
|
taskerServer.RegisterMiddlewareStack([]asynq.MiddlewareFunc{
|
2023-03-08 07:51:48 +01:00
|
|
|
observibilityMiddleware(),
|
2023-03-06 09:18:41 +01:00
|
|
|
})
|
|
|
|
|
2023-02-20 10:56:30 +01:00
|
|
|
taskerServer.RegisterHandlers(tasker.AccountRegisterTask, task.AccountRegisterOnChainProcessor(custodialContainer))
|
|
|
|
taskerServer.RegisterHandlers(tasker.AccountRefillGasTask, task.AccountRefillGasProcessor(custodialContainer))
|
|
|
|
taskerServer.RegisterHandlers(tasker.SignTransferTask, task.SignTransfer(custodialContainer))
|
2023-07-05 09:14:45 +02:00
|
|
|
taskerServer.RegisterHandlers(tasker.SignTransferTaskAuth, task.SignTransferAuthorizationProcessor(custodialContainer))
|
2023-02-20 10:56:30 +01:00
|
|
|
taskerServer.RegisterHandlers(tasker.DispatchTxTask, task.DispatchTx(custodialContainer))
|
2023-02-15 08:05:43 +01:00
|
|
|
|
|
|
|
return taskerServer
|
|
|
|
}
|
2023-03-06 09:18:41 +01:00
|
|
|
|
|
|
|
func isFailureHandler(err error) bool {
|
|
|
|
switch err {
|
|
|
|
// Ignore lock contention errors; retry until lock obtain.
|
|
|
|
case redislock.ErrNotObtained:
|
|
|
|
return false
|
|
|
|
default:
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func retryHandler(count int, err error, task *asynq.Task) time.Duration {
|
|
|
|
if count < fixedRetryCount {
|
|
|
|
return fixedRetryPeriod
|
|
|
|
} else {
|
|
|
|
return asynq.DefaultRetryDelayFunc(count, err, task)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-03-08 07:51:48 +01:00
|
|
|
func observibilityMiddleware() asynq.MiddlewareFunc {
|
2023-03-06 09:18:41 +01:00
|
|
|
return func(handler asynq.Handler) asynq.Handler {
|
|
|
|
return asynq.HandlerFunc(func(ctx context.Context, task *asynq.Task) error {
|
|
|
|
taskId, _ := asynq.GetTaskID(ctx)
|
|
|
|
|
|
|
|
err := handler.ProcessTask(ctx, task)
|
|
|
|
if err != nil && isFailureHandler(err) {
|
|
|
|
lo.Error("tasker: handler error", "err", err, "task_type", task.Type(), "task_id", taskId)
|
2023-03-16 13:03:51 +01:00
|
|
|
} else if asynq.IsPanicError(err) {
|
|
|
|
lo.Error("tasker: handler panic", "err", err, "task_type", task.Type(), "task_id", taskId)
|
2023-03-06 09:18:41 +01:00
|
|
|
} else {
|
|
|
|
lo.Info("tasker: process task", "task_type", task.Type(), "task_id", taskId)
|
|
|
|
}
|
|
|
|
|
|
|
|
return err
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|