New JobQueue worker
This commit is contained in:
46
backend/internal/jobqueue/main.go
Normal file
46
backend/internal/jobqueue/main.go
Normal file
@ -0,0 +1,46 @@
|
||||
package jobqueue
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
)
|
||||
|
||||
var (
|
||||
ctx context.Context
|
||||
cancel context.CancelFunc
|
||||
worker *Worker
|
||||
)
|
||||
|
||||
// Start ...
|
||||
func Start() {
|
||||
ctx, cancel = context.WithCancel(context.Background())
|
||||
q := &Queue{
|
||||
jobs: make(chan Job),
|
||||
ctx: ctx,
|
||||
cancel: cancel,
|
||||
}
|
||||
|
||||
// Defines a queue worker, which will execute our queue.
|
||||
worker = newWorker(q)
|
||||
|
||||
// Execute jobs in queue.
|
||||
go worker.doWork()
|
||||
}
|
||||
|
||||
// AddJob adds a job to the queue for processing
|
||||
func AddJob(j Job) error {
|
||||
if worker == nil {
|
||||
return errors.New("Unable to add job, jobqueue has not been started")
|
||||
}
|
||||
worker.Queue.AddJob(j)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Shutdown ...
|
||||
func Shutdown() error {
|
||||
if cancel == nil {
|
||||
return errors.New("Unable to shutdown, jobqueue has not been started")
|
||||
}
|
||||
cancel()
|
||||
return nil
|
||||
}
|
58
backend/internal/jobqueue/models.go
Normal file
58
backend/internal/jobqueue/models.go
Normal file
@ -0,0 +1,58 @@
|
||||
package jobqueue
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// Queue holds name, list of jobs and context with cancel.
|
||||
type Queue struct {
|
||||
jobs chan Job
|
||||
ctx context.Context
|
||||
cancel context.CancelFunc
|
||||
}
|
||||
|
||||
// Job - holds logic to perform some operations during queue execution.
|
||||
type Job struct {
|
||||
Name string
|
||||
Action func() error // A function that should be executed when the job is running.
|
||||
}
|
||||
|
||||
// AddJobs adds jobs to the queue and cancels channel.
|
||||
func (q *Queue) AddJobs(jobs []Job) {
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(len(jobs))
|
||||
|
||||
for _, job := range jobs {
|
||||
// Goroutine which adds job to the queue.
|
||||
go func(job Job) {
|
||||
q.AddJob(job)
|
||||
wg.Done()
|
||||
}(job)
|
||||
}
|
||||
|
||||
go func() {
|
||||
wg.Wait()
|
||||
// Cancel queue channel, when all goroutines were done.
|
||||
q.cancel()
|
||||
}()
|
||||
}
|
||||
|
||||
// AddJob sends job to the channel.
|
||||
func (q *Queue) AddJob(job Job) {
|
||||
q.jobs <- job
|
||||
log.Printf("New job %s added to queue", job.Name)
|
||||
}
|
||||
|
||||
// Run performs job execution.
|
||||
func (j Job) Run() error {
|
||||
log.Printf("Job running: %s", j.Name)
|
||||
|
||||
err := j.Action()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
36
backend/internal/jobqueue/worker.go
Normal file
36
backend/internal/jobqueue/worker.go
Normal file
@ -0,0 +1,36 @@
|
||||
package jobqueue
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"npm/internal/logger"
|
||||
)
|
||||
|
||||
// Worker responsible for queue serving.
|
||||
type Worker struct {
|
||||
Queue *Queue
|
||||
}
|
||||
|
||||
func newWorker(queue *Queue) *Worker {
|
||||
return &Worker{
|
||||
Queue: queue,
|
||||
}
|
||||
}
|
||||
|
||||
// doWork processes jobs from the queue (jobs channel).
|
||||
func (w *Worker) doWork() bool {
|
||||
for {
|
||||
select {
|
||||
// if context was canceled.
|
||||
case <-w.Queue.ctx.Done():
|
||||
logger.Info("JobQueue worker graceful shutdown")
|
||||
return true
|
||||
// if job received.
|
||||
case job := <-w.Queue.jobs:
|
||||
err := job.Run()
|
||||
if err != nil {
|
||||
logger.Error(fmt.Sprintf("%sError", job.Name), err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user