github.com/iron-io/functions@v0.0.0-20180820112432-d59d7d1c40b2/api/models/mq.go (about)

     1  package models
     2  
     3  import "context"
     4  
     5  // Titan uses a Message Queue to impose a total ordering on jobs that it will
     6  // execute in order. Tasks are added to the queue via the Push() interface. The
     7  // MQ must support a reserve-delete 2 step dequeue to allow Titan to implement
     8  // timeouts and retries.
     9  //
    10  // The Reserve() operation must return a job based on this total ordering
    11  // (described below). At this point, the MQ backend must start a timeout on the
    12  // job. If Delete() is not called on the Task within the timeout, the Task should
    13  // be restored to the queue.
    14  //
    15  // Total ordering: The queue should maintain an ordering based on priority and
    16  // logical time.  Priorities are currently 0-2 and available in the Task's
    17  // priority field.  Tasks with higher priority always get pulled off the queue
    18  // first.  Within the same priority, jobs should be available in FIFO order.
    19  
    20  // When a job is required to be restored to the queue, it should maintain it's
    21  // approximate order in the queue. That is, for jobs [A, B, C], with A being
    22  // the head of the queue:
    23  // Reserve() leads to A being passed to a consumer, and timeout started.
    24  // Next Reserve() leads to B being dequeued. This consumer finishes running the
    25  // task, leading to Delete() being called. B is now permanently erased from the
    26  // queue.
    27  // A's timeout occurs before the job is finished. At this point the ordering
    28  // should be [A, C] and not [C, A].
    29  type MessageQueue interface {
    30  	// Push a Task onto the queue. If any error is returned, the Task SHOULD not be
    31  	// queued. Note that this does not completely avoid double queueing, that is
    32  	// OK, Titan will perform a check against the datastore after a dequeue.
    33  	//
    34  	// If the job's Delay value is > 0, the job should NOT be enqueued. The job
    35  	// should only be available in the queue after at least Delay seconds have
    36  	// elapsed. No ordering is required among multiple jobs queued with similar
    37  	// delays. That is, if jobs {A, C} are queued at t seconds, both with Delay
    38  	// = 5 seconds, and the same priority, then they may be available on the
    39  	// queue as [C, A] or [A, C].
    40  	Push(context.Context, *Task) (*Task, error)
    41  
    42  	// Remove a job from the front of the queue, reserve it for a timeout and
    43  	// return it. MQ implementations MUST NOT lose jobs in case of errors. That
    44  	// is, in case of reservation failure, it should be possible to retrieve the
    45  	// job on a future reservation.
    46  	Reserve(context.Context) (*Task, error)
    47  
    48  	// If a reservation is pending, consider it acknowledged and delete it. If
    49  	// the job does not have an outstanding reservation, error. If a job did not
    50  	// exist, succeed.
    51  	Delete(context.Context, *Task) error
    52  }
    53  
    54  type Enqueue func(context.Context, MessageQueue, *Task) (*Task, error)