@@ -6,13 +6,14 @@ import (
6
6
"os"
7
7
"time"
8
8
9
- "github.com/AliyunContainerService/image-syncer/pkg/utils/types"
9
+ "github.com/fatih/color"
10
+ "github.com/panjf2000/ants"
11
+ "github.com/sirupsen/logrus"
10
12
"gopkg.in/yaml.v2"
11
13
12
14
"github.com/AliyunContainerService/image-syncer/pkg/concurrent"
13
15
"github.com/AliyunContainerService/image-syncer/pkg/task"
14
- "github.com/fatih/color"
15
- "github.com/sirupsen/logrus"
16
+ "github.com/AliyunContainerService/image-syncer/pkg/utils/types"
16
17
)
17
18
18
19
// Client describes a synchronization client
@@ -97,7 +98,48 @@ func (c *Client) Run() error {
97
98
}
98
99
}
99
100
100
- c .openRoutinesHandleTaskAndWaitForFinish ()
101
+ routinePool , _ := ants .NewPoolWithFunc (c .routineNum , func (i interface {}) {
102
+ tTask , ok := i .(task.Task )
103
+ if ! ok {
104
+ c .logger .Errorf ("invalid task %v" , i )
105
+ return
106
+ }
107
+
108
+ nextTasks , message , err := tTask .Run ()
109
+ count , total := c .taskCounter .Increase ()
110
+ finishedNumString := color .New (color .FgGreen ).Sprintf ("%d" , count )
111
+ totalNumString := color .New (color .FgGreen ).Sprintf ("%d" , total )
112
+
113
+ if err != nil {
114
+ c .failedTaskList .PushBack (tTask )
115
+ c .failedTaskCounter .IncreaseTotal ()
116
+ c .logger .Errorf ("Failed to executed %v: %v. Now %v/%v tasks have been processed." , tTask .String (), err ,
117
+ finishedNumString , totalNumString )
118
+ } else {
119
+ if tTask .Type () == task .ManifestType {
120
+ // TODO: the ignored images will not be recorded in success images list
121
+ c .successImagesList .Add (tTask .GetSource ().String (), tTask .GetDestination ().String ())
122
+ }
123
+
124
+ if len (message ) != 0 {
125
+ c .logger .Infof ("Finish %v: %v. Now %v/%v tasks have been processed." , tTask .String (), message ,
126
+ finishedNumString , totalNumString )
127
+ } else {
128
+ c .logger .Infof ("Finish %v. Now %v/%v tasks have been processed." , tTask .String (),
129
+ finishedNumString , totalNumString )
130
+ }
131
+ }
132
+
133
+ for _ , t := range nextTasks {
134
+ c .taskList .PushFront (t )
135
+ c .taskCounter .IncreaseTotal ()
136
+ }
137
+ })
138
+ defer routinePool .Release ()
139
+
140
+ if err = c .handleTasks (routinePool ); err != nil {
141
+ return fmt .Errorf ("failed to handle tasks: %v" , err )
142
+ }
101
143
102
144
for times := 0 ; times < c .retries ; times ++ {
103
145
c .taskCounter , c .failedTaskCounter = c .failedTaskCounter , concurrent .NewCounter (0 , 0 )
@@ -110,7 +152,9 @@ func (c *Client) Run() error {
110
152
if c .taskList .Len () != 0 {
111
153
// retry to handle task
112
154
c .logger .Infof ("Start to retry tasks, please wait ..." )
113
- c .openRoutinesHandleTaskAndWaitForFinish ()
155
+ if err = c .handleTasks (routinePool ); err != nil {
156
+ return fmt .Errorf ("failed to handle tasks: %v" , err )
157
+ }
114
158
}
115
159
}
116
160
@@ -144,73 +188,21 @@ func (c *Client) Run() error {
144
188
return nil
145
189
}
146
190
147
- func (c * Client ) openRoutinesHandleTaskAndWaitForFinish () {
148
- broadcastChan := concurrent .NewBroadcastChan (c .routineNum )
149
- broadcastChan .Broadcast ()
150
-
151
- go func () {
152
- for {
153
- // if all the worker routines is hung and taskList is empty, stop everything
154
- <- broadcastChan .TotalHungChan ()
155
- if c .taskList .Len () == 0 {
156
- broadcastChan .Close ()
191
+ func (c * Client ) handleTasks (routinePool * ants.PoolWithFunc ) error {
192
+ for {
193
+ item := c .taskList .PopFront ()
194
+ // no more tasks need to handle
195
+ if item == nil {
196
+ if routinePool .Running () == 0 {
197
+ break
157
198
}
199
+ time .Sleep (1 * time .Second )
200
+ continue
158
201
}
159
- }()
160
-
161
- concurrent .CreateRoutinesAndWaitForFinish (c .routineNum , func () {
162
- for {
163
- closed := broadcastChan .Wait ()
164
-
165
- // run out of exist tasks
166
- for {
167
- item := c .taskList .PopFront ()
168
- // no more tasks need to handle
169
- if item == nil {
170
- break
171
- }
172
-
173
- tTask := item .(task.Task )
174
-
175
- c .logger .Infof ("Executing %v..." , tTask .String ())
176
- nextTasks , message , err := tTask .Run ()
177
-
178
- count , total := c .taskCounter .Increase ()
179
- finishedNumString := color .New (color .FgGreen ).Sprintf ("%d" , count )
180
- totalNumString := color .New (color .FgGreen ).Sprintf ("%d" , total )
181
-
182
- if err != nil {
183
- c .failedTaskList .PushBack (tTask )
184
- c .failedTaskCounter .IncreaseTotal ()
185
- c .logger .Errorf ("Failed to executed %v: %v. Now %v/%v tasks have been processed." , tTask .String (), err ,
186
- finishedNumString , totalNumString )
187
- } else {
188
- if tTask .Type () == task .ManifestType {
189
- // TODO: the ignored images will not be recorded in success images list
190
- c .successImagesList .Add (tTask .GetSource ().String (), tTask .GetDestination ().String ())
191
- }
192
-
193
- if len (message ) != 0 {
194
- c .logger .Infof ("Finish %v: %v. Now %v/%v tasks have been processed." , tTask .String (), message ,
195
- finishedNumString , totalNumString )
196
- } else {
197
- c .logger .Infof ("Finish %v. Now %v/%v tasks have been processed." , tTask .String (),
198
- finishedNumString , totalNumString )
199
- }
200
- }
201
-
202
- if nextTasks != nil {
203
- for _ , t := range nextTasks {
204
- c .taskList .PushFront (t )
205
- c .taskCounter .IncreaseTotal ()
206
- }
207
- broadcastChan .Broadcast ()
208
- }
209
- }
210
202
211
- if closed {
212
- return
213
- }
203
+ if err := routinePool .Invoke (item ); err != nil {
204
+ return fmt .Errorf ("failed to invoke routine: %v" , err )
214
205
}
215
- })
206
+ }
207
+ return nil
216
208
}
0 commit comments