@@ -7,6 +7,7 @@ package goes
77import (
88 "errors"
99 "sync"
10+ "time"
1011)
1112
1213var (
@@ -24,6 +25,7 @@ type Executor struct {
2425
2526 workers []* worker
2627 scheduler scheduler
28+ closeCh chan struct {}
2729 closed bool
2830
2931 wg sync.WaitGroup
@@ -50,11 +52,13 @@ func NewExecutor(workerNum int, opts ...Option) *Executor {
5052 conf : conf ,
5153 workers : workers ,
5254 scheduler : conf .newScheduler (),
55+ closeCh : make (chan struct {}, 1 ),
5356 closed : false ,
5457 lock : conf .newLocker (),
5558 }
5659
5760 executor .spawnWorker ()
61+ executor .runPurgeTask ()
5862 return executor
5963}
6064
@@ -66,6 +70,54 @@ func (e *Executor) spawnWorker() *worker {
6670 return worker
6771}
6872
73+ func (e * Executor ) purgeActive () bool {
74+ return e .conf .purgeInterval > 0 && e .conf .workerLifetime > 0
75+ }
76+
77+ func (e * Executor ) purgeWorkers () {
78+ e .lock .Lock ()
79+ defer e .lock .Unlock ()
80+
81+ now := e .conf .now ()
82+ oldWorkers := e .workers
83+ newWorkers := make ([]* worker , 0 , len (oldWorkers ))
84+ for _ , worker := range oldWorkers {
85+ if worker .WaitingTasks () <= 0 && now .Sub (worker .AcceptTime ()) >= e .conf .workerLifetime {
86+ worker .Done ()
87+ } else {
88+ newWorkers = append (newWorkers , worker )
89+ }
90+ }
91+
92+ e .workers = newWorkers
93+ e .scheduler .Set (e .workers )
94+
95+ // Avoid gc leaks.
96+ for i := range oldWorkers {
97+ oldWorkers [i ] = nil
98+ }
99+ }
100+
101+ func (e * Executor ) runPurgeTask () {
102+ if ! e .purgeActive () {
103+ return
104+ }
105+
106+ go func () {
107+ ticker := time .NewTicker (e .conf .purgeInterval )
108+ defer ticker .Stop ()
109+
110+ for {
111+ select {
112+ case <- ticker .C :
113+ e .purgeWorkers ()
114+ case <- e .closeCh :
115+ return
116+ }
117+ }
118+ }()
119+ }
120+
69121// AvailableWorkers returns the number of workers available.
70122func (e * Executor ) AvailableWorkers () int {
71123 e .lock .Lock ()
@@ -97,9 +149,11 @@ func (e *Executor) Submit(task Task) error {
97149 worker = e .spawnWorker ()
98150 }
99151
100- worker .SetAcceptTime (e .conf .now ())
101- e .lock .Unlock ()
152+ if e .purgeActive () {
153+ worker .SetAcceptTime (e .conf .now ())
154+ }
102155
156+ e .lock .Unlock ()
103157 worker .Accept (task )
104158 return nil
105159}
0 commit comments