Multiple implementations of the same back-end application. The aim is to provide quick, side-by-side comparisons of different technologies (languages, frameworks, libraries) while preserving consistent business logic across all implementations.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

104 lines
2.6 KiB

package scheduler
import (
"context"
"time"
"autostore/internal/application/commands"
"autostore/internal/application/interfaces"
)
type ExpiredItemsScheduler struct {
handleExpiredItemsCmd *commands.HandleExpiredItemsCommand
logger interfaces.ILogger
ticker *time.Ticker
done chan struct{}
}
func NewExpiredItemsScheduler(
handleExpiredItemsCmd *commands.HandleExpiredItemsCommand,
logger interfaces.ILogger,
) *ExpiredItemsScheduler {
return &ExpiredItemsScheduler{
handleExpiredItemsCmd: handleExpiredItemsCmd,
logger: logger,
done: make(chan struct{}),
}
}
func (s *ExpiredItemsScheduler) Start(ctx context.Context) error {
s.logger.Info(ctx, "Starting expired items scheduler")
// Process expired items immediately on startup
if err := s.processExpiredItems(ctx); err != nil {
s.logger.Error(ctx, "Failed to process expired items on startup", "error", err)
return err
}
// Calculate duration until next midnight
now := time.Now()
midnight := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location())
if now.After(midnight) {
midnight = midnight.Add(24 * time.Hour)
}
durationUntilMidnight := midnight.Sub(now)
// Start a timer for the first midnight
firstMidnightTimer := time.NewTimer(durationUntilMidnight)
go func() {
for {
select {
case <-firstMidnightTimer.C:
s.processExpiredItems(ctx)
// After first midnight, set up daily ticker
s.ticker = time.NewTicker(24 * time.Hour)
firstMidnightTimer.Stop()
for {
select {
case <-s.ticker.C:
s.processExpiredItems(ctx)
case <-s.done:
s.ticker.Stop()
return
case <-ctx.Done():
s.ticker.Stop()
return
}
}
case <-s.done:
firstMidnightTimer.Stop()
return
case <-ctx.Done():
firstMidnightTimer.Stop()
return
}
}
}()
s.logger.Info(ctx, "Expired items scheduler started", "next_run", midnight.Format(time.RFC3339))
return nil
}
func (s *ExpiredItemsScheduler) Stop() error {
s.logger.Info(context.Background(), "Stopping expired items scheduler")
close(s.done)
if s.ticker != nil {
s.ticker.Stop()
}
return nil
}
func (s *ExpiredItemsScheduler) processExpiredItems(ctx context.Context) error {
s.logger.Info(ctx, "Running scheduled expired items processing")
if err := s.handleExpiredItemsCmd.Execute(ctx); err != nil {
s.logger.Error(ctx, "Scheduled expired items processing failed", "error", err)
return err
}
s.logger.Info(ctx, "Scheduled expired items processing completed")
return nil
}