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 }