stalker 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Rakefile +18 -0
- data/VERSION +1 -0
- data/bin/stalk +20 -0
- data/examples/enqueue.rb +8 -0
- data/examples/jobs.rb +20 -0
- data/lib/stalker.rb +109 -0
- metadata +77 -0
data/Rakefile
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'jeweler'
|
2
|
+
|
3
|
+
Jeweler::Tasks.new do |s|
|
4
|
+
s.name = "stalker"
|
5
|
+
s.summary = "A job queueing and background workers system using Beanstalkd."
|
6
|
+
s.description = "A job queueing and background workers system using Beanstalkd. Inspired by the Minion gem."
|
7
|
+
s.author = "Adam Wiggins"
|
8
|
+
s.email = "adam@heroku.com"
|
9
|
+
s.homepage = "http://github.com/adamwiggins/stalker"
|
10
|
+
s.executables = [ "stalk" ]
|
11
|
+
s.rubyforge_project = "stalker"
|
12
|
+
|
13
|
+
s.add_dependency 'beanstalk-client'
|
14
|
+
|
15
|
+
s.files = FileList["[A-Z]*", "{bin,lib}/**/*"]
|
16
|
+
end
|
17
|
+
|
18
|
+
Jeweler::GemcutterTasks.new
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.0
|
data/bin/stalk
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require File.dirname(__FILE__) + '/../lib/stalker'
|
4
|
+
|
5
|
+
usage = "stalk <jobs.rb> [<priority>[,<priority>,..]]"
|
6
|
+
file = ARGV.shift or abort usage
|
7
|
+
priorities = (ARGV.shift || 'all').split(',')
|
8
|
+
|
9
|
+
require file
|
10
|
+
|
11
|
+
jobs = Stalker.jobs(priorities)
|
12
|
+
puts "Working #{jobs.size} #{priorities.join(', ')} priority jobs: [ #{jobs.join(' ')} ]"
|
13
|
+
|
14
|
+
trap('INT') do
|
15
|
+
puts "\rExiting"
|
16
|
+
exit
|
17
|
+
end
|
18
|
+
|
19
|
+
Stalker.work priorities
|
20
|
+
|
data/examples/enqueue.rb
ADDED
data/examples/jobs.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
$LOAD_PATH.unshift '../lib'
|
2
|
+
require 'stalker'
|
3
|
+
|
4
|
+
include Stalker
|
5
|
+
|
6
|
+
priority :high do
|
7
|
+
job 'send.email' do |args|
|
8
|
+
puts "Sending email to args['email']"
|
9
|
+
end
|
10
|
+
|
11
|
+
job 'transform.image' do |args|
|
12
|
+
puts "Image transform"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
priority :low do
|
17
|
+
job 'cleanup.strays' do |args|
|
18
|
+
puts "Cleaning up"
|
19
|
+
end
|
20
|
+
end
|
data/lib/stalker.rb
ADDED
@@ -0,0 +1,109 @@
|
|
1
|
+
require 'beanstalk-client'
|
2
|
+
require 'json'
|
3
|
+
require 'uri'
|
4
|
+
|
5
|
+
module Stalker
|
6
|
+
extend self
|
7
|
+
|
8
|
+
def enqueue(job, args={})
|
9
|
+
beanstalk.use find_priority(job)
|
10
|
+
beanstalk.put [ job, args ].to_json
|
11
|
+
end
|
12
|
+
|
13
|
+
def priority(p, &block)
|
14
|
+
@@priority = p.to_s
|
15
|
+
block.call
|
16
|
+
@@priority = nil
|
17
|
+
end
|
18
|
+
|
19
|
+
def job(j, &block)
|
20
|
+
@@priority ||= 'default'
|
21
|
+
@@priorities ||= {}
|
22
|
+
@@priorities[j] = @@priority
|
23
|
+
|
24
|
+
@@handlers ||= {}
|
25
|
+
@@handlers[j] = block
|
26
|
+
end
|
27
|
+
|
28
|
+
def work(priorities=['all'])
|
29
|
+
if Array(priorities) == [ 'all' ]
|
30
|
+
priorities = @@priorities.values.uniq
|
31
|
+
end
|
32
|
+
|
33
|
+
beanstalk.list_tubes_watched.each { |tube| beanstalk.ignore(tube) }
|
34
|
+
priorities.each { |priority| beanstalk.watch(priority) }
|
35
|
+
|
36
|
+
loop do
|
37
|
+
work_one_job
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
class NoSuchJob < RuntimeError; end
|
42
|
+
|
43
|
+
def work_one_job
|
44
|
+
job = beanstalk.reserve
|
45
|
+
name, args = JSON.parse job.body
|
46
|
+
log_job(name, args)
|
47
|
+
handler = @@handlers[name]
|
48
|
+
raise(NoSuchJob, name) unless handler
|
49
|
+
handler.call(args)
|
50
|
+
job.delete
|
51
|
+
rescue => e
|
52
|
+
STDERR.puts exception_message(e)
|
53
|
+
job.bury
|
54
|
+
end
|
55
|
+
|
56
|
+
def log_job(name, args)
|
57
|
+
args_flat = args.inject("") do |accum, (key,value)|
|
58
|
+
accum += "#{key}=#{value} "
|
59
|
+
end
|
60
|
+
|
61
|
+
log sprintf("%-15s :: #{args_flat}", name)
|
62
|
+
end
|
63
|
+
|
64
|
+
def log(msg)
|
65
|
+
puts "[#{Time.now}] #{msg}"
|
66
|
+
end
|
67
|
+
|
68
|
+
def jobs(priorities=['all'])
|
69
|
+
jobs = []
|
70
|
+
@@priorities.each do |job, priority|
|
71
|
+
jobs << job if priorities == %w(all) or priorities.include? priority
|
72
|
+
end
|
73
|
+
jobs
|
74
|
+
end
|
75
|
+
|
76
|
+
class NoJobsDefined < RuntimeError; end
|
77
|
+
|
78
|
+
def find_priority(job)
|
79
|
+
raise NoJobsDefined unless defined?(@@priorities)
|
80
|
+
@@priorities[job] or raise(NoSuchJob, job)
|
81
|
+
end
|
82
|
+
|
83
|
+
def beanstalk
|
84
|
+
@@beanstalk ||= Beanstalk::Pool.new([ beanstalk_host_and_port ])
|
85
|
+
end
|
86
|
+
|
87
|
+
def beanstalk_url
|
88
|
+
ENV['BEANSTALK_URL'] || 'beanstalk://localhost:11300/'
|
89
|
+
end
|
90
|
+
|
91
|
+
class BadURL < RuntimeError; end
|
92
|
+
|
93
|
+
def beanstalk_host_and_port
|
94
|
+
uri = URI.parse(beanstalk_url)
|
95
|
+
raise(BadURL, beanstalk_url) if uri.scheme != 'beanstalk'
|
96
|
+
return "#{uri.host}:#{uri.port}"
|
97
|
+
end
|
98
|
+
|
99
|
+
def exception_message(e)
|
100
|
+
msg = [ "Exception #{e.class} -> #{e.message}" ]
|
101
|
+
|
102
|
+
base = File.expand_path(Dir.pwd) + '/'
|
103
|
+
e.backtrace.each do |t|
|
104
|
+
msg << " #{File.expand_path(t).gsub(/#{base}/, '')}"
|
105
|
+
end
|
106
|
+
|
107
|
+
msg.join("\n")
|
108
|
+
end
|
109
|
+
end
|
metadata
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: stalker
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 1
|
8
|
+
- 0
|
9
|
+
version: 0.1.0
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Adam Wiggins
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2010-03-26 00:00:00 -07:00
|
18
|
+
default_executable: stalk
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: beanstalk-client
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
segments:
|
28
|
+
- 0
|
29
|
+
version: "0"
|
30
|
+
type: :runtime
|
31
|
+
version_requirements: *id001
|
32
|
+
description: A job queueing and background workers system using Beanstalkd. Inspired by the Minion gem.
|
33
|
+
email: adam@heroku.com
|
34
|
+
executables:
|
35
|
+
- stalk
|
36
|
+
extensions: []
|
37
|
+
|
38
|
+
extra_rdoc_files: []
|
39
|
+
|
40
|
+
files:
|
41
|
+
- Rakefile
|
42
|
+
- VERSION
|
43
|
+
- bin/stalk
|
44
|
+
- lib/stalker.rb
|
45
|
+
has_rdoc: true
|
46
|
+
homepage: http://github.com/adamwiggins/stalker
|
47
|
+
licenses: []
|
48
|
+
|
49
|
+
post_install_message:
|
50
|
+
rdoc_options:
|
51
|
+
- --charset=UTF-8
|
52
|
+
require_paths:
|
53
|
+
- lib
|
54
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
55
|
+
requirements:
|
56
|
+
- - ">="
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
segments:
|
59
|
+
- 0
|
60
|
+
version: "0"
|
61
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
62
|
+
requirements:
|
63
|
+
- - ">="
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
segments:
|
66
|
+
- 0
|
67
|
+
version: "0"
|
68
|
+
requirements: []
|
69
|
+
|
70
|
+
rubyforge_project: stalker
|
71
|
+
rubygems_version: 1.3.6
|
72
|
+
signing_key:
|
73
|
+
specification_version: 3
|
74
|
+
summary: A job queueing and background workers system using Beanstalkd.
|
75
|
+
test_files:
|
76
|
+
- examples/enqueue.rb
|
77
|
+
- examples/jobs.rb
|