code.gitea.io/gitea@v1.19.3/modules/queue/queue.go (about)

     1  // Copyright 2019 The Gitea Authors. All rights reserved.
     2  // SPDX-License-Identifier: MIT
     3  
     4  package queue
     5  
     6  import (
     7  	"context"
     8  	"fmt"
     9  	"time"
    10  )
    11  
    12  // ErrInvalidConfiguration is called when there is invalid configuration for a queue
    13  type ErrInvalidConfiguration struct {
    14  	cfg interface{}
    15  	err error
    16  }
    17  
    18  func (err ErrInvalidConfiguration) Error() string {
    19  	if err.err != nil {
    20  		return fmt.Sprintf("Invalid Configuration Argument: %v: Error: %v", err.cfg, err.err)
    21  	}
    22  	return fmt.Sprintf("Invalid Configuration Argument: %v", err.cfg)
    23  }
    24  
    25  // IsErrInvalidConfiguration checks if an error is an ErrInvalidConfiguration
    26  func IsErrInvalidConfiguration(err error) bool {
    27  	_, ok := err.(ErrInvalidConfiguration)
    28  	return ok
    29  }
    30  
    31  // Type is a type of Queue
    32  type Type string
    33  
    34  // Data defines an type of queuable data
    35  type Data interface{}
    36  
    37  // HandlerFunc is a function that takes a variable amount of data and processes it
    38  type HandlerFunc func(...Data) (unhandled []Data)
    39  
    40  // NewQueueFunc is a function that creates a queue
    41  type NewQueueFunc func(handler HandlerFunc, config, exemplar interface{}) (Queue, error)
    42  
    43  // Shutdownable represents a queue that can be shutdown
    44  type Shutdownable interface {
    45  	Shutdown()
    46  	Terminate()
    47  }
    48  
    49  // Named represents a queue with a name
    50  type Named interface {
    51  	Name() string
    52  }
    53  
    54  // Queue defines an interface of a queue-like item
    55  //
    56  // Queues will handle their own contents in the Run method
    57  type Queue interface {
    58  	Flushable
    59  	Run(atShutdown, atTerminate func(func()))
    60  	Push(Data) error
    61  }
    62  
    63  // PushBackable queues can be pushed back to
    64  type PushBackable interface {
    65  	// PushBack pushes data back to the top of the fifo
    66  	PushBack(Data) error
    67  }
    68  
    69  // DummyQueueType is the type for the dummy queue
    70  const DummyQueueType Type = "dummy"
    71  
    72  // NewDummyQueue creates a new DummyQueue
    73  func NewDummyQueue(handler HandlerFunc, opts, exemplar interface{}) (Queue, error) {
    74  	return &DummyQueue{}, nil
    75  }
    76  
    77  // DummyQueue represents an empty queue
    78  type DummyQueue struct{}
    79  
    80  // Run does nothing
    81  func (*DummyQueue) Run(_, _ func(func())) {}
    82  
    83  // Push fakes a push of data to the queue
    84  func (*DummyQueue) Push(Data) error {
    85  	return nil
    86  }
    87  
    88  // PushFunc fakes a push of data to the queue with a function. The function is never run.
    89  func (*DummyQueue) PushFunc(Data, func() error) error {
    90  	return nil
    91  }
    92  
    93  // Has always returns false as this queue never does anything
    94  func (*DummyQueue) Has(Data) (bool, error) {
    95  	return false, nil
    96  }
    97  
    98  // Flush always returns nil
    99  func (*DummyQueue) Flush(time.Duration) error {
   100  	return nil
   101  }
   102  
   103  // FlushWithContext always returns nil
   104  func (*DummyQueue) FlushWithContext(context.Context) error {
   105  	return nil
   106  }
   107  
   108  // IsEmpty asserts that the queue is empty
   109  func (*DummyQueue) IsEmpty() bool {
   110  	return true
   111  }
   112  
   113  // ImmediateType is the type to execute the function when push
   114  const ImmediateType Type = "immediate"
   115  
   116  // NewImmediate creates a new false queue to execute the function when push
   117  func NewImmediate(handler HandlerFunc, opts, exemplar interface{}) (Queue, error) {
   118  	return &Immediate{
   119  		handler: handler,
   120  	}, nil
   121  }
   122  
   123  // Immediate represents an direct execution queue
   124  type Immediate struct {
   125  	handler HandlerFunc
   126  }
   127  
   128  // Run does nothing
   129  func (*Immediate) Run(_, _ func(func())) {}
   130  
   131  // Push fakes a push of data to the queue
   132  func (q *Immediate) Push(data Data) error {
   133  	return q.PushFunc(data, nil)
   134  }
   135  
   136  // PushFunc fakes a push of data to the queue with a function. The function is never run.
   137  func (q *Immediate) PushFunc(data Data, f func() error) error {
   138  	if f != nil {
   139  		if err := f(); err != nil {
   140  			return err
   141  		}
   142  	}
   143  	q.handler(data)
   144  	return nil
   145  }
   146  
   147  // Has always returns false as this queue never does anything
   148  func (*Immediate) Has(Data) (bool, error) {
   149  	return false, nil
   150  }
   151  
   152  // Flush always returns nil
   153  func (*Immediate) Flush(time.Duration) error {
   154  	return nil
   155  }
   156  
   157  // FlushWithContext always returns nil
   158  func (*Immediate) FlushWithContext(context.Context) error {
   159  	return nil
   160  }
   161  
   162  // IsEmpty asserts that the queue is empty
   163  func (*Immediate) IsEmpty() bool {
   164  	return true
   165  }
   166  
   167  var queuesMap = map[Type]NewQueueFunc{
   168  	DummyQueueType: NewDummyQueue,
   169  	ImmediateType:  NewImmediate,
   170  }
   171  
   172  // RegisteredTypes provides the list of requested types of queues
   173  func RegisteredTypes() []Type {
   174  	types := make([]Type, len(queuesMap))
   175  	i := 0
   176  	for key := range queuesMap {
   177  		types[i] = key
   178  		i++
   179  	}
   180  	return types
   181  }
   182  
   183  // RegisteredTypesAsString provides the list of requested types of queues
   184  func RegisteredTypesAsString() []string {
   185  	types := make([]string, len(queuesMap))
   186  	i := 0
   187  	for key := range queuesMap {
   188  		types[i] = string(key)
   189  		i++
   190  	}
   191  	return types
   192  }
   193  
   194  // NewQueue takes a queue Type, HandlerFunc, some options and possibly an exemplar and returns a Queue or an error
   195  func NewQueue(queueType Type, handlerFunc HandlerFunc, opts, exemplar interface{}) (Queue, error) {
   196  	newFn, ok := queuesMap[queueType]
   197  	if !ok {
   198  		return nil, fmt.Errorf("unsupported queue type: %v", queueType)
   199  	}
   200  	return newFn(handlerFunc, opts, exemplar)
   201  }