1
+ try :
2
+ import multiprocessing
3
+ except :
4
+ import sys
5
+ sys .exit ("multiprocessing was not available" )
6
+
7
+ from pyres .exceptions import NoQueueError
8
+ from pyres .worker import Worker
9
+ class JuniorWorker (Worker ):
10
+ def work (self , interval = 5 ):
11
+ self .startup ()
12
+ while True :
13
+ if self ._shutdown :
14
+ break
15
+ job = self .reserve ()
16
+ if job :
17
+ print "got: %s" % job
18
+ self .child = os .fork ()
19
+ if self .child :
20
+ print 'Forked %s at %s' % (self .child , datetime .datetime .now ())
21
+ os .waitpid (self .child , 0 )
22
+ else :
23
+ print 'Processing %s since %s' % (job ._queue , datetime .datetime .now ())
24
+ self .process (job )
25
+ os ._exit (0 )
26
+ self .child = None
27
+ else :
28
+ break
29
+
30
+ self .unregister_worker ()
31
+
32
+
33
+ class Manager (object ):
34
+ def __init__ (self , queues , host , max_children = 10 ):
35
+ self .queues = queues
36
+ self ._host = host
37
+ self .max_children = max_children
38
+ self ._shutdown = False
39
+ self .children = []
40
+ self .resq = ResQ (host )
41
+ self .validate_queues ()
42
+ self .reports = {}
43
+
44
+ def __str__ (self ):
45
+ import os ;
46
+ hostname = os .uname ()[1 ]
47
+ pid = os .getpid ()
48
+ return 'Manager:%s:%s:%s' % (hostname , pid , ',' .join (self .queues ))
49
+
50
+ def validate_queues (self ):
51
+ if not self .queues :
52
+ raise NoQueueError ("Please give each worker at least one queue." )
53
+
54
+ def check_rising (self , queue , size ):
55
+ if queue in self .reports :
56
+ time = time .time ()
57
+ old_size = self .reports [queue ][0 ]
58
+ old_time = self .reports [queue ][1 ]
59
+ if time > old_time + 5 and size > old_size + 20 :
60
+ return True
61
+ else :
62
+ self .reports [queue ] = (size , time .time ())
63
+ return False
64
+
65
+ def work (self ):
66
+ self .startup ()
67
+ while True :
68
+ if self ._shutdown :
69
+ break
70
+ #check to see if stuff is still going
71
+ for queue in self .queues :
72
+ #check queue size
73
+ size = self .resq .size (queue )
74
+ if check_rising (queue ,size ):
75
+ if len (self .children ) < self .max_children :
76
+ self .start_child (queue )
77
+
78
+ def startup (self ):
79
+ self .register_manager ()
80
+ self .register_signals ()
81
+
82
+ def register_manager (self ):
83
+ self .resq .redis .sadd ('managers' ,str (self ))
84
+
85
+ def unregister_manager (self ):
86
+ self .resq .redis .srem ('managers' ,str (self ))
87
+
88
+ def register_signals (self ):
89
+ signal .signal (signal .SIGTERM , self .shutdown_all )
90
+ signal .signal (signal .SIGINT , self .shutdown_all )
91
+ signal .signal (signal .SIGQUIT , self .schedule_shutdown )
92
+ signal .signal (signal .SIGUSR1 , self .kill_children )
93
+
94
+ def shutdown_all (self , signum , frame ):
95
+ self .schedule_shutdown (signum , frame )
96
+ self .kill_children (signum , frame )
97
+
98
+ def schedule_shutdown (self , signum , frame ):
99
+ self ._shutdown = True
100
+
101
+ def kill_children (self ):
102
+ for child in self .children :
103
+ child .terminate ()
104
+
105
+ def start_child (self , queue ):
106
+ p = multiprocessing .Process (target = JuniorWorker .run , args = ([queue ], self ._host ))
107
+ self .children .append (p )
108
+ p .start ()
109
+ return True
110
+
111
+ @classmethod
112
+ def run (cls , queues = [], host = "localhost:6379" ):
113
+ manager = cls (queues , host )
114
+ manager .work ()
0 commit comments