3
3
except :
4
4
import sys
5
5
sys .exit ("multiprocessing was not available" )
6
- import os , datetime , time , signal , sys
7
- from pyres import ResQ
8
- from pyres .exceptions import NoQueueError
6
+
7
+ import time , os , signal
9
8
from pyres .worker import Worker
9
+ from pyres import ResQ
10
+ from pyres .utils import OrderedDict
11
+ import datetime
12
+
10
13
class Minion (multiprocessing .Process , Worker ):
11
- def __init__ (self , conn , queues = [] ):
12
- self . conn = conn
14
+ def __init__ (self , queues , server , password ):
15
+ multiprocessing . Process . __init__ ( self , name = 'Minion' )
13
16
self .queues = queues
14
- super (Minion ,self ).__init__ (name = 'Minion' )
15
-
16
- def _check_message (self ):
17
- if self .conn .poll ():
18
- message = self .conn .recv ()
19
- self .process_message (message )
20
-
21
- def process_message (self , message ):
22
- pass
17
+ self .validate_queues ()
18
+ self ._shutdown = False
19
+ self .child = None
20
+ if isinstance (server ,basestring ):
21
+ self .resq = ResQ (server = server , password = password )
22
+ elif isinstance (server , ResQ ):
23
+ self .resq = server
24
+ else :
25
+ raise Exception ("Bad server argument" )
26
+ #Worker.__init__(self, queues=queues, server="localhost:6379", password=None)
27
+ #super(Minion,self).__init__(name='Minion')
23
28
24
29
def work (self , interval = 5 ):
25
30
self .startup ()
26
31
while True :
27
- self ._check_messages ()
28
32
if self ._shutdown :
29
33
print 'shutdown scheduled'
30
34
break
31
35
job = self .reserve ()
32
36
if job :
33
37
self .process (job )
34
38
else :
35
- if interval == 0 :
36
- break
37
39
time .sleep (interval )
38
40
self .unregister_worker ()
39
41
@@ -43,54 +45,141 @@ def run(self):
43
45
# job = self.q.get()
44
46
# print 'pid: %s is running %s ' % (self.pid,job)
45
47
46
- class Khan (Worker ):
48
+
49
+ class Khan (object ):
47
50
_command_map = {
48
- 'ADD' : '_add_minion ' ,
51
+ 'ADD' : 'add_minion ' ,
49
52
'REMOVE' : '_remove_minion' ,
50
53
'SHUTDOWN' : '_schedule_shutdown'
51
54
}
52
- _workers = {}
53
- def __init__ (self , pool_size = 5 , queue_list = [], server = 'localhost:6379' , password = None ):
55
+ _workers = OrderedDict ()
56
+ def __init__ (self , pool_size = 5 , queues = [], server = 'localhost:6379' , password = None ):
57
+ #super(Khan,self).__init__(queues=queues,server=server,password=password)
58
+ self ._shutdown = False
54
59
self .pool_size = pool_size
55
- self .resq = ResQ (server , password = password )
56
- self ._workers = list ()
60
+ self .queues = queues
61
+ self .server = server
62
+ self .password = password
63
+ self .pid = os .getpid ()
64
+ if isinstance (server ,basestring ):
65
+ self .resq = ResQ (server = server , password = password )
66
+ elif isinstance (server , ResQ ):
67
+ self .resq = server
68
+ else :
69
+ raise Exception ("Bad server argument" )
70
+ #self._workers = list()
71
+
72
+ def startup (self ):
73
+ self .register_signal_handlers ()
74
+ self .register_worker ()
75
+
76
+ def register_signal_handlers (self ):
77
+ signal .signal (signal .SIGTERM , self .schedule_shutdown )
78
+ signal .signal (signal .SIGINT , self .schedule_shutdown )
79
+ signal .signal (signal .SIGQUIT , self .schedule_shutdown )
80
+ signal .signal (signal .SIGUSR1 , self .kill_child )
81
+ signal .signal (signal .SIGUSR1 , self .add_child )
82
+
83
+ def _schedule_shutdown (self ):
84
+ self .schedule_shutdown (None , None )
85
+
86
+ def schedule_shutdown (self , signum , frame ):
87
+ print 'Shutdown scheduled'
88
+ self ._shutdown = True
89
+
90
+ def kill_child (self , signum , frame ):
91
+ self ._remove_minion ()
92
+
93
+ def add_child (self , signum , frame ):
94
+ self .add_minion ()
57
95
58
- def _check_command (self ):
96
+ def register_khan (self ):
97
+ self .resq .redis .sadd ('resque:khans' ,str (self ))
98
+ self .started = datetime .datetime .now ()
99
+
100
+ def _check_commands (self ):
59
101
if not self ._shutdown :
60
- command = self .resq .redis .pop ('resque:khan:%s' % self )
102
+ print 'Checking commands'
103
+ command_key = 'resque:khan:%s' % self
104
+ command = self .resq .redis .pop (command_key )
105
+ print 'COMMAND' , command
61
106
if command :
62
107
self .process_command (command )
63
- self ._check_command ()
108
+ self ._check_commands ()
64
109
65
110
def process_command (self , command ):
111
+ print 'Processing Command'
66
112
#available commands, shutdown, add 1, remove 1
67
113
command = self ._command_map .get (command , None )
68
114
if command :
69
115
fn = getattr (self , command )
70
116
if fn :
71
117
fn ()
72
118
73
- def _add_minion (self ):
74
- parent_conn , child_conn = multiprocessing . Pipe ()
75
- m = Minion ( child_conn , q )
119
+ def add_minion (self ):
120
+ print 'Adding minion'
121
+ m = self . _add_minion ( )
76
122
m .start ()
77
- self ._workers .append ((parent_conn , m ))
78
123
79
- def _remove_minion (self ):
80
- self ._workers
81
- def run ():
124
+ def _add_minion (self ):
125
+ print 'Adding mminion'
126
+ #parent_conn, child_conn = multiprocessing.Pipe()
127
+ m = Minion (self .queues , self .server , self .password )
128
+ #m.start()
129
+ self ._workers [m .pid ] = m
130
+ return m
131
+ #self._workers.append(m)
132
+
133
+ def _shutdown_minions (self ):
134
+ """
135
+ send the SIGNINT signal to each worker in the pool.
136
+ """
137
+ for minion in self ._workers .values ():
138
+ minion .terminate ()
139
+ minion .join ()
140
+
141
+ def _remove_minion (self , pid = None ):
142
+ #if pid:
143
+ # m = self._workers.pop(pid)
144
+ pid , m = self ._workers .popitem (False )
145
+ m .terminate ()
146
+ return m
147
+
148
+ def register_worker (self ):
149
+ self .resq .redis .sadd ('resque:khans' ,str (self ))
150
+ #self.resq._redis.add("worker:#{self}:started", Time.now.to_s)
151
+ self .started = datetime .datetime .now ()
152
+
153
+ def unregister_worker (self ):
154
+ print 'Unregistering'
155
+ self .resq .redis .srem ('resque:khans' ,str (self ))
156
+ self .started = None
157
+
158
+ def work (self , interval = 5 ):
82
159
self .startup ()
83
- q = multiprocessing .Queue ()
84
- for i in range (pool_size ):
85
- self ._add_minion ()
160
+ for i in range (self .pool_size ):
161
+ m = self ._add_minion ()
162
+ m .start ()
163
+
86
164
while True :
87
165
self ._check_commands ()
88
166
if self ._shutdown :
89
167
#send signals to each child
168
+ self ._shutdown_minions ()
90
169
break
91
- time .sleep (5 )
170
+ #get job
171
+ else :
172
+ time .sleep (interval )
92
173
self .unregister_worker ()
93
-
174
+
175
+ def __str__ (self ):
176
+ hostname = os .uname ()[1 ]
177
+ return '%s:%s' % (hostname , self .pid )
178
+
179
+ @classmethod
180
+ def run (cls , pool_size = 5 , queues = [], server = 'localhost:6379' ):
181
+ worker = cls (pool_size = pool_size , queues = queues , server = server )
182
+ worker .work ()
94
183
95
184
#if __name__ == "__main__":
96
185
# k = Khan()
@@ -104,6 +193,6 @@ def run():
104
193
if len (args ) < 1 :
105
194
parser .print_help ()
106
195
parser .error ("Please give the horde at least one queue." )
107
- khan = Khan ( queue_list = args , server = options .dest )
108
- khan .run ()
109
- #Worker.run(queues, options.server)
196
+ Khan . run ( pool_size = 2 , queues = args , server = options .server )
197
+ # khan.run()
198
+ #Worker.run(queues, options.server)
0 commit comments