Last active
October 22, 2024 13:20
-
-
Save kubosuke/8c67721d3605055bc59ec6b52ced3a2b to your computer and use it in GitHub Desktop.
Go sequential cronjob sample
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"fmt" | |
"log" | |
"os" | |
"os/signal" | |
"sync" | |
"syscall" | |
"time" | |
) | |
type Job interface { | |
Execute() | |
} | |
type JobQueue struct { | |
jobs chan Job | |
wg sync.WaitGroup | |
quit chan bool | |
closed bool | |
mu sync.Mutex | |
} | |
func NewJobQueue() *JobQueue { | |
jq := &JobQueue{ | |
jobs: make(chan Job), | |
quit: make(chan bool), | |
} | |
jq.wg.Add(1) | |
go jq.worker() | |
return jq | |
} | |
func (jq *JobQueue) Enqueue(job Job) { | |
jq.mu.Lock() | |
defer jq.mu.Unlock() | |
if jq.closed { | |
log.Println("Attempt to enqueue on closed queue") | |
return | |
} | |
jq.jobs <- job | |
} | |
func (jq *JobQueue) worker() { | |
defer jq.wg.Done() | |
for { | |
select { | |
case job := <-jq.jobs: | |
job.Execute() | |
case <-jq.quit: | |
return | |
} | |
} | |
} | |
func (jq *JobQueue) Close() { | |
jq.mu.Lock() | |
if !jq.closed { | |
jq.closed = true | |
close(jq.quit) | |
jq.wg.Wait() | |
close(jq.jobs) | |
} | |
jq.mu.Unlock() | |
} | |
type ExampleJob struct { | |
ID string | |
DateTime time.Time | |
} | |
func NewExampleJob() ExampleJob { | |
return ExampleJob{ | |
ID: generateShortUUID(), | |
DateTime: time.Now(), | |
} | |
} | |
func generateShortUUID() string { | |
return fmt.Sprintf("%x", time.Now().UnixNano()) | |
} | |
func (e ExampleJob) Execute() { | |
fmt.Printf("🚀 Enqueued job %s at %s, execution started at %s\n", e.ID, e.DateTime.Format(time.RFC3339), time.Now().Format(time.RFC3339)) | |
time.Sleep(5 * time.Second) | |
fmt.Printf("✅ Job %s done\n", e.ID) | |
} | |
func main() { | |
jq := NewJobQueue() | |
sigChan := make(chan os.Signal, 1) | |
signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM) | |
ticker := time.NewTicker(5 * time.Second) | |
done := make(chan bool, 1) | |
go func() { | |
for { | |
select { | |
case <-ticker.C: | |
for i := 0; i < 5; i++ { | |
go jq.Enqueue(NewExampleJob()) | |
} | |
case sig := <-sigChan: | |
fmt.Printf("⚠️ Received signal: %s. Initiating graceful shutdown.\n", sig) | |
ticker.Stop() | |
done <- true | |
return | |
} | |
} | |
}() | |
<-done | |
fmt.Println("🛑 Server process has been gracefully shut down.") | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment