github.com/cozy/cozy-stack@v0.0.0-20240603063001-31110fa4cae1/model/job/trigger_at.go (about)

     1  package job
     2  
     3  import (
     4  	"time"
     5  )
     6  
     7  // maxPastTriggerTime is the maximum duration in the past for which the at
     8  // triggers are executed immediately instead of discarded.
     9  var maxPastTriggerTime = 24 * time.Hour
    10  
    11  // AtTrigger implements the @at trigger type. It schedules a job at a specified
    12  // time in the future.
    13  type AtTrigger struct {
    14  	*TriggerInfos
    15  	at   time.Time
    16  	done chan struct{}
    17  }
    18  
    19  // NewAtTrigger returns a new instance of AtTrigger given the specified
    20  // options.
    21  func NewAtTrigger(infos *TriggerInfos) (*AtTrigger, error) {
    22  	at, err := time.Parse(time.RFC3339, infos.Arguments)
    23  	if err != nil {
    24  		return nil, ErrMalformedTrigger
    25  	}
    26  	return &AtTrigger{
    27  		TriggerInfos: infos,
    28  		at:           at,
    29  		done:         make(chan struct{}),
    30  	}, nil
    31  }
    32  
    33  // NewInTrigger returns a new instance of AtTrigger given the specified
    34  // options as @in.
    35  func NewInTrigger(infos *TriggerInfos) (*AtTrigger, error) {
    36  	d, err := time.ParseDuration(infos.Arguments)
    37  	if err != nil {
    38  		return nil, ErrMalformedTrigger
    39  	}
    40  	at := time.Now().Add(d)
    41  	return &AtTrigger{
    42  		TriggerInfos: infos,
    43  		at:           at,
    44  		done:         make(chan struct{}),
    45  	}, nil
    46  }
    47  
    48  // Type implements the Type method of the Trigger interface.
    49  func (a *AtTrigger) Type() string {
    50  	return a.TriggerInfos.Type
    51  }
    52  
    53  // Schedule implements the Schedule method of the Trigger interface.
    54  func (a *AtTrigger) Schedule() <-chan *JobRequest {
    55  	ch := make(chan *JobRequest)
    56  	go func() {
    57  		duration := -time.Since(a.at)
    58  		if duration < 0 {
    59  			if duration > -maxPastTriggerTime {
    60  				ch <- a.TriggerInfos.JobRequest()
    61  			}
    62  			close(ch)
    63  			return
    64  		}
    65  		select {
    66  		case <-time.After(duration):
    67  			ch <- a.TriggerInfos.JobRequest()
    68  		case <-a.done:
    69  		}
    70  		close(ch)
    71  	}()
    72  	return ch
    73  }
    74  
    75  // Unschedule implements the Unschedule method of the Trigger interface.
    76  func (a *AtTrigger) Unschedule() {
    77  	close(a.done)
    78  }
    79  
    80  // Infos implements the Infos method of the Trigger interface.
    81  func (a *AtTrigger) Infos() *TriggerInfos {
    82  	return a.TriggerInfos
    83  }
    84  
    85  // CombineRequest implements the CombineRequest method of the Trigger interface.
    86  func (a *AtTrigger) CombineRequest() string {
    87  	return keepOriginalRequest
    88  }
    89  
    90  var _ Trigger = &AtTrigger{}