mirror of
https://github.com/rjNemo/rentease.git
synced 2026-06-10 20:56:50 +00:00
basic task scheduler
This commit is contained in:
parent
ee3674e12f
commit
b25d7be29d
4 changed files with 154 additions and 0 deletions
2
Makefile
2
Makefile
|
|
@ -9,6 +9,8 @@ run: build
|
|||
@docker run -p ${PORT}:${PORT} -e DATABASE_URL="host=docker.for.mac.host.internal user=${DB_USER} database=${DB_NAME}" -e PORT=${PORT} ${NAME}
|
||||
dev: templ
|
||||
@air cmd/main.go
|
||||
cron:
|
||||
@go run cmd/cron/main.go
|
||||
templ:
|
||||
@templ generate --watch --proxy=http://localhost:${PORT} &
|
||||
format:
|
||||
|
|
|
|||
48
cmd/cron/main.go
Normal file
48
cmd/cron/main.go
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
|
||||
"github.com/rjNemo/rentease/internal/cron"
|
||||
)
|
||||
|
||||
func main() {
|
||||
scheduler := cron.New()
|
||||
|
||||
scheduler.AddJob(cron.Job{
|
||||
Name: "Monthly Booking Report",
|
||||
Schedule: "minute",
|
||||
//Schedule: "monthly",
|
||||
Action: cron.JobMonthlyBookingReport,
|
||||
})
|
||||
|
||||
go scheduler.Start()
|
||||
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case err := <-scheduler.ErrChan:
|
||||
if err != nil {
|
||||
log.Println("Error:", err)
|
||||
}
|
||||
case msg := <-scheduler.SuccessChan:
|
||||
log.Print(msg)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
// Capture termination signals for graceful shutdown
|
||||
sigChan := make(chan os.Signal, 1)
|
||||
signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
|
||||
|
||||
// Wait for termination signal
|
||||
<-sigChan
|
||||
log.Println("Received termination signal, shutting down...")
|
||||
|
||||
// Stop the task manager and close channels
|
||||
scheduler.Stop()
|
||||
log.Println("All tasks stopped, exiting.")
|
||||
}
|
||||
88
internal/cron/cron.go
Normal file
88
internal/cron/cron.go
Normal file
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
16
internal/cron/job_report.go
Normal file
16
internal/cron/job_report.go
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
package cron
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"log"
|
||||
"time"
|
||||
)
|
||||
|
||||
func JobMonthlyBookingReport() error {
|
||||
now := time.Now()
|
||||
log.Println("Start Monthly Booking Report job at:", now)
|
||||
//err := booking.NewService().BuildReport("monthly", int(now.Month()), now.Year())
|
||||
err := errors.New("test")
|
||||
log.Printf("Executed Monthly Booking Report job at %v with errors: %s:", time.Now().Format(time.DateTime), err)
|
||||
return err
|
||||
}
|
||||
Loading…
Reference in a new issue