From 3f57232a9d88983bca68a180a95c64da63081cb2 Mon Sep 17 00:00:00 2001 From: Ruidy Date: Sun, 23 Mar 2025 22:57:34 +0100 Subject: [PATCH] move cron code to pkg --- cmd/cron/main.go | 4 +- internal/cron/job_report.go | 2 +- pkg/cron/cron.go | 88 +++++++++++++++++++++++++++++++++++++ 3 files changed, 91 insertions(+), 3 deletions(-) create mode 100644 pkg/cron/cron.go diff --git a/cmd/cron/main.go b/cmd/cron/main.go index 8c9f446..aae9908 100644 --- a/cmd/cron/main.go +++ b/cmd/cron/main.go @@ -6,7 +6,7 @@ import ( "os/signal" "syscall" - "github.com/rjNemo/rentease/internal/cron" + "github.com/rjNemo/rentease/pkg/cron" ) func main() { @@ -15,7 +15,7 @@ func main() { scheduler.AddJob(cron.Job{ Name: "Monthly Booking Report", Schedule: "minute", - //Schedule: "monthly", + // Schedule: "monthly", // Action: cron.JobMonthlyBookingReport, }) diff --git a/internal/cron/job_report.go b/internal/cron/job_report.go index f3730e1..d45b7e3 100644 --- a/internal/cron/job_report.go +++ b/internal/cron/job_report.go @@ -29,7 +29,7 @@ func JobMonthlyBookingReport() error { } store := booking.NewPgStore(db) - service, err := bookingService.NewService(store, nil, nil, ps) + service, err := bookingService.NewService(store, nil, ps) if err != nil { return fmt.Errorf("error creating booking service: %w", err) } diff --git a/pkg/cron/cron.go b/pkg/cron/cron.go new file mode 100644 index 0000000..637276f --- /dev/null +++ b/pkg/cron/cron.go @@ -0,0 +1,88 @@ +package cron + +import ( + "fmt" + "log" + "time" +) + +// Cron handles jobs scheduling and execution +type Cron struct { + jobs []Job + ErrChan chan error + DoneChan chan struct{} + SuccessChan chan string +} + +// Job is a type that holds the details for each job. +type Job struct { + Name string + Schedule string + Action JobFunc +} + +type JobFunc func() error + +func New() *Cron { + return &Cron{ + jobs: make([]Job, 0), + ErrChan: make(chan error), + SuccessChan: make(chan string), + DoneChan: make(chan struct{}), + } +} + +func (c *Cron) AddJob(job Job) { + c.jobs = append(c.jobs, job) +} + +func (c *Cron) Start() { + for _, j := range c.jobs { + go c.scheduleJob(j) + } +} + +func (c *Cron) Stop() { + close(c.DoneChan) + close(c.SuccessChan) + close(c.ErrChan) +} + +// scheduleJob adds a task to the Cron schedule based on its schedule +func (c *Cron) scheduleJob(j Job) { + for { + select { + case <-c.DoneChan: + log.Printf("stopping job %s", j.Name) + return + default: + now := time.Now() + + var next time.Time + switch j.Schedule { + case "minute": + next = now.Add(10 * time.Second) + case "daily": + next = now.AddDate(0, 0, 1).Truncate(24 * time.Hour) + case "weekly": + next = now.AddDate(0, 0, 7).Truncate(24 * time.Hour) + case "monthly": + nextMonth := now.AddDate(0, 1, 0) + next = time.Date(nextMonth.Year(), nextMonth.Month(), 1, 0, 0, 0, 0, nextMonth.Location()) + default: + log.Printf("Unknown schedule %q for job %q", j.Schedule, j.Name) + return + } + + sleepDuration := time.Until(next) + log.Printf("Job %q will run in %s", j.Name, sleepDuration.String()) + time.Sleep(sleepDuration) + + if err := j.Action(); err != nil { + c.ErrChan <- fmt.Errorf("job %s failed: %w", j.Name, err) + } else { + c.SuccessChan <- fmt.Sprintf("job %s completed successfully", j.Name) + } + } + } +}