package schedule import ( "context" "errors" "github.com/carlosframework/platform/internal/hostwrite" "github.com/carlosframework/platform/internal/registry" "os" ) type timerMutator interface { MutateTimer(context.Context, registry.Timer, string, bool) (*registry.Timer, error) } func mutateSelectedTimer(ctx context.Context, t registry.Timer, expected string, remove bool) (*registry.Timer, bool, error) { selected, ok := ctx.Value(timerWorkKey{}).(timerWork) if !ok || selected.work == nil { return nil, false, nil } m, ok := selected.work.(timerMutator) if !ok { return nil, false, nil } row, err := m.MutateTimer(ctx, t, expected, remove) return row, true, err } func deleteSelectedTimer(ctx context.Context, reg *registry.Registry, t registry.Timer) error { if _, handled, err := mutateSelectedTimer(ctx, t, t.Registration, true); handled { return err } return withTimerWork(ctx, func() error { return reg.DeleteTimerRegistration(t.Host, t.Name, t.Registration) }) } type ClaimTimers struct { TimerStore Writes hostwrite.Config Context context.Context } func (s ClaimTimers) UpsertTimer(t registry.Timer) error { work, err := s.Writes.Select(s.Context, t.Host, "timers") if err != nil { return err } return (SelectedTimers{Store: s.TimerStore, Work: work, Context: s.Context, Host: t.Host}).UpsertTimer(t) } func (s ClaimTimers) DeleteTimer(host, name string) error { work, err := s.Writes.Select(s.Context, host, "timers") if err != nil { return err } return (SelectedTimers{Store: s.TimerStore, Work: work, Context: s.Context, Host: host}).DeleteTimer(host, name) } func (s SelectedTimers) mutate(t registry.Timer, remove bool) (bool, error) { m, ok := s.Work.(timerMutator) if !ok { return false, nil } if s.Store == nil || s.Context == nil || t.Host != s.Host { return true, hostwrite.ErrUnavailable } var old *registry.Timer err := s.Work.With(s.Context, hostwrite.Identity{}, func() error { var err error old, err = s.Store.GetTimer(t.Host, t.Name) if errors.Is(err, os.ErrNotExist) { return nil } return err }) if err != nil { return true, err } expected := "" if old != nil { expected = old.Registration if old.Kind != t.Kind && !remove { return true, registry.ErrTimerKind } } if remove { if old == nil { return true, nil } t = *old } _, err = m.MutateTimer(s.Context, t, expected, remove) return true, err } func hasTimerMutator(ctx context.Context) bool { s, ok := ctx.Value(timerWorkKey{}).(timerWork) if !ok { return false } _, ok = s.work.(timerMutator) return ok }