@@ -13,6 +13,58 @@ import (
1313
1414const MainQueueName = "main"
1515
16+ // queueStorage is a thread-safe storage for task queues with basic Get/Set/Delete operations
17+ type queueStorage struct {
18+ mu sync.RWMutex
19+ queues map [string ]* TaskQueue
20+ }
21+
22+ func newQueueStorage () * queueStorage {
23+ return & queueStorage {
24+ queues : make (map [string ]* TaskQueue ),
25+ }
26+ }
27+
28+ // Get retrieves a queue by name, returns nil if not found
29+ func (qs * queueStorage ) Get (name string ) (* TaskQueue , bool ) {
30+ qs .mu .RLock ()
31+ defer qs .mu .RUnlock ()
32+ queue , exists := qs .queues [name ]
33+ return queue , exists
34+ }
35+
36+ // List retrieves all queues
37+ func (qs * queueStorage ) List () []* TaskQueue {
38+ qs .mu .RLock ()
39+ defer qs .mu .RUnlock ()
40+
41+ queues := make ([]* TaskQueue , 0 , len (qs .queues ))
42+ for _ , queue := range qs .queues {
43+ queues = append (queues , queue )
44+ }
45+
46+ return queues
47+ }
48+
49+ // Set stores a queue with the given name
50+ func (qs * queueStorage ) Set (name string , queue * TaskQueue ) {
51+ qs .mu .Lock ()
52+ defer qs .mu .Unlock ()
53+ qs .queues [name ] = queue
54+ }
55+
56+ // Delete removes a queue by name
57+ func (qs * queueStorage ) Delete (name string ) {
58+ qs .mu .Lock ()
59+ defer qs .mu .Unlock ()
60+ delete (qs .queues , name )
61+ }
62+
63+ // Len returns the number of tasks in a queue by name
64+ func (qs * queueStorage ) Len () int {
65+ return len (qs .queues )
66+ }
67+
1668// TaskQueueSet is a manager for a set of named queues
1769type TaskQueueSet struct {
1870 MainName string
@@ -23,12 +75,12 @@ type TaskQueueSet struct {
2375 cancel context.CancelFunc
2476
2577 m sync.RWMutex
26- Queues map [ string ] * TaskQueue
78+ Queues * queueStorage
2779}
2880
2981func NewTaskQueueSet () * TaskQueueSet {
3082 return & TaskQueueSet {
31- Queues : make ( map [ string ] * TaskQueue ),
83+ Queues : newQueueStorage ( ),
3284 MainName : MainQueueName ,
3385 }
3486}
@@ -61,18 +113,14 @@ func (tqs *TaskQueueSet) StartMain(ctx context.Context) {
61113}
62114
63115func (tqs * TaskQueueSet ) Start (ctx context.Context ) {
64- tqs .m .RLock ()
65- for _ , q := range tqs .Queues {
66- q .Start (ctx )
67- }
68-
69- tqs .m .RUnlock ()
116+ tqs .Iterate (ctx , func (ctx context.Context , queue * TaskQueue ) {
117+ queue .Start (ctx )
118+ })
70119}
71120
121+ // Add register a new queue for TaskQueueSet.
72122func (tqs * TaskQueueSet ) Add (queue * TaskQueue ) {
73- tqs .m .Lock ()
74- tqs .Queues [queue .Name ] = queue
75- tqs .m .Unlock ()
123+ tqs .Queues .Set (queue .Name , queue )
76124}
77125
78126func (tqs * TaskQueueSet ) NewNamedQueue (name string , handler func (ctx context.Context , t task.Task ) TaskResult , opts ... TaskQueueOption ) {
@@ -91,92 +139,88 @@ func (tqs *TaskQueueSet) NewNamedQueue(name string, handler func(ctx context.Con
91139 q .logger = log .NewLogger ().Named ("task_queue" )
92140 }
93141
94- tqs .m .Lock ()
95- tqs .Queues [name ] = q
96- tqs .m .Unlock ()
142+ tqs .Queues .Set (q .Name , q )
97143}
98144
99145func (tqs * TaskQueueSet ) GetByName (name string ) * TaskQueue {
100- tqs .m .RLock ()
101- defer tqs .m .RUnlock ()
102- ts , exists := tqs .Queues [name ]
103- if exists {
104- return ts
146+ q , ok := tqs .Queues .Get (name )
147+ if ! ok {
148+ return nil
105149 }
106- return nil
150+
151+ return q
107152}
108153
109154func (tqs * TaskQueueSet ) GetMain () * TaskQueue {
110155 return tqs .GetByName (tqs .MainName )
111156}
112157
113- /*
114- taskQueueSet.DoWithLock(func(tqs *TaskQueueSet){
115- tqs.GetMain().Pop()
116- })
117- */
118158func (tqs * TaskQueueSet ) DoWithLock (fn func (tqs * TaskQueueSet )) {
119159 tqs .m .Lock ()
120160 defer tqs .m .Unlock ()
161+
121162 if fn != nil {
122163 fn (tqs )
123164 }
124165}
125166
126167// Iterate run doFn for every task.
127- func (tqs * TaskQueueSet ) Iterate (doFn func (queue * TaskQueue )) {
168+ func (tqs * TaskQueueSet ) Iterate (ctx context. Context , doFn func (ctx context. Context , queue * TaskQueue )) {
128169 if doFn == nil {
129170 return
130171 }
131172
132173 tqs .m .RLock ()
133174 defer tqs .m .RUnlock ()
134- if len ( tqs .Queues ) == 0 {
175+ if tqs .Queues . Len ( ) == 0 {
135176 return
136177 }
137178
138179 main := tqs .GetMain ()
139180 if main != nil {
140- doFn (main )
181+ doFn (ctx , main )
141182 }
142183 // TODO sort names
143184
144- for _ , q := range tqs .Queues {
185+ for _ , q := range tqs .Queues . List () {
145186 if q .Name != tqs .MainName {
146- doFn (q )
187+ doFn (ctx , q )
147188 }
148189 }
149190}
150191
151192func (tqs * TaskQueueSet ) Remove (name string ) {
152- tqs .m .Lock ()
153- ts , exists := tqs .Queues [name ]
193+ ts , exists := tqs .Queues .Get (name )
154194 if exists {
155195 ts .Stop ()
156196 }
157197
158- delete (tqs .Queues , name )
159- tqs .m .Unlock ()
198+ tqs .Queues .Delete (name )
160199}
161200
162201func (tqs * TaskQueueSet ) WaitStopWithTimeout (timeout time.Duration ) {
163202 checkTick := time .NewTicker (time .Millisecond * 100 )
164203 defer checkTick .Stop ()
204+
165205 timeoutTick := time .NewTicker (timeout )
166206 defer timeoutTick .Stop ()
167207
168208 for {
169209 select {
170210 case <- checkTick .C :
171- stopped := true
172- tqs .m .RLock ()
173- for _ , q := range tqs .Queues {
174- if q .Status != "stop" {
175- stopped = false
176- break
211+ stopped := func () bool {
212+ tqs .m .RLock ()
213+ defer tqs .m .RUnlock ()
214+
215+ for _ , q := range tqs .Queues .List () {
216+ if q .GetStatusType () != QueueStatusStop {
217+ return false
218+ }
177219 }
178- }
179- tqs .m .RUnlock ()
220+
221+ return true
222+ }()
223+
180224 if stopped {
181225 return
182226 }
0 commit comments