mrflip-edamame 0.1.1
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/.document +8 -0
- data/.gitignore +31 -0
- data/LICENSE.textile +21 -0
- data/README.textile +178 -0
- data/Rakefile +75 -0
- data/VERSION +1 -0
- data/app/edamame_san/config.ru +4 -0
- data/app/edamame_san/config.yml +17 -0
- data/app/edamame_san/config/.gitignore +1 -0
- data/app/edamame_san/edamame_san.rb +71 -0
- data/app/edamame_san/public/favicon.ico +0 -0
- data/app/edamame_san/public/images/edamame_logo.icns +0 -0
- data/app/edamame_san/public/images/edamame_logo.ico +0 -0
- data/app/edamame_san/public/images/edamame_logo.png +0 -0
- data/app/edamame_san/public/images/edamame_logo_2.icns +0 -0
- data/app/edamame_san/public/javascripts/application.js +8 -0
- data/app/edamame_san/public/javascripts/jquery/jquery-ui.js +8694 -0
- data/app/edamame_san/public/javascripts/jquery/jquery.js +4376 -0
- data/app/edamame_san/public/stylesheets/application.css +32 -0
- data/app/edamame_san/public/stylesheets/layout.css +88 -0
- data/app/edamame_san/views/layout.haml +13 -0
- data/app/edamame_san/views/load.haml +37 -0
- data/app/edamame_san/views/root.haml +25 -0
- data/bin/edamame-ps +2 -0
- data/bin/empty_all.rb +15 -0
- data/bin/stats.rb +13 -0
- data/bin/sync.rb +15 -0
- data/bin/test_run.rb +14 -0
- data/edamame.gemspec +110 -0
- data/lib/edamame.rb +193 -0
- data/lib/edamame/job.rb +134 -0
- data/lib/edamame/queue.rb +6 -0
- data/lib/edamame/queue/beanstalk.rb +132 -0
- data/lib/edamame/rescheduled.rb +89 -0
- data/lib/edamame/scheduling.rb +69 -0
- data/lib/edamame/store.rb +8 -0
- data/lib/edamame/store/base.rb +62 -0
- data/lib/edamame/store/tyrant_store.rb +50 -0
- data/lib/methods.txt +94 -0
- data/spec/edamame_spec.rb +7 -0
- data/spec/spec_helper.rb +9 -0
- data/utils/god/README-god.textile +54 -0
- data/utils/god/beanstalkd_god.rb +34 -0
- data/utils/god/edamame.god +30 -0
- data/utils/god/god-etc-init-dot-d-example +40 -0
- data/utils/god/god_email.rb +45 -0
- data/utils/god/god_process.rb +140 -0
- data/utils/god/god_site_config.rb +4 -0
- data/utils/god/sinatra_god.rb +36 -0
- data/utils/god/tyrant_god.rb +67 -0
- data/utils/simulation/Add Percent Variation.vi +0 -0
- data/utils/simulation/Harmonic Average.vi +0 -0
- data/utils/simulation/Rescheduling Simulation.aliases +3 -0
- data/utils/simulation/Rescheduling Simulation.lvlps +3 -0
- data/utils/simulation/Rescheduling Simulation.lvproj +22 -0
- data/utils/simulation/Rescheduling.vi +0 -0
- data/utils/simulation/Weighted Average.vi +0 -0
- metadata +135 -0
@@ -0,0 +1,32 @@
|
|
1
|
+
/* ===========================================================================
|
2
|
+
Default styling for the upload bar
|
3
|
+
*/
|
4
|
+
|
5
|
+
body { margin: 0px ; }
|
6
|
+
|
7
|
+
.bar {
|
8
|
+
width: 300px;
|
9
|
+
}
|
10
|
+
#progress {
|
11
|
+
border: 1px solid #222;
|
12
|
+
display: block;
|
13
|
+
float: left;
|
14
|
+
margin-right: 0.25em;
|
15
|
+
}
|
16
|
+
#progressbar {
|
17
|
+
width: 0px;
|
18
|
+
height: 24px;
|
19
|
+
}
|
20
|
+
|
21
|
+
#progress { background: #eee; }
|
22
|
+
#progress #progressbar { background: #bbf; }
|
23
|
+
#progress.working { background: #eef; }
|
24
|
+
#progress.success #progressbar { background: #cfd; }
|
25
|
+
#progress.error { background: #fcc; }
|
26
|
+
#progress.error #progressbar { background: #fcd; }
|
27
|
+
|
28
|
+
iframe.yuploader {
|
29
|
+
border: 0px none white;
|
30
|
+
margin: 0px;
|
31
|
+
padding: 0px;
|
32
|
+
}
|
@@ -0,0 +1,88 @@
|
|
1
|
+
|
2
|
+
/*
|
3
|
+
Page layout
|
4
|
+
*/
|
5
|
+
|
6
|
+
body {
|
7
|
+
background-color: #4B7399;
|
8
|
+
font-family: Verdana, Helvetica, Arial;
|
9
|
+
font-size: 14px;
|
10
|
+
padding: 0;
|
11
|
+
margin: 0;
|
12
|
+
}
|
13
|
+
|
14
|
+
a img {
|
15
|
+
border: none;
|
16
|
+
}
|
17
|
+
|
18
|
+
a {
|
19
|
+
color: #0000FF;
|
20
|
+
}
|
21
|
+
|
22
|
+
.clear {
|
23
|
+
clear: both;
|
24
|
+
height: 0;
|
25
|
+
overflow: hidden;
|
26
|
+
}
|
27
|
+
|
28
|
+
#container {
|
29
|
+
width: 75%;
|
30
|
+
margin: 0 auto;
|
31
|
+
background-color: #FFF;
|
32
|
+
padding: 20px 40px;
|
33
|
+
border: solid 1px black;
|
34
|
+
margin-top: 20px;
|
35
|
+
}
|
36
|
+
|
37
|
+
#flash_notice, #flash_error {
|
38
|
+
padding: 5px 8px;
|
39
|
+
margin: 10px 0;
|
40
|
+
}
|
41
|
+
|
42
|
+
#flash_notice {
|
43
|
+
background-color: #CFC;
|
44
|
+
border: solid 1px #6C6;
|
45
|
+
}
|
46
|
+
|
47
|
+
#flash_error {
|
48
|
+
background-color: #FCC;
|
49
|
+
border: solid 1px #C66;
|
50
|
+
}
|
51
|
+
|
52
|
+
.fieldWithErrors {
|
53
|
+
display: inline;
|
54
|
+
}
|
55
|
+
|
56
|
+
#errorExplanation {
|
57
|
+
width: 400px;
|
58
|
+
border: 2px solid #CF0000;
|
59
|
+
padding: 0px;
|
60
|
+
padding-bottom: 12px;
|
61
|
+
margin-bottom: 20px;
|
62
|
+
background-color: #f0f0f0;
|
63
|
+
}
|
64
|
+
|
65
|
+
#errorExplanation h2 {
|
66
|
+
text-align: left;
|
67
|
+
font-weight: bold;
|
68
|
+
padding: 5px 5px 5px 15px;
|
69
|
+
font-size: 12px;
|
70
|
+
margin: 0;
|
71
|
+
background-color: #c00;
|
72
|
+
color: #fff;
|
73
|
+
}
|
74
|
+
|
75
|
+
#errorExplanation p {
|
76
|
+
color: #333;
|
77
|
+
margin-bottom: 0;
|
78
|
+
padding: 8px;
|
79
|
+
}
|
80
|
+
|
81
|
+
#errorExplanation ul {
|
82
|
+
margin: 2px 24px;
|
83
|
+
}
|
84
|
+
|
85
|
+
#errorExplanation ul li {
|
86
|
+
font-size: 12px;
|
87
|
+
list-style: disc;
|
88
|
+
}
|
@@ -0,0 +1,13 @@
|
|
1
|
+
!!! XML
|
2
|
+
!!! Strict
|
3
|
+
%html{ "xml:lang" => "en", :lang => "en", :xmlns => "http://www.w3.org/1999/xhtml" }
|
4
|
+
%head
|
5
|
+
%link{ :href => "/stylesheets/application.css", :rel => "stylesheet", :type => "text/css" }
|
6
|
+
%link{ :href => "/favicon.ico", :rel => "shortcut icon", :type => "image/x-icon" }
|
7
|
+
|
8
|
+
%body
|
9
|
+
#container
|
10
|
+
=yield
|
11
|
+
|
12
|
+
-# %script{ :type => "text/javascript", :src => "http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js" }
|
13
|
+
-# %script{ :type => "text/javascript", :src => "http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.1/jquery-ui.min.js" }
|
@@ -0,0 +1,37 @@
|
|
1
|
+
%style{ :type => 'text/css' }
|
2
|
+
@import url('/stylesheets/layout.css');
|
3
|
+
|
4
|
+
%p
|
5
|
+
|
6
|
+
Jobs in the edamame job store:
|
7
|
+
|
8
|
+
|
9
|
+
%table
|
10
|
+
%tr
|
11
|
+
%th query_term
|
12
|
+
%th priority
|
13
|
+
%th prev_items
|
14
|
+
%th prev_rate
|
15
|
+
%th prev_span_min
|
16
|
+
%th prev_span_max
|
17
|
+
- @dest_store.each_as(Edamame::Job) do |key, obj|
|
18
|
+
%tr
|
19
|
+
%td=h key.inspect
|
20
|
+
%td=h obj.inspect
|
21
|
+
%td=h obj.key
|
22
|
+
-# %td=h obj[:query_term]
|
23
|
+
-# %td=h obj[:priority]
|
24
|
+
-# %td=h obj[:prev_items]
|
25
|
+
-# %td=h obj[:prev_rate]
|
26
|
+
-# %td=h obj[:prev_span_min]
|
27
|
+
-# %td=h obj[:prev_span_max]
|
28
|
+
|
29
|
+
|
30
|
+
|
31
|
+
|
32
|
+
|
33
|
+
|
34
|
+
|
35
|
+
|
36
|
+
|
37
|
+
|
@@ -0,0 +1,25 @@
|
|
1
|
+
%style{ :type => 'text/css' }
|
2
|
+
@import url('/stylesheets/layout.css');
|
3
|
+
|
4
|
+
%p
|
5
|
+
|
6
|
+
Jobs in the edamame job store:
|
7
|
+
|
8
|
+
|
9
|
+
%table
|
10
|
+
%tr
|
11
|
+
%th query_term
|
12
|
+
%th priority
|
13
|
+
%th prev_items
|
14
|
+
%th prev_rate
|
15
|
+
%th prev_span_min
|
16
|
+
%th prev_span_max
|
17
|
+
- @store.each_as(Wuclan::Domains::Twitter::Scrape::TwitterSearchJob) do |key, obj|
|
18
|
+
%tr
|
19
|
+
-# %td=h key.inspect
|
20
|
+
%td=h obj[:query_term]
|
21
|
+
%td=h obj[:priority]
|
22
|
+
%td=h obj[:prev_items]
|
23
|
+
%td=h obj[:prev_rate]
|
24
|
+
%td=h obj[:prev_span_min]
|
25
|
+
%td=h obj[:prev_span_max]
|
data/bin/edamame-ps
ADDED
data/bin/empty_all.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
$: << File.dirname(__FILE__)+'/../../lib'
|
3
|
+
require 'rubygems'
|
4
|
+
require 'edamame'
|
5
|
+
require 'monkeyshines/monitor'
|
6
|
+
|
7
|
+
pq = Edamame::PersistentQueue.new(
|
8
|
+
:queue => { :type => 'BeanstalkQueue', :uris => ['localhost:11210'] },
|
9
|
+
:store => { :type => 'TyrantStore', :uri => ':11212' }
|
10
|
+
)
|
11
|
+
|
12
|
+
periodic_log = Monkeyshines::Monitor::PeriodicLogger.new(:iters => 1000, :time => 30)
|
13
|
+
pq.queue.empty_all do |job|
|
14
|
+
periodic_log.periodically{ [ job.tube, job.priority, job.delay, job.scheduling, job.obj['key'] ] }
|
15
|
+
end
|
data/bin/stats.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
$: << File.dirname(__FILE__)+'/../../lib'
|
3
|
+
require 'rubygems'
|
4
|
+
require 'edamame'
|
5
|
+
require 'monkeyshines/monitor'
|
6
|
+
|
7
|
+
pq = Edamame::PersistentQueue.new(
|
8
|
+
:tube => ARGV[0],
|
9
|
+
:queue => { :type => 'BeanstalkQueue', :uris => ['localhost:11210'] },
|
10
|
+
:store => { :type => 'TyrantStore', :uri => ':11212' }
|
11
|
+
)
|
12
|
+
|
13
|
+
p pq.stats
|
data/bin/sync.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
$: << File.dirname(__FILE__)+'/../../lib'
|
3
|
+
require 'rubygems'
|
4
|
+
require 'edamame'
|
5
|
+
require 'monkeyshines/monitor'
|
6
|
+
|
7
|
+
pq = Edamame::PersistentQueue.new(
|
8
|
+
:queue => { :type => 'BeanstalkQueue', :uris => ['localhost:11210'] },
|
9
|
+
:store => { :type => 'TyrantStore', :uri => ':11212' }
|
10
|
+
)
|
11
|
+
|
12
|
+
periodic_log = Monkeyshines::Monitor::PeriodicLogger.new(:iters => 1000, :time => 30)
|
13
|
+
pq.load do |job|
|
14
|
+
periodic_log.periodically{ [ pq.store.size, job, job.tube, job.priority, job.delay, job.obj['key'] ] }
|
15
|
+
end
|
data/bin/test_run.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
$: << File.dirname(__FILE__)+'/../../lib'
|
3
|
+
require 'rubygems'
|
4
|
+
require 'json'
|
5
|
+
require 'edamame'
|
6
|
+
|
7
|
+
broker = Edamame::Broker.new(
|
8
|
+
:queue => { :type => 'BeanstalkQueue', :uris => ['localhost:11210'] },
|
9
|
+
:store => { :type => 'TyrantStore', :uri => ':11212' }
|
10
|
+
)
|
11
|
+
|
12
|
+
broker.work do |job|
|
13
|
+
Monkeyshines.logger.info [job, job.scheduling, job.stats, job.obj].inspect
|
14
|
+
end
|
data/edamame.gemspec
ADDED
@@ -0,0 +1,110 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec`
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{edamame}
|
8
|
+
s.version = "0.1.1"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Philip (flip) Kromer"]
|
12
|
+
s.date = %q{2009-08-23}
|
13
|
+
s.description = %q{
|
14
|
+
|
15
|
+
Edamame combines the Beanstalk priority queue with a Tokyo Tyrant database and God monitoring to produce a persistent distributed priority job queue system.
|
16
|
+
|
17
|
+
Like beanstalk, it is fast, lightweight, distributed, priority queuing, reliable scheduling; it adds persistence, named jobs and job querying/enumeration.
|
18
|
+
|
19
|
+
}
|
20
|
+
s.email = %q{flip@infochimps.org}
|
21
|
+
s.executables = ["edamame-ps", "empty_all.rb", "stats.rb", "sync.rb", "test_run.rb"]
|
22
|
+
s.extra_rdoc_files = [
|
23
|
+
"LICENSE.textile",
|
24
|
+
"README.textile"
|
25
|
+
]
|
26
|
+
s.files = [
|
27
|
+
".document",
|
28
|
+
".gitignore",
|
29
|
+
"LICENSE.textile",
|
30
|
+
"README.textile",
|
31
|
+
"Rakefile",
|
32
|
+
"VERSION",
|
33
|
+
"app/edamame_san/config.ru",
|
34
|
+
"app/edamame_san/config.yml",
|
35
|
+
"app/edamame_san/config/.gitignore",
|
36
|
+
"app/edamame_san/edamame_san.rb",
|
37
|
+
"app/edamame_san/public/favicon.ico",
|
38
|
+
"app/edamame_san/public/images/edamame_logo.icns",
|
39
|
+
"app/edamame_san/public/images/edamame_logo.ico",
|
40
|
+
"app/edamame_san/public/images/edamame_logo.png",
|
41
|
+
"app/edamame_san/public/images/edamame_logo_2.icns",
|
42
|
+
"app/edamame_san/public/javascripts/application.js",
|
43
|
+
"app/edamame_san/public/javascripts/jquery/jquery-ui.js",
|
44
|
+
"app/edamame_san/public/javascripts/jquery/jquery.js",
|
45
|
+
"app/edamame_san/public/stylesheets/application.css",
|
46
|
+
"app/edamame_san/public/stylesheets/layout.css",
|
47
|
+
"app/edamame_san/views/layout.haml",
|
48
|
+
"app/edamame_san/views/load.haml",
|
49
|
+
"app/edamame_san/views/root.haml",
|
50
|
+
"bin/edamame-ps",
|
51
|
+
"bin/empty_all.rb",
|
52
|
+
"bin/stats.rb",
|
53
|
+
"bin/sync.rb",
|
54
|
+
"bin/test_run.rb",
|
55
|
+
"edamame.gemspec",
|
56
|
+
"lib/edamame.rb",
|
57
|
+
"lib/edamame/job.rb",
|
58
|
+
"lib/edamame/queue.rb",
|
59
|
+
"lib/edamame/queue/beanstalk.rb",
|
60
|
+
"lib/edamame/rescheduled.rb",
|
61
|
+
"lib/edamame/scheduling.rb",
|
62
|
+
"lib/edamame/store.rb",
|
63
|
+
"lib/edamame/store/base.rb",
|
64
|
+
"lib/edamame/store/tyrant_store.rb",
|
65
|
+
"lib/methods.txt",
|
66
|
+
"spec/edamame_spec.rb",
|
67
|
+
"spec/spec_helper.rb",
|
68
|
+
"utils/god/README-god.textile",
|
69
|
+
"utils/god/beanstalkd_god.rb",
|
70
|
+
"utils/god/edamame.god",
|
71
|
+
"utils/god/god-etc-init-dot-d-example",
|
72
|
+
"utils/god/god_email.rb",
|
73
|
+
"utils/god/god_process.rb",
|
74
|
+
"utils/god/god_site_config.rb",
|
75
|
+
"utils/god/sinatra_god.rb",
|
76
|
+
"utils/god/tyrant_god.rb",
|
77
|
+
"utils/simulation/Add Percent Variation.vi",
|
78
|
+
"utils/simulation/Harmonic Average.vi",
|
79
|
+
"utils/simulation/Rescheduling Simulation.aliases",
|
80
|
+
"utils/simulation/Rescheduling Simulation.lvlps",
|
81
|
+
"utils/simulation/Rescheduling Simulation.lvproj",
|
82
|
+
"utils/simulation/Rescheduling.vi",
|
83
|
+
"utils/simulation/Weighted Average.vi"
|
84
|
+
]
|
85
|
+
s.homepage = %q{http://github.com/mrflip/edamame}
|
86
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
87
|
+
s.require_paths = ["lib"]
|
88
|
+
s.rubygems_version = %q{1.3.5}
|
89
|
+
s.summary = %q{Beanstalk + Tokyo Tyrant = Edamame, a fast persistent distributed priority job queue.}
|
90
|
+
s.test_files = [
|
91
|
+
"spec/edamame_spec.rb",
|
92
|
+
"spec/spec_helper.rb"
|
93
|
+
]
|
94
|
+
|
95
|
+
if s.respond_to? :specification_version then
|
96
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
97
|
+
s.specification_version = 3
|
98
|
+
|
99
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
100
|
+
s.add_development_dependency(%q<rspec>, [">= 0"])
|
101
|
+
s.add_development_dependency(%q<yard>, [">= 0"])
|
102
|
+
else
|
103
|
+
s.add_dependency(%q<rspec>, [">= 0"])
|
104
|
+
s.add_dependency(%q<yard>, [">= 0"])
|
105
|
+
end
|
106
|
+
else
|
107
|
+
s.add_dependency(%q<rspec>, [">= 0"])
|
108
|
+
s.add_dependency(%q<yard>, [">= 0"])
|
109
|
+
end
|
110
|
+
end
|
data/lib/edamame.rb
ADDED
@@ -0,0 +1,193 @@
|
|
1
|
+
require 'wukong/extensions'
|
2
|
+
require 'monkeyshines/utils/logger'
|
3
|
+
require 'monkeyshines/utils/factory_module'
|
4
|
+
require 'beanstalk-client'
|
5
|
+
require 'edamame/scheduling'
|
6
|
+
require 'edamame/job'
|
7
|
+
require 'edamame/queue'
|
8
|
+
require 'edamame/store'
|
9
|
+
|
10
|
+
module Edamame
|
11
|
+
|
12
|
+
class PersistentQueue
|
13
|
+
DEFAULT_CONFIG = {
|
14
|
+
:queue => { :type => :beanstalk, :pool => ['localhost:11300'] }
|
15
|
+
}
|
16
|
+
attr_reader :tube, :store, :queue
|
17
|
+
def initialize options={}
|
18
|
+
@tube = options[:tube] || :default
|
19
|
+
@store = Edamame::Store.create options[:store]
|
20
|
+
@queue = Edamame::Queue.create options[:queue].merge(:default_tube => @tube)
|
21
|
+
end
|
22
|
+
|
23
|
+
#
|
24
|
+
# Add a new Job to the queue
|
25
|
+
#
|
26
|
+
def put job, *args
|
27
|
+
job.tube = self.tube if job.tube.blank?
|
28
|
+
self.tube = job.tube
|
29
|
+
return if store.include?(job.key)
|
30
|
+
store.save job
|
31
|
+
queue.put job, *args
|
32
|
+
end
|
33
|
+
|
34
|
+
def tube= _tube
|
35
|
+
return if @tube == _tube
|
36
|
+
puts "#{self.class} setting tube to #{_tube}, was #{@tube}"
|
37
|
+
queue.tube = @tube = _tube
|
38
|
+
end
|
39
|
+
|
40
|
+
# Alias for put(job)
|
41
|
+
def << job
|
42
|
+
put job
|
43
|
+
end
|
44
|
+
|
45
|
+
# Retrieve named record
|
46
|
+
def get key
|
47
|
+
Edamame::Job.from_hash store.get(key)
|
48
|
+
end
|
49
|
+
|
50
|
+
#
|
51
|
+
# Request a job fom the queue for processing
|
52
|
+
#
|
53
|
+
def reserve timeout=nil
|
54
|
+
job = queue.reserve(timeout)
|
55
|
+
end
|
56
|
+
|
57
|
+
#
|
58
|
+
# Remove the job from the queue.
|
59
|
+
#
|
60
|
+
def delete job
|
61
|
+
store.delete job.key
|
62
|
+
queue.delete job
|
63
|
+
end
|
64
|
+
|
65
|
+
#
|
66
|
+
# Returns the job to the queue, to be re-run later.
|
67
|
+
#
|
68
|
+
# release'ing a job acknowledges it was completed, successfully or not
|
69
|
+
#
|
70
|
+
def release job
|
71
|
+
job.update!
|
72
|
+
store.save job
|
73
|
+
queue.release job, job.priority, job.scheduling.delay
|
74
|
+
end
|
75
|
+
|
76
|
+
#
|
77
|
+
# Shelves the job.
|
78
|
+
#
|
79
|
+
def bury job
|
80
|
+
store.bury job
|
81
|
+
queue.bury job
|
82
|
+
end
|
83
|
+
|
84
|
+
#
|
85
|
+
# Returns each job as it appears in the queue.
|
86
|
+
#
|
87
|
+
# all jobs -- active, inactive, running, etc -- are returned,
|
88
|
+
# and in some arbitrary order.
|
89
|
+
#
|
90
|
+
def each *args, &block
|
91
|
+
store.each do |key, job_hsh|
|
92
|
+
yield Edamame::Job.from_hash(job_hsh)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
#
|
97
|
+
# Loads all jobs from the backing store into the queue.
|
98
|
+
#
|
99
|
+
def load &block
|
100
|
+
hoard do |job|
|
101
|
+
yield(job) if block
|
102
|
+
unless store.include?(job.key)
|
103
|
+
store.save job
|
104
|
+
end
|
105
|
+
end
|
106
|
+
unhoard &block
|
107
|
+
end
|
108
|
+
|
109
|
+
# Returns a hash of stats about the store and queue
|
110
|
+
def stats
|
111
|
+
{ :store_stats => store.stats,
|
112
|
+
:queue_stats => queue.stats,
|
113
|
+
:tube => self.tube }
|
114
|
+
end
|
115
|
+
|
116
|
+
protected
|
117
|
+
#
|
118
|
+
# Destructively strips the beanstalkd queue of all of its jobs.
|
119
|
+
#
|
120
|
+
# This is the only way (I know) to enumerate all of the jobs in the queue --
|
121
|
+
# certainly the only way that respects concurrency.
|
122
|
+
#
|
123
|
+
# You shouldn't use this in general; the point of the backing store is to
|
124
|
+
# allow exactly such queries and enumeration. See #each instead.
|
125
|
+
#
|
126
|
+
def hoard &block
|
127
|
+
queue.empty tube, &block
|
128
|
+
end
|
129
|
+
|
130
|
+
#
|
131
|
+
# Loads all jobs from the backing store into the queue.
|
132
|
+
#
|
133
|
+
# The queue must be emptied of all jobs before running this command:
|
134
|
+
# otherwise jobs will be duplicated.
|
135
|
+
#
|
136
|
+
def unhoard &block
|
137
|
+
store.each do |key, hsh|
|
138
|
+
job = Edamame::Job.from_hash hsh
|
139
|
+
self.tube = job.tube
|
140
|
+
yield(job) if block
|
141
|
+
queue.put job
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
#
|
146
|
+
#
|
147
|
+
#
|
148
|
+
def log line
|
149
|
+
Monkeyshines.logger.info line
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
class Broker < PersistentQueue
|
154
|
+
def reschedule job
|
155
|
+
delay = job.scheduling.delay
|
156
|
+
if delay
|
157
|
+
# log_job job, 'rescheduled', delay, (Time.now + delay).to_flat, job.scheduling.to_flat.join
|
158
|
+
release job
|
159
|
+
else
|
160
|
+
# log_job job, 'deleted'
|
161
|
+
delete job
|
162
|
+
end
|
163
|
+
end
|
164
|
+
def log_job job, *stuff
|
165
|
+
log [job.tube, job.priority, job.delay, job.obj['key'], *stuff].flatten.join("\t")
|
166
|
+
end
|
167
|
+
def work timeout=10, &block
|
168
|
+
loop do
|
169
|
+
job = reserve(timeout) or break
|
170
|
+
result = block.call(job)
|
171
|
+
job.update!
|
172
|
+
reschedule job
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
module Wuclan
|
179
|
+
module Domains
|
180
|
+
module Twitter
|
181
|
+
module Scrape
|
182
|
+
TwitterSearchJob = Struct.new(
|
183
|
+
:query_term,
|
184
|
+
:priority,
|
185
|
+
:prev_items,
|
186
|
+
:prev_rate,
|
187
|
+
:prev_span_min,
|
188
|
+
:prev_span_max
|
189
|
+
)
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|