Use same db for tasks.

This commit is contained in:
mikestefanello 2024-06-19 12:51:54 -04:00
parent 8abe5e5f02
commit edf9af8fc4
3 changed files with 54 additions and 39 deletions

View file

@ -106,6 +106,7 @@ type (
// TasksConfig stores the tasks configuration // TasksConfig stores the tasks configuration
TasksConfig struct { TasksConfig struct {
// TODO remove separate DB?
Driver string Driver string
Connection string Connection string
TestConnection string TestConnection string

View file

@ -177,7 +177,9 @@ func (c *Container) initMail() {
// initTasks initializes the task client // initTasks initializes the task client
func (c *Container) initTasks() { func (c *Container) initTasks() {
var err error var err error
c.Tasks, err = NewTaskClient(c.Config) // You could use a separate database for tasks, if you'd like. but using one
// makes transaction support easier
c.Tasks, err = NewTaskClient(c.Config.Tasks, c.Database)
if err != nil { if err != nil {
panic(fmt.Sprintf("failed to create task client: %v", err)) panic(fmt.Sprintf("failed to create task client: %v", err))
} }

View file

@ -20,7 +20,6 @@ type (
TaskClient struct { TaskClient struct {
queue *goqite.Queue queue *goqite.Queue
runner *jobs.Runner runner *jobs.Runner
db *sql.DB
} }
Task interface { Task interface {
@ -37,6 +36,7 @@ type (
//maxRetries *int //maxRetries *int
//timeout *time.Duration //timeout *time.Duration
//deadline *time.Time //deadline *time.Time
tx *sql.Tx
at *time.Time at *time.Time
wait *time.Duration wait *time.Duration
//retain *time.Duration //retain *time.Duration
@ -81,24 +81,24 @@ func (q *queue[T]) Receive(ctx context.Context, payload []byte) error {
} }
// NewTaskClient creates a new task client // NewTaskClient creates a new task client
func NewTaskClient(cfg *config.Config) (*TaskClient, error) { func NewTaskClient(cfg config.TasksConfig, db *sql.DB) (*TaskClient, error) {
var connection string //var connection string
//
switch cfg.App.Environment { //switch cfg.App.Environment {
case config.EnvTest: //case config.EnvTest:
connection = cfg.Tasks.TestConnection // connection = cfg.Tasks.TestConnection
default: //default:
connection = cfg.Tasks.Connection // connection = cfg.Tasks.Connection
} //}
//
db, err := openDB(cfg.Tasks.Driver, connection) //db, err := openDB(cfg.Tasks.Driver, connection)
if err != nil { //if err != nil {
return nil, err // return nil, err
} //}
//
// TODO is this correct? //// TODO is this correct?
db.SetMaxOpenConns(cfg.Tasks.Goroutines) //db.SetMaxOpenConns(cfg.Tasks.Goroutines)
db.SetMaxIdleConns(cfg.Tasks.Goroutines) //db.SetMaxIdleConns(cfg.Tasks.Goroutines)
// Install the schema // Install the schema
if err := goqite.Setup(context.Background(), db); err != nil { if err := goqite.Setup(context.Background(), db); err != nil {
@ -113,29 +113,29 @@ func NewTaskClient(cfg *config.Config) (*TaskClient, error) {
queue: goqite.New(goqite.NewOpts{ queue: goqite.New(goqite.NewOpts{
DB: db, DB: db,
Name: "tasks", Name: "tasks",
MaxReceive: cfg.Tasks.MaxRetries, MaxReceive: cfg.MaxRetries,
}), }),
db: db,
} }
t.runner = jobs.NewRunner(jobs.NewRunnerOpts{ t.runner = jobs.NewRunner(jobs.NewRunnerOpts{
Limit: cfg.Tasks.Goroutines, Limit: cfg.Goroutines,
Log: log.Default(), Log: log.Default(),
PollInterval: cfg.Tasks.PollInterval, PollInterval: cfg.PollInterval,
Queue: t.queue, Queue: t.queue,
}) })
return t, nil return t, nil
} }
// Close closes the connection to the task service //// Close closes the connection to the task service
func (t *TaskClient) Close() error { //func (t *TaskClient) Close() error {
// TODO close the runner // // TODO close the runner
return t.db.Close() // return t.db.Close()
} //}
// StartRunner starts the scheduler service which adds scheduled tasks to the queue // StartRunner starts the scheduler service which adds scheduled tasks to the queue.
// This must be running in order to queue tasks set for periodic execution // This must be running in order to execute queued tasked.
// To stop the runner, cancel the context.
func (t *TaskClient) StartRunner(ctx context.Context) { func (t *TaskClient) StartRunner(ctx context.Context) {
t.runner.Start(ctx) t.runner.Start(ctx)
} }
@ -164,21 +164,33 @@ func (t *TaskOp) Wait(duration time.Duration) *TaskOp {
return t return t
} }
// Tx will insert the task as part of a given database transaction
func (t *TaskOp) Tx(tx *sql.Tx) *TaskOp {
t.tx = tx
return t
}
// Save saves the task so it can be executed // Save saves the task so it can be executed
func (t *TaskOp) Save() error { func (t *TaskOp) Save() error {
// Build the payload // Build the payload
// TODO use gob?
payload, err := json.Marshal(t.task) payload, err := json.Marshal(t.task)
if err != nil { if err != nil {
return err return err
} }
msg := goqite.Message{ //msg := goqite.Message{
Body: payload, // Body: payload,
} //}
//
if t.wait != nil { //if t.wait != nil {
msg.Delay = *t.wait // msg.Delay = *t.wait
} //}
// TODO support delay
//return t.client.queue.Send(context.Background(), msg) //return t.client.queue.Send(context.Background(), msg)
return jobs.Create(context.Background(), t.client.queue, t.task.Name(), payload) if t.tx == nil {
return jobs.Create(context.Background(), t.client.queue, t.task.Name(), payload)
} else {
return jobs.CreateTx(context.Background(), t.tx, t.client.queue, t.task.Name(), payload)
}
} }