sweatshop 1.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +6 -0
- data/LICENSE +20 -0
- data/README.markdown +103 -0
- data/Rakefile +43 -0
- data/VERSION.yml +4 -0
- data/bin/sweatd +3 -0
- data/config/defaults.yml +8 -0
- data/config/sweatshop.yml +15 -0
- data/install.rb +20 -0
- data/lib/message_queue/base.rb +17 -0
- data/lib/message_queue/kestrel.rb +32 -0
- data/lib/message_queue/rabbit.rb +108 -0
- data/lib/sweat_shop.rb +179 -0
- data/lib/sweat_shop/daemoned.rb +405 -0
- data/lib/sweat_shop/metaid.rb +5 -0
- data/lib/sweat_shop/sweatd.rb +76 -0
- data/lib/sweat_shop/worker.rb +162 -0
- data/script/initd.sh +108 -0
- data/script/kestrel +93 -0
- data/script/kestrel.sh +93 -0
- data/script/sweatshop +17 -0
- data/test/hello_worker.rb +13 -0
- data/test/test_functional_worker.rb +72 -0
- data/test/test_helper.rb +4 -0
- data/test/test_sweatshop.rb +78 -0
- metadata +91 -0
@@ -0,0 +1,162 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/metaid'
|
2
|
+
|
3
|
+
module SweatShop
|
4
|
+
class Worker
|
5
|
+
def self.inherited(subclass)
|
6
|
+
self.workers << subclass
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.method_missing(method, *args, &block)
|
10
|
+
if method.to_s =~ /^async_(.*)/
|
11
|
+
method = $1
|
12
|
+
expected_args = instance.method(method).arity
|
13
|
+
if expected_args != args.size
|
14
|
+
raise ArgumentError.new("#{method} expects #{expected_args} arguments")
|
15
|
+
end
|
16
|
+
return instance.send(method, *args) unless config['enable']
|
17
|
+
|
18
|
+
uid = ::Digest::MD5.hexdigest("#{name}:#{method}:#{args}:#{Time.now.to_f}")
|
19
|
+
task = {:args => args, :method => method, :uid => uid, :queued_at => Time.now.to_i}
|
20
|
+
|
21
|
+
log("Putting #{uid} on #{queue_name}")
|
22
|
+
enqueue(task)
|
23
|
+
|
24
|
+
uid
|
25
|
+
elsif instance.respond_to?(method)
|
26
|
+
instance.send(method, *args)
|
27
|
+
else
|
28
|
+
super
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.instance
|
33
|
+
@instance ||= new
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.config
|
37
|
+
SweatShop.config
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.queue_name
|
41
|
+
@queue_name ||= self.to_s
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.delete_queue
|
45
|
+
queue.delete(queue_name)
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.queue_size
|
49
|
+
queue.queue_size(queue_name)
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.enqueue(task)
|
53
|
+
queue.enqueue(queue_name, task)
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.dequeue
|
57
|
+
queue.dequeue(queue_name)
|
58
|
+
end
|
59
|
+
|
60
|
+
def self.confirm
|
61
|
+
queue.confirm(queue_name)
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.subscribe
|
65
|
+
queue.subscribe(queue_name) do |task|
|
66
|
+
do_task(task)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def self.do_tasks
|
71
|
+
while task = dequeue
|
72
|
+
do_task(task)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def self.do_task(task)
|
77
|
+
begin
|
78
|
+
call_before_task(task)
|
79
|
+
|
80
|
+
queued_at = task[:queued_at] ? "(queued #{Time.at(task[:queued_at]).strftime('%Y/%m/%d %H:%M:%S')})" : ''
|
81
|
+
log("Dequeuing #{queue_name}::#{task[:method]} #{queued_at}")
|
82
|
+
task[:result] = instance.send(task[:method], *task[:args])
|
83
|
+
|
84
|
+
call_after_task(task)
|
85
|
+
confirm
|
86
|
+
rescue SystemExit
|
87
|
+
exit
|
88
|
+
rescue Exception => e
|
89
|
+
log("Caught Exception: #{e.message}, \n#{e.backtrace.join("\n")}")
|
90
|
+
call_exception_handler(e)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def self.queue
|
95
|
+
SweatShop.queue(queue_group.to_s)
|
96
|
+
end
|
97
|
+
|
98
|
+
def self.workers
|
99
|
+
SweatShop.workers
|
100
|
+
end
|
101
|
+
|
102
|
+
def self.config
|
103
|
+
SweatShop.config
|
104
|
+
end
|
105
|
+
|
106
|
+
def self.log(msg)
|
107
|
+
SweatShop.log(msg)
|
108
|
+
end
|
109
|
+
|
110
|
+
def self.call_before_task(task)
|
111
|
+
superclass.call_before_task(task) if superclass.respond_to?(:call_before_task)
|
112
|
+
before_task.call(task) if before_task
|
113
|
+
end
|
114
|
+
|
115
|
+
def self.call_after_task(task)
|
116
|
+
superclass.call_after_task(task) if superclass.respond_to?(:call_after_task)
|
117
|
+
after_task.call(task) if after_task
|
118
|
+
end
|
119
|
+
|
120
|
+
def self.call_exception_handler(exception)
|
121
|
+
superclass.call_exception_handler(exception) if superclass.respond_to?(:call_exception_handler)
|
122
|
+
on_exception.call(exception) if on_exception
|
123
|
+
end
|
124
|
+
|
125
|
+
def self.before_task(&block)
|
126
|
+
if block
|
127
|
+
@before_task = block
|
128
|
+
else
|
129
|
+
@before_task
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
def self.after_task(&block)
|
134
|
+
if block
|
135
|
+
@after_task = block
|
136
|
+
else
|
137
|
+
@after_task
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
def self.on_exception(&block)
|
142
|
+
if block
|
143
|
+
@on_exception = block
|
144
|
+
else
|
145
|
+
@on_exception
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
def self.stop
|
150
|
+
instance.stop
|
151
|
+
end
|
152
|
+
|
153
|
+
# called before we exit -- subclass can implement this method
|
154
|
+
def stop; end;
|
155
|
+
|
156
|
+
|
157
|
+
def self.queue_group(group=nil)
|
158
|
+
group ? meta_def(:_queue_group){ group } : _queue_group
|
159
|
+
end
|
160
|
+
queue_group :default
|
161
|
+
end
|
162
|
+
end
|
data/script/initd.sh
ADDED
@@ -0,0 +1,108 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
|
3
|
+
# chkconfig: 345 80 20
|
4
|
+
# description: Sweatshop starts the sweatd daemon
|
5
|
+
|
6
|
+
# Source function library.
|
7
|
+
if [ -f /etc/init.d/functions ] ; then
|
8
|
+
. /etc/init.d/functions
|
9
|
+
elif [ -f /etc/rc.d/init.d/functions ] ; then
|
10
|
+
. /etc/rc.d/init.d/functions
|
11
|
+
else
|
12
|
+
exit 0
|
13
|
+
fi
|
14
|
+
|
15
|
+
DAEMON=/opt/current/script/sweatshop
|
16
|
+
NAME=sweatshop
|
17
|
+
PID_DIR=/opt/current/log
|
18
|
+
LOG_FILE=$PID_DIR/sweatshop.log
|
19
|
+
INSTANCES=3
|
20
|
+
#QUEUE_GROUPS=test
|
21
|
+
export RAILS_ENV=dev
|
22
|
+
|
23
|
+
[ -f /etc/sysconfig/${NAME} ] && . /etc/sysconfig/${NAME}
|
24
|
+
|
25
|
+
|
26
|
+
# Gracefully exit if the package has been removed.
|
27
|
+
if [ ! -x $DAEMON ]; then
|
28
|
+
echo "$DAEMON does not exist"
|
29
|
+
exit 0
|
30
|
+
fi;
|
31
|
+
|
32
|
+
|
33
|
+
function start() {
|
34
|
+
num=$1
|
35
|
+
pidfile=$PID_DIR/$NAME.$num.pid
|
36
|
+
echo $"Starting ${NAME}:${num} "
|
37
|
+
if [ -z $QUEUE_GROUPS ]; then
|
38
|
+
$DAEMON -d start --log-file $LOG_FILE --pid-file $pidfile
|
39
|
+
else
|
40
|
+
$DAEMON -d start --log-file $LOG_FILE --pid-file $pidfile --groups $QUEUE_GROUPS
|
41
|
+
fi
|
42
|
+
RETVAL=$?
|
43
|
+
[ $RETVAL -eq 0 ] && success || failure
|
44
|
+
echo
|
45
|
+
return $RETVAL
|
46
|
+
}
|
47
|
+
|
48
|
+
function stop() {
|
49
|
+
num=$1
|
50
|
+
pidfile=$PID_DIR/$NAME.$num.pid
|
51
|
+
echo $"Stopping ${NAME}:${num}: "
|
52
|
+
$DAEMON -d stop --log-file $LOG_FILE --pid-file $pidfile
|
53
|
+
RETVAL=$?
|
54
|
+
[ $RETVAL -eq 0 ] && success || failure
|
55
|
+
echo
|
56
|
+
return $RETVAL
|
57
|
+
}
|
58
|
+
|
59
|
+
function reload() {
|
60
|
+
num=$1
|
61
|
+
pidfile=$PID_DIR/$NAME.$num.pid
|
62
|
+
echo $"Reloading ${NAME}:${num}: "
|
63
|
+
$DAEMON -d reload --log-file $LOG_FILE --pid-file $pidfile
|
64
|
+
RETVAL=$?
|
65
|
+
[ $RETVAL -eq 0 ] && success || failure
|
66
|
+
echo
|
67
|
+
return $RETVAL
|
68
|
+
}
|
69
|
+
|
70
|
+
function zap() {
|
71
|
+
num=$1
|
72
|
+
pidfile=$PID_DIR/$NAME.$num.pid
|
73
|
+
rm -f $pidfile
|
74
|
+
}
|
75
|
+
|
76
|
+
function doAll() {
|
77
|
+
func=$1
|
78
|
+
ii=0
|
79
|
+
while [ "$ii" -lt $INSTANCES ] ; do
|
80
|
+
eval "$func $(($ii))"
|
81
|
+
ii=$(($ii + 1))
|
82
|
+
done
|
83
|
+
}
|
84
|
+
|
85
|
+
case "$1" in
|
86
|
+
start)
|
87
|
+
doAll start
|
88
|
+
;;
|
89
|
+
stop)
|
90
|
+
doAll stop
|
91
|
+
;;
|
92
|
+
restart)
|
93
|
+
doAll stop
|
94
|
+
sleep 1
|
95
|
+
doAll start
|
96
|
+
;;
|
97
|
+
reload)
|
98
|
+
doAll reload
|
99
|
+
;;
|
100
|
+
zap)
|
101
|
+
doAll zap
|
102
|
+
;;
|
103
|
+
*)
|
104
|
+
echo "Usage: $0 {start|stop|restart|reload|zap}"
|
105
|
+
exit 1
|
106
|
+
esac
|
107
|
+
|
108
|
+
exit $RETVAL
|
data/script/kestrel
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
#
|
3
|
+
# chkconfig: 345 80 20
|
4
|
+
# description: kestrel is a light-weight queue written in scala
|
5
|
+
#
|
6
|
+
|
7
|
+
# Source function library.
|
8
|
+
if [ -f /etc/init.d/functions ] ; then
|
9
|
+
. /etc/init.d/functions
|
10
|
+
elif [ -f /etc/rc.d/init.d/functions ] ; then
|
11
|
+
. /etc/rc.d/init.d/functions
|
12
|
+
else
|
13
|
+
exit 0
|
14
|
+
fi
|
15
|
+
|
16
|
+
prog=kestrel
|
17
|
+
USER=daemon
|
18
|
+
KESTREL_HOME=/opt/kestrel
|
19
|
+
VERSION=1.0
|
20
|
+
JAR=$KESTREL_HOME/kestrel-$VERSION.jar
|
21
|
+
|
22
|
+
if [ ! -r $JAR ]; then
|
23
|
+
echo "FAIL"
|
24
|
+
echo "*** jar missing - not starting"
|
25
|
+
exit 1
|
26
|
+
fi
|
27
|
+
|
28
|
+
PIDFILE=/var/run/${prog}.pid
|
29
|
+
LOCKFILE=/var/lock/subsys/$prog
|
30
|
+
|
31
|
+
HEAP_OPTS="-Xmx2048m -Xms1024m -XX:NewSize=256m"
|
32
|
+
JAVA_OPTS="-server -verbosegc -XX:+PrintGCDetails -XX:+UseConcMarkSweepGC -XX:+UseParNewGC $HEAP_OPTS"
|
33
|
+
|
34
|
+
start() {
|
35
|
+
echo -n $"Starting $prog: "
|
36
|
+
java $JAVA_OPTS -jar $JAR > /var/log/$prog-startup.log 2>&1 &
|
37
|
+
RETVAL=$?
|
38
|
+
if [ $RETVAL -eq 0 ]; then
|
39
|
+
echo $! > $PIDFILE
|
40
|
+
success $"$prog startup"
|
41
|
+
touch $LOCKFILE
|
42
|
+
else
|
43
|
+
failure $"$prog startup"
|
44
|
+
fi
|
45
|
+
echo
|
46
|
+
return $RETVAL;
|
47
|
+
}
|
48
|
+
|
49
|
+
stop() {
|
50
|
+
echo -n $"Stopping $prog: "
|
51
|
+
if [ -f $PIDFILE ]; then
|
52
|
+
killproc -p $PIDFILE $prog
|
53
|
+
RETVAL=$?
|
54
|
+
if [ $RETVAL -eq 0 ]; then
|
55
|
+
rm -f $LOCKFILE
|
56
|
+
rm -f $PIDFILE
|
57
|
+
fi;
|
58
|
+
else
|
59
|
+
RETVAL=1
|
60
|
+
failure;
|
61
|
+
fi
|
62
|
+
echo
|
63
|
+
return $RETVAL;
|
64
|
+
}
|
65
|
+
|
66
|
+
|
67
|
+
case "$1" in
|
68
|
+
start)
|
69
|
+
start
|
70
|
+
;;
|
71
|
+
|
72
|
+
stop)
|
73
|
+
stop
|
74
|
+
;;
|
75
|
+
|
76
|
+
restart)
|
77
|
+
stop
|
78
|
+
start
|
79
|
+
;;
|
80
|
+
|
81
|
+
condrestart)
|
82
|
+
if [ -f $LOCKFILE ]; then
|
83
|
+
stop
|
84
|
+
start
|
85
|
+
fi
|
86
|
+
;;
|
87
|
+
|
88
|
+
*)
|
89
|
+
echo $"Usage: $0 {start|stop|restart|condrestart}"
|
90
|
+
exit 1
|
91
|
+
esac
|
92
|
+
|
93
|
+
exit $RETVAL
|
data/script/kestrel.sh
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
#
|
3
|
+
# chkconfig: 345 80 20
|
4
|
+
# description: kestrel is a light-weight queue written in scala
|
5
|
+
#
|
6
|
+
|
7
|
+
# Source function library.
|
8
|
+
if [ -f /etc/init.d/functions ] ; then
|
9
|
+
. /etc/init.d/functions
|
10
|
+
elif [ -f /etc/rc.d/init.d/functions ] ; then
|
11
|
+
. /etc/rc.d/init.d/functions
|
12
|
+
else
|
13
|
+
exit 0
|
14
|
+
fi
|
15
|
+
|
16
|
+
prog=kestrel
|
17
|
+
USER=daemon
|
18
|
+
KESTREL_HOME=/opt/kestrel
|
19
|
+
VERSION=1.0
|
20
|
+
JAR=$KESTREL_HOME/kestrel-$VERSION.jar
|
21
|
+
|
22
|
+
if [ ! -r $JAR ]; then
|
23
|
+
echo "FAIL"
|
24
|
+
echo "*** jar missing - not starting"
|
25
|
+
exit 1
|
26
|
+
fi
|
27
|
+
|
28
|
+
PIDFILE=/var/run/${prog}.pid
|
29
|
+
LOCKFILE=/var/lock/subsys/$prog
|
30
|
+
|
31
|
+
HEAP_OPTS="-Xmx2048m -Xms1024m -XX:NewSize=256m"
|
32
|
+
JAVA_OPTS="-server -verbosegc -XX:+PrintGCDetails -XX:+UseConcMarkSweepGC -XX:+UseParNewGC $HEAP_OPTS"
|
33
|
+
|
34
|
+
start() {
|
35
|
+
echo -n $"Starting $prog: "
|
36
|
+
java $JAVA_OPTS -jar $JAR > /var/log/$prog-startup.log 2>&1 &
|
37
|
+
RETVAL=$?
|
38
|
+
if [ $RETVAL -eq 0 ]; then
|
39
|
+
echo $! > $PIDFILE
|
40
|
+
success $"$prog startup"
|
41
|
+
touch $LOCKFILE
|
42
|
+
else
|
43
|
+
failure $"$prog startup"
|
44
|
+
fi
|
45
|
+
echo
|
46
|
+
return $RETVAL;
|
47
|
+
}
|
48
|
+
|
49
|
+
stop() {
|
50
|
+
echo -n $"Stopping $prog: "
|
51
|
+
if [ -f $PIDFILE ]; then
|
52
|
+
killproc -p $PIDFILE $prog
|
53
|
+
RETVAL=$?
|
54
|
+
if [ $RETVAL -eq 0 ]; then
|
55
|
+
rm -f $LOCKFILE
|
56
|
+
rm -f $PIDFILE
|
57
|
+
fi;
|
58
|
+
else
|
59
|
+
RETVAL=1
|
60
|
+
failure;
|
61
|
+
fi
|
62
|
+
echo
|
63
|
+
return $RETVAL;
|
64
|
+
}
|
65
|
+
|
66
|
+
|
67
|
+
case "$1" in
|
68
|
+
start)
|
69
|
+
start
|
70
|
+
;;
|
71
|
+
|
72
|
+
stop)
|
73
|
+
stop
|
74
|
+
;;
|
75
|
+
|
76
|
+
restart)
|
77
|
+
stop
|
78
|
+
start
|
79
|
+
;;
|
80
|
+
|
81
|
+
condrestart)
|
82
|
+
if [ -f $LOCKFILE ]; then
|
83
|
+
stop
|
84
|
+
start
|
85
|
+
fi
|
86
|
+
;;
|
87
|
+
|
88
|
+
*)
|
89
|
+
echo $"Usage: $0 {start|stop|restart|condrestart}"
|
90
|
+
exit 1
|
91
|
+
esac
|
92
|
+
|
93
|
+
exit $RETVAL
|