backgroundrb-rails3 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/.autotest +17 -0
- data/ChangeLog +50 -0
- data/Gemfile +11 -0
- data/LICENSE +4 -0
- data/MIT-LICENSE +20 -0
- data/README +22 -0
- data/Rakefile +128 -0
- data/TODO.org +5 -0
- data/app/controller/backgroundrb_status_controller.rb +6 -0
- data/backgroundrb-rails3.gemspec +219 -0
- data/config/backgroundrb.yml +11 -0
- data/doc/Rakefile +5 -0
- data/doc/config.yaml +2 -0
- data/doc/content/advanced/advanced.txt +76 -0
- data/doc/content/advanced/advanced.yaml +4 -0
- data/doc/content/bugs/bugs.txt +20 -0
- data/doc/content/bugs/bugs.yaml +5 -0
- data/doc/content/community/community.txt +36 -0
- data/doc/content/community/community.yaml +5 -0
- data/doc/content/content.txt +168 -0
- data/doc/content/content.yaml +5 -0
- data/doc/content/faq/faq.txt +41 -0
- data/doc/content/faq/faq.yaml +5 -0
- data/doc/content/rails/rails.txt +182 -0
- data/doc/content/rails/rails.yaml +5 -0
- data/doc/content/scheduling/scheduling.txt +166 -0
- data/doc/content/scheduling/scheduling.yaml +5 -0
- data/doc/content/workers/workers.txt +178 -0
- data/doc/content/workers/workers.yaml +5 -0
- data/doc/layouts/default/default.erb +56 -0
- data/doc/layouts/default/default.yaml +4 -0
- data/doc/lib/default.rb +7 -0
- data/doc/output/Assets/BG-Ad-Top.png +0 -0
- data/doc/output/Assets/BG-Body.png +0 -0
- data/doc/output/Assets/BG-Feed.png +0 -0
- data/doc/output/Assets/BG-Menu-Hover.png +0 -0
- data/doc/output/Assets/BG-Menu.png +0 -0
- data/doc/output/Assets/BG-Sidebar-Bottom.png +0 -0
- data/doc/output/Assets/Button-Feed.png +0 -0
- data/doc/output/images/bg-ad-top.png +0 -0
- data/doc/output/images/bg-body.png +0 -0
- data/doc/output/images/bg-feed.gif +0 -0
- data/doc/output/images/bg-footer.jpg +0 -0
- data/doc/output/images/bg-header.jpg +0 -0
- data/doc/output/images/bg-menu-hover.png +0 -0
- data/doc/output/images/bg-menu.png +0 -0
- data/doc/output/images/bg-sidebar-bottom.gif +0 -0
- data/doc/output/images/button-feed.png +0 -0
- data/doc/output/images/icon-comment.png +0 -0
- data/doc/output/images/more_icon.gif +0 -0
- data/doc/output/style.css +299 -0
- data/doc/page_defaults.yaml +13 -0
- data/doc/tasks/default.rake +3 -0
- data/doc/templates/default/default.txt +1 -0
- data/doc/templates/default/default.yaml +4 -0
- data/examples/backgroundrb.yml +25 -0
- data/examples/foo_controller.rb +48 -0
- data/examples/god_worker.rb +7 -0
- data/examples/worker_tests/god_worker_test.rb +8 -0
- data/examples/workers/error_worker.rb +17 -0
- data/examples/workers/foo_worker.rb +38 -0
- data/examples/workers/god_worker.rb +7 -0
- data/examples/workers/model_worker.rb +13 -0
- data/examples/workers/renewal_worker.rb +11 -0
- data/examples/workers/rss_worker.rb +26 -0
- data/examples/workers/server_worker.rb +31 -0
- data/examples/workers/world_worker.rb +12 -0
- data/examples/workers/xmpp_worker.rb +7 -0
- data/init.rb +7 -0
- data/install.rb +1 -0
- data/know_issues.org +5 -0
- data/lib/backgroundrb.rb +1 -0
- data/lib/backgroundrb/bdrb_client_helper.rb +8 -0
- data/lib/backgroundrb/bdrb_cluster_connection.rb +156 -0
- data/lib/backgroundrb/bdrb_config.rb +43 -0
- data/lib/backgroundrb/bdrb_conn_error.rb +29 -0
- data/lib/backgroundrb/bdrb_connection.rb +179 -0
- data/lib/backgroundrb/bdrb_job_queue.rb +79 -0
- data/lib/backgroundrb/bdrb_result.rb +19 -0
- data/lib/backgroundrb/bdrb_start_stop.rb +146 -0
- data/lib/backgroundrb/rails_worker_proxy.rb +181 -0
- data/lib/backgroundrb/railtie.rb +48 -0
- data/lib/generators/backgroundrb/bdrb_migration/USAGE +12 -0
- data/lib/generators/backgroundrb/bdrb_migration/bdrb_migration_generator.rb +15 -0
- data/lib/generators/backgroundrb/bdrb_migration/templates/migration.rb +27 -0
- data/lib/generators/backgroundrb/worker/USAGE +16 -0
- data/lib/generators/backgroundrb/worker/templates/unit_test.rb +12 -0
- data/lib/generators/backgroundrb/worker/templates/worker.rb +7 -0
- data/lib/generators/backgroundrb/worker/worker_generator.rb +14 -0
- data/lib/tasks/backgroundrb_tasks.rake +103 -0
- data/release_notes.org +48 -0
- data/release_points.org +46 -0
- data/script/backgroundrb +52 -0
- data/script/bdrb_test_helper.rb +99 -0
- data/script/load_worker_env.rb +31 -0
- data/script/monitrc +25 -0
- data/server/backgroundrb_server.rb +12 -0
- data/server/lib/bdrb_result_storage.rb +62 -0
- data/server/lib/bdrb_server_helper.rb +24 -0
- data/server/lib/bdrb_thread_pool.rb +127 -0
- data/server/lib/cron_trigger.rb +197 -0
- data/server/lib/invalid_dump_error.rb +4 -0
- data/server/lib/log_worker.rb +25 -0
- data/server/lib/master_proxy.rb +140 -0
- data/server/lib/master_worker.rb +187 -0
- data/server/lib/meta_worker.rb +432 -0
- data/server/lib/trigger.rb +34 -0
- data/test/bdrb_client_test_helper.rb +5 -0
- data/test/bdrb_test_helper.rb +35 -0
- data/test/client/backgroundrb.yml +17 -0
- data/test/client/test_bdrb_client_helper.rb +13 -0
- data/test/client/test_bdrb_cluster_connection.rb +162 -0
- data/test/client/test_bdrb_config.rb +20 -0
- data/test/client/test_bdrb_connection.rb +29 -0
- data/test/client/test_bdrb_job_queue.rb +63 -0
- data/test/client/test_worker_proxy.rb +130 -0
- data/test/server/test_cron_trigger.rb +281 -0
- data/test/server/test_master_proxy.rb +54 -0
- data/test/server/test_master_worker.rb +157 -0
- data/test/server/test_meta_worker.rb +281 -0
- data/test/server/test_result_storage.rb +14 -0
- data/test/socket_mocker.rb +34 -0
- data/test/workers/bar_worker.rb +10 -0
- data/test/workers/foo_worker.rb +10 -0
- data/uninstall.rb +1 -0
- metadata +345 -0
data/doc/Rakefile
ADDED
data/doc/config.yaml
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
<div id="content">
|
|
2
|
+
|
|
3
|
+
%(entry-title)<a name="advanced"> Advanced Stuff </a>%
|
|
4
|
+
|
|
5
|
+
Each worker comes with an Event loop of its own and can potentially do lots of fancy stuff. Two noteworthy methods are:
|
|
6
|
+
|
|
7
|
+
<pre class="multiline">connect(ip,port,Handler)
|
|
8
|
+
start_server(ip,port,Handler) </pre>
|
|
9
|
+
|
|
10
|
+
If you are familiar with the EventMachine or Twisted style of network programming, the above methods allow you to
|
|
11
|
+
start tcp servers inside your workers or let you connect to external tcp servers. For Each accepted client or
|
|
12
|
+
connected socket, an instance of Handler class would be created and integrated with main event loop.
|
|
13
|
+
This can be used for worker to worker communication between backgroundrb servers running on two machines.
|
|
14
|
+
|
|
15
|
+
p(sub-title). @BackgrounDRb::MetaWorker#connect@ :
|
|
16
|
+
|
|
17
|
+
@connect@ lets you connect to an external TCP Server and integrates the connection within reactor loop
|
|
18
|
+
of worker. For example:
|
|
19
|
+
|
|
20
|
+
<pre class="multiline">class TimeClient
|
|
21
|
+
def receive_data(p_data)
|
|
22
|
+
worker.get_external_data(p_data)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def post_init
|
|
26
|
+
p "***************** : connection completed"
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
class FooWorker < BackgrounDRb::MetaWorker
|
|
31
|
+
set_worker_name :foo_worker
|
|
32
|
+
def create(args = nil)
|
|
33
|
+
external_connection = nil
|
|
34
|
+
connect("localhost",11009,TimeClient) { |conn| external_connection = conn }
|
|
35
|
+
end
|
|
36
|
+
def get_external_data(p_data)
|
|
37
|
+
puts "And external data is : #{p_data}"
|
|
38
|
+
end
|
|
39
|
+
end </pre>
|
|
40
|
+
|
|
41
|
+
p(sub-title). @BackgrounDRb::MetaWorker#start_server@ :
|
|
42
|
+
|
|
43
|
+
Above method allows you to start a tcp server from your worker, all the accepted connections are integrated with event loop of worker.
|
|
44
|
+
|
|
45
|
+
<pre class="multiline"> class TimeServer
|
|
46
|
+
|
|
47
|
+
def receive_data(p_data)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def post_init
|
|
51
|
+
add_periodic_timer(2) { say_hello_world }
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def connection_completed
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def say_hello_world
|
|
58
|
+
p "***************** : invoking hello world #{Time.now}"
|
|
59
|
+
send_data("Hello World\n")
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
class ServerWorker < BackgrounDRb::MetaWorker
|
|
64
|
+
set_worker_name :server_worker
|
|
65
|
+
def create(args = nil)
|
|
66
|
+
# start the server when worker starts
|
|
67
|
+
start_server("0.0.0.0",11009,TimeServer) do |client_connection|
|
|
68
|
+
client_connection.say_hello_world
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end </pre>
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
</div>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
<div id="content">
|
|
2
|
+
|
|
3
|
+
%(entry-title)<a name="trac">Submit Bug Report or Patch </a>%
|
|
4
|
+
|
|
5
|
+
_BackgrounDRb_ causing trouble, or you have a potential fix? Why not submit the bug report "here":http://backgroundrb.devjavu.com/report/ .
|
|
6
|
+
You can also submit potential patches that fix known bugs or add exciting features to the above trac url.
|
|
7
|
+
|
|
8
|
+
Also, if you are using older version of _BackgrounDRb_ and having a problem, why not upgrade to latest code from git, your bug
|
|
9
|
+
might have been fixed there.
|
|
10
|
+
|
|
11
|
+
%(entry-title)<a name="known_bugs">Known Problems </a>%
|
|
12
|
+
|
|
13
|
+
Since _BackgrounDRb_ has feature of thread pools, which allows users to execute tasks
|
|
14
|
+
concurrently, we are using @allow_concurrency = true@ in @ActiveRecord@ model objects.
|
|
15
|
+
This has been known to create some issues with Oracle database Adapters. If you are sure of
|
|
16
|
+
what you are doing and don't need thread pool feature, you can go ahead and remove @allow_concurrency = true@
|
|
17
|
+
from _BackgrounDRb_ code and it should work.
|
|
18
|
+
|
|
19
|
+
</div>
|
|
20
|
+
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
<div id="content">
|
|
2
|
+
|
|
3
|
+
%(entry-title)<a name="people"> People </a>%
|
|
4
|
+
|
|
5
|
+
_BackgrounDRb_ has been brought to you by, "Hemant Kumar":http://gnufied.org with help of folks
|
|
6
|
+
from Ruby and Ruby on Rails community. _BackgrounDRb_ was an original idea of "Ezra Zygmuntowicz":http://brainspl.at .
|
|
7
|
+
|
|
8
|
+
Today it pulls in ideas from "EventMachine":http://eventmachine.rubyforge.org , "Twisted":http://twistedmatrix.com .
|
|
9
|
+
I am eternally grateful to following people ( in no particular order ):
|
|
10
|
+
|
|
11
|
+
*(content_list) Francis Cianfrocca : For EventMachine
|
|
12
|
+
* Matz : For creating Ruby
|
|
13
|
+
* Dale Cook : For Documentation
|
|
14
|
+
* "Jason LaPier":http://offtheline.net : for initial testing and bug reports.
|
|
15
|
+
* Kevin Russell : For Letting me work on his Mac machine all day and night and helping out with Mac OSX issues.
|
|
16
|
+
* Richard Stallman: For giving us free software and Emacs.
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
%(entry-title)<a name="mailing_list"> Mailing List </a>%
|
|
20
|
+
|
|
21
|
+
You can join BackgrounDRb mailing list "here":http://rubyforge.org/mailman/listinfo/backgroundrb-devel .
|
|
22
|
+
Its a perfect place for discussing new ideas, asking questions, submitting patches and stuff.
|
|
23
|
+
|
|
24
|
+
%(entry-title)<a name="irc"> IRC Help </a>%
|
|
25
|
+
|
|
26
|
+
You can also try #backgroundrb on freenode for help.
|
|
27
|
+
|
|
28
|
+
%(entry-title)<a name="contribute"> Contribute </a>%
|
|
29
|
+
|
|
30
|
+
Your contributions/feedback is most welcome. We have very simple rule for giving new coders
|
|
31
|
+
commit access. If you submit one patch which is accepted for inclusion in the _BackgrounDRb_
|
|
32
|
+
code repository, you are elligible for commit access. Create an account on "Github":http://github.com/
|
|
33
|
+
and let me (gethemant at gmail dot com) know your login handle.
|
|
34
|
+
|
|
35
|
+
</div>
|
|
36
|
+
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
<div id="content">
|
|
2
|
+
|
|
3
|
+
%(entry-title)<a name="introduction"> Introduction </a>%
|
|
4
|
+
|
|
5
|
+
*BackgrounDRb* is a Ruby job server and scheduler. Its main intent is to be
|
|
6
|
+
used with Ruby on Rails applications for offloading long-running tasks.
|
|
7
|
+
Since a Rails application blocks while serving a request it is best to
|
|
8
|
+
move long-running tasks off into a background process that is divorced
|
|
9
|
+
from http request/response cycle.
|
|
10
|
+
|
|
11
|
+
%(entry-title)<a name="installation"> Installation </a>%
|
|
12
|
+
|
|
13
|
+
p(sub-title). Installing the dependencies :
|
|
14
|
+
|
|
15
|
+
As of version 1.0.4 _BackgrounDRb_ depends on _chronic_ and _packet_ gems. Thus lets get
|
|
16
|
+
started by installing these two gems:
|
|
17
|
+
|
|
18
|
+
<pre class="boxed">sudo gem install chronic packet </pre>
|
|
19
|
+
|
|
20
|
+
Please note that, this version of _BackgrounDRb_ needs packet version 0.1.7 or greater, so make
|
|
21
|
+
sure you have that.
|
|
22
|
+
|
|
23
|
+
p(sub-title). Getting the code from Subversion :
|
|
24
|
+
|
|
25
|
+
<pre class="boxed"> svn co http://svn.devjavu.com/backgroundrb/trunk </pre>
|
|
26
|
+
|
|
27
|
+
p(sub-title). Installing from Git:
|
|
28
|
+
|
|
29
|
+
As of version 1.0.4 __BackgrounDRb__ development has moved to <a href="http://github.com/gnufied/backgroundrb/tree/master">github</a>. Above SVN url
|
|
30
|
+
will always mirror stable releases from Git. However to enjoy latest and greatest of features
|
|
31
|
+
you can install the plugin from git:
|
|
32
|
+
|
|
33
|
+
<pre class="multiline">
|
|
34
|
+
git clone git://github.com/gnufied/backgroundrb.git </pre>
|
|
35
|
+
|
|
36
|
+
<p style="text-decoration: line-through;"> Also for running git version of BackgrounDRb you will need, git version of packet.</p>
|
|
37
|
+
|
|
38
|
+
p(sub-title). Installation using Piston
|
|
39
|
+
|
|
40
|
+
<pre class="boxed">piston import http://svn.devjavu.com/backgroundrb/trunk/ backgroundrb </pre>
|
|
41
|
+
|
|
42
|
+
%(entry-title)<a name="configuration"> Configuration </a>%
|
|
43
|
+
|
|
44
|
+
After getting the plugin, you must copy it into your vendor/plugins and
|
|
45
|
+
then configure it for use. _BackgrounDRb_ comes with a rake task for
|
|
46
|
+
automating plugin configuration. Before running rake task, remove if
|
|
47
|
+
any old @backgroundrb@ or @load_worker_env.rb@ script is there in script folder of your rails
|
|
48
|
+
app after that run, following command from root directory of your
|
|
49
|
+
rails application:
|
|
50
|
+
|
|
51
|
+
<pre class="boxed">rake backgroundrb:setup </pre>
|
|
52
|
+
|
|
53
|
+
Above Command does following things :
|
|
54
|
+
|
|
55
|
+
*(content_list) Creates a config file @backgroundrb.yml@ in config directory of your rails application.
|
|
56
|
+
* Creates @RAILS_ROOT/lib/workers@ directory for keeping BackgrounDRb workers in one place.
|
|
57
|
+
* Creates @RAILS_ROOT/test/bdrb_test_helper.rb@ as a test helper for your workers
|
|
58
|
+
* Creates migration required for creating persistent job queue table.
|
|
59
|
+
|
|
60
|
+
After above make sure, that generated migration is ran using:
|
|
61
|
+
|
|
62
|
+
<pre class="boxed">rake db:migrate </pre>
|
|
63
|
+
|
|
64
|
+
p(sub-title). Configuration Options
|
|
65
|
+
|
|
66
|
+
A default @backgroundrb.yml@ file looks like this:
|
|
67
|
+
|
|
68
|
+
<pre class="multiline">
|
|
69
|
+
:backgroundrb:
|
|
70
|
+
:port: 11006
|
|
71
|
+
:ip: 0.0.0.0 </pre>
|
|
72
|
+
|
|
73
|
+
However, various other configuration options are available. For example, to load @production@
|
|
74
|
+
environment in your workers:
|
|
75
|
+
|
|
76
|
+
<pre class="multiline">
|
|
77
|
+
:backgroundrb:
|
|
78
|
+
:port: 11006
|
|
79
|
+
:ip: 0.0.0.0
|
|
80
|
+
:environment: production </pre>
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
Following file demonstrates other available configuration options:
|
|
84
|
+
|
|
85
|
+
<pre class="multiline">
|
|
86
|
+
---
|
|
87
|
+
:backgroundrb:
|
|
88
|
+
:port: 11006 # port to start listen
|
|
89
|
+
:ip: localhost # host to listen
|
|
90
|
+
:environment: production # rails environment to load
|
|
91
|
+
:log: foreground # foreground mode,print log messages on console
|
|
92
|
+
:debug_log: false # disable log workers and other logging
|
|
93
|
+
:persistent_disabled: false # turn this off if your application doesn't use backgroundrb's persistent/enqueued tasks system
|
|
94
|
+
:persistent_delay: 10 # the time (seconds) between each time backgroundrb checks the database for enqueued tasks
|
|
95
|
+
:schedules: # optional task scheduling
|
|
96
|
+
: # look in scheduling section </pre>
|
|
97
|
+
|
|
98
|
+
%(entry-title)<a name="worker"> Workers </a>%
|
|
99
|
+
|
|
100
|
+
Once you are set with initial configuration, you can proceed to create worker and start
|
|
101
|
+
_BackgrounDRb_ server. To generate a worker:
|
|
102
|
+
|
|
103
|
+
<pre class="boxed"> ./script/generate worker billing </pre>
|
|
104
|
+
|
|
105
|
+
Output will look something like:
|
|
106
|
+
|
|
107
|
+
<pre class="multiline">exists lib/workers/
|
|
108
|
+
create lib/workers/billing_worker.rb </pre>
|
|
109
|
+
|
|
110
|
+
And generated worker will look like:
|
|
111
|
+
|
|
112
|
+
<pre class="multiline">class BillingWorker < BackgrounDRb::MetaWorker
|
|
113
|
+
set_worker_name :billing_worker
|
|
114
|
+
def create(args = nil)
|
|
115
|
+
# method gets called, when new instance of worker is created.
|
|
116
|
+
end
|
|
117
|
+
end </pre>
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
You can define worker specific initialization in @create@ method. Tasks that are to be executed
|
|
121
|
+
in this worker should be defined as seperate methods. For example:
|
|
122
|
+
|
|
123
|
+
<pre class="multiline">class BillingWorker < BackgrounDRb::MetaWorker
|
|
124
|
+
set_worker_name :billing_worker
|
|
125
|
+
def create(args = nil)
|
|
126
|
+
# this method is called, when worker is loaded for the first time
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def charge_customer(customer_id = nil)
|
|
130
|
+
logger.info 'charging customer now'
|
|
131
|
+
end
|
|
132
|
+
end </pre>
|
|
133
|
+
|
|
134
|
+
%(entry-title)<a name="invoking_tasks"> Invoking Tasks </a>%
|
|
135
|
+
|
|
136
|
+
Task @charge_customer@ defined in @BillingWorker@ can be invoked in several ways. To beging with
|
|
137
|
+
it can be invoked from rails or can be scheduled to execute at particular interval using
|
|
138
|
+
cron like syntax.
|
|
139
|
+
|
|
140
|
+
p(sub-title). Invoking Task from Rails :
|
|
141
|
+
|
|
142
|
+
In your Rails controllers you have access to proxy class @MiddleMan@ which can be used
|
|
143
|
+
to interact with BackgrounDRb server, either from Rails controllers/Models or from Rails console.
|
|
144
|
+
For example to invoke @charge_customer@ method asychronously one can use:
|
|
145
|
+
|
|
146
|
+
<pre class="boxed">MiddleMan.worker(:billing_worker).async_charge_customer(:arg => current_customer.id) </pre>
|
|
147
|
+
|
|
148
|
+
Above code can be also executed from Rails console.
|
|
149
|
+
|
|
150
|
+
p(sub-title). Start the BackgrounDRb server :
|
|
151
|
+
|
|
152
|
+
You can use:
|
|
153
|
+
|
|
154
|
+
<pre class="boxed">./script/backgroundrb start </pre>
|
|
155
|
+
|
|
156
|
+
For more options:
|
|
157
|
+
|
|
158
|
+
<pre class="boxed">./script/backgroundrb --help </pre>
|
|
159
|
+
|
|
160
|
+
As documented above, you can use @backgroundrb.yml@ file to load different rails environments, however you can use:
|
|
161
|
+
|
|
162
|
+
<pre class="boxed">./script/backgroundrb -e development </pre>
|
|
163
|
+
|
|
164
|
+
</div>
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
<div id="content">
|
|
2
|
+
|
|
3
|
+
%(entry-title)<a name="faq"> Frequently asked Questions </a>%
|
|
4
|
+
|
|
5
|
+
*(content_list) *How does it work with ActiveRecord in multi-threaded environment?*<br/>
|
|
6
|
+
You can use _BackgrounDRb_'s inbuilt thread pool for executing tasks
|
|
7
|
+
concurrently. We are using @allow_concurrency = true@ for @ActiveRecord@
|
|
8
|
+
models, which is known to create problem with Oracle database adapters, if
|
|
9
|
+
you are using Oracle db, you can turn it off, by removing @allow_concurrency = true@.
|
|
10
|
+
* *Whats the deal with persistent job queues?*<br />
|
|
11
|
+
Well, its used for persisting tasks to the table, so as later
|
|
12
|
+
then can be inspected for status and results. Before using this feature.You should
|
|
13
|
+
run @rake backgroundrb:setup@ and run @rake db:migrate@ for creation of required
|
|
14
|
+
table.
|
|
15
|
+
* *My worker dies silently*<br />
|
|
16
|
+
First,make sure you have logging enabled (Meaning, you are not using @:debug_log false@
|
|
17
|
+
in your config file).Second, if a worker dies, the backtrace should be written to the
|
|
18
|
+
file @RAILS_ROOT/log/backgroundrb_debug_xxxx.log@. Third, You should not pass
|
|
19
|
+
entire @ActiveRecord@ model's around, this could cause hard to debug problems.AR objects
|
|
20
|
+
don't serialize well across tcp sockets. If none of this helps, hit us on the mailing list.
|
|
21
|
+
* *Master server died silently*<br/>
|
|
22
|
+
If _BackgrounDRb_ master server dies, its definetely a bug in _BackgrounDRb_, exception
|
|
23
|
+
should be still logged in same @RAILS_ROOT/log/backgroundrb_debug_xxxx.log@ file. Copy
|
|
24
|
+
the exception and file a bug report.
|
|
25
|
+
* *Where do I file bug reports?* <br />
|
|
26
|
+
You can submit bug reports at: "http://backgroundrb.devjavu.com/report/":http://backgroundrb.devjavu.com/report/.
|
|
27
|
+
* *Result caching is not working properly* <br />
|
|
28
|
+
Switch to memcache for storing results. More information "here:"http://localhost:3000/workers/#result_caching.
|
|
29
|
+
* *Dynamically started workers through @new_worker@ are not working* <br />
|
|
30
|
+
Use, the worker key that was used for accessing dynamically started workers.
|
|
31
|
+
* *BackgrounDRb server is not starting*<br />
|
|
32
|
+
Make sure, you have latest version of chronic and packet gems installed.After
|
|
33
|
+
that, clone the git repository (or download a snapshot from github) and run
|
|
34
|
+
@rake backgroundrb:setup@. If you are upgrading make sure, that older
|
|
35
|
+
autogenerated scripts namely, @load_worker_env.rb@ and @backgroundrb@
|
|
36
|
+
are removed from script directory of your rails application before running
|
|
37
|
+
rake task.If you are upgrading to 1.1, check if @scheduled_at@ column
|
|
38
|
+
is there in @bdrb_job_queues@ table.
|
|
39
|
+
|
|
40
|
+
</div>
|
|
41
|
+
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
<div id="content">
|
|
2
|
+
|
|
3
|
+
%(entry-title)<a name="introduction"> Introduction </a>%
|
|
4
|
+
|
|
5
|
+
BackgrounDRb offers seamless integration with rails. You can invoke random tasks defined in your
|
|
6
|
+
workers from rails. You can pass arguments, collect results, monitor status of workers and other
|
|
7
|
+
stuff.
|
|
8
|
+
|
|
9
|
+
%(entry-title)<a name="async_task"> Invoke a task asynchronously on a worker </a>%
|
|
10
|
+
|
|
11
|
+
Let's say, you have following worker code:
|
|
12
|
+
|
|
13
|
+
<pre class="multiline">class FooWorker < BackgrounDRb::MetaWorker
|
|
14
|
+
set_worker_name :foo_worker
|
|
15
|
+
def create(args = nil)
|
|
16
|
+
# this method is called, when worker is loaded for the first time
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def some_task args
|
|
20
|
+
# perform a long running task
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
</pre>
|
|
24
|
+
|
|
25
|
+
And you want to invoke @some_task@ method with appropriate arguments from rails.
|
|
26
|
+
Following snippet will invoke method @some_task@ with argument @data@ in @foo_worker@. Also, method will
|
|
27
|
+
be invoked asynchronously and Rails won't wait for result from BackgrounDRb server.
|
|
28
|
+
|
|
29
|
+
<pre class="multiline">worker = MiddleMan.worker(:foo_worker)
|
|
30
|
+
worker.async_some_task(:arg => data) </pre>
|
|
31
|
+
|
|
32
|
+
It should be noted that, since @some_task@ method is being
|
|
33
|
+
executed asynchronously, don't expect any meaningful return values from method invocation.
|
|
34
|
+
If you want to invoke a method on worker and collect results returned by it, you
|
|
35
|
+
should read next section (Invoke method and collect results).
|
|
36
|
+
|
|
37
|
+
When you invoke @MiddleMan.worker(:foo_worker)@ it returns a worker proxy, hence you can combine above two lines in
|
|
38
|
+
one as follows:
|
|
39
|
+
|
|
40
|
+
<pre class="multiline">MiddleMan.worker(:foo_worker,<optional_worker_key>).
|
|
41
|
+
async_some_task(:arg => data) </pre>
|
|
42
|
+
|
|
43
|
+
Above snippet also demonstrates that, if your worker was started with a @worker_key@ you can use it to
|
|
44
|
+
get correct worker proxy.
|
|
45
|
+
|
|
46
|
+
%(entry-title)<a name="sync_task"> Synchronous Task invocation (Invoke task and wait for results) </a>%
|
|
47
|
+
|
|
48
|
+
Following snippet will invoke method @some_task@ with argument @data@ in @foo_worker@. Also, method will block
|
|
49
|
+
until BackgrounDRb server returns a result.
|
|
50
|
+
|
|
51
|
+
<pre class="multiline">worker = MiddleMan.worker(:foo_worker)
|
|
52
|
+
result = worker.some_task(:arg => data) </pre>
|
|
53
|
+
|
|
54
|
+
Since, now you are expecting a return value from your worker method, new worker code will look like:
|
|
55
|
+
|
|
56
|
+
<pre class="multiline">class FooWorker < BackgrounDRb::MetaWorker
|
|
57
|
+
set_worker_name :foo_worker
|
|
58
|
+
def create(args = nil)
|
|
59
|
+
# this method is called, when worker is loaded for the first time
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def some_task args
|
|
63
|
+
billing_result = UserPayment.bill!
|
|
64
|
+
return billing_result
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
</pre>
|
|
68
|
+
|
|
69
|
+
As illustrated above, you can use @worker_key@ or make them in single line too.
|
|
70
|
+
|
|
71
|
+
%(entry-title)<a name="worker_results"> Retrieve Cached Worker results </a>%
|
|
72
|
+
|
|
73
|
+
If you are using @cache@ in your worker code to store result objects, you can retrieve them from
|
|
74
|
+
rails using:
|
|
75
|
+
|
|
76
|
+
<pre class="boxed">status_obj = MiddleMan.worker(:foo_worker).ask_result(cache_key) </pre>
|
|
77
|
+
|
|
78
|
+
You must use @worker_key@ if *worker was started with a worker_key*.
|
|
79
|
+
|
|
80
|
+
From controller, you can also reset result stored for a particular worker, with particular cache key.
|
|
81
|
+
This is only applicable, if you are using memcache for storing results.
|
|
82
|
+
|
|
83
|
+
<pre class="multiline">
|
|
84
|
+
MiddleMan.worker(:foo_worker).reset_memcache_result(cache_key) # or
|
|
85
|
+
MiddleMan.worker(:foo_worker,"worker_key").reset_memcache_result(cache_key)
|
|
86
|
+
</pre>
|
|
87
|
+
|
|
88
|
+
%(entry-title)<a name="persistent_task"> Enqueue task to the persistent job queue : </a>%
|
|
89
|
+
|
|
90
|
+
Jobs executed via synchronous and asynchronous APIs are fine, but these tasks are usually
|
|
91
|
+
kept in memory(and hence they are fast) and hence aren't entirely failsafe.
|
|
92
|
+
|
|
93
|
+
To solve this _BackgrounDRb_ also lets you add jobs to a persistent job queue, which is
|
|
94
|
+
automatically picked by responsible worker and invoked. To use this:
|
|
95
|
+
|
|
96
|
+
<pre class="boxed">MiddleMan(:hello_worker).enq_some_task(:arg => "hello_world",:job_key => "boy")</pre>
|
|
97
|
+
|
|
98
|
+
With _BackgrounDRb_ version >= 1.1, you can also schedule a persistent task to be executed at a particular time,
|
|
99
|
+
|
|
100
|
+
<pre class="multiline">MiddleMan(:hello_worker).enq_some_task(:arg => "hello_world",
|
|
101
|
+
:job_key => "boy",:scheduled_at => (Time.now + 1.hour))</pre>
|
|
102
|
+
|
|
103
|
+
Above line will add specified task to the job queue and set to be invoked at specified time. For more information
|
|
104
|
+
about scheduling see scheduling section.
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
%(entry-title)<a name="new_worker"> Start a new worker from controller </a>%
|
|
108
|
+
|
|
109
|
+
To start a worker from rails:
|
|
110
|
+
|
|
111
|
+
<pre class="multiline">used_job_key = MiddleMan.new_worker(:worker => :foo_worker,\
|
|
112
|
+
:worker_key => "my_secret_job_key") </pre>
|
|
113
|
+
|
|
114
|
+
Worker key passed here, while starting the worker can be used later for invoking tasks on started
|
|
115
|
+
worker or for accessing cached result objects and stuff like that.
|
|
116
|
+
|
|
117
|
+
Important thing to be kept in mind is, when you are creating a worker using above approach, you
|
|
118
|
+
must use a unique @worker_key@ while starting the worker. Also, while invoking any of the other methods
|
|
119
|
+
like @ask_result@, @worker_info@ or one of the worker methods, you must user same @worker_key@.
|
|
120
|
+
|
|
121
|
+
%(entry-title)<a name="worker_info"> Worker Info </a>%
|
|
122
|
+
|
|
123
|
+
You can get worker specific information using:
|
|
124
|
+
|
|
125
|
+
<pre class="boxed">MiddleMan.worker(:foo_worker).worker_info </pre>
|
|
126
|
+
|
|
127
|
+
The return value will look something like:
|
|
128
|
+
|
|
129
|
+
<pre class="boxed">{:worker=>:foo_worker, :status=>:running, :worker_key=>"hello"} </pre>
|
|
130
|
+
|
|
131
|
+
Information about all currently running workers can be obtained using:
|
|
132
|
+
|
|
133
|
+
<pre class="boxed">MiddleMan.all_worker_info </pre>
|
|
134
|
+
|
|
135
|
+
Return value will look like:
|
|
136
|
+
|
|
137
|
+
<pre class="multiline">{"0.0.0.0:11006"=>nil, "0.0.0.0:11008"=>
|
|
138
|
+
[{:worker_key=>"", :status=>:running, :worker=>:log_worker},
|
|
139
|
+
{:worker_key=>"", :status=>:running, :worker=>:foo_worker}]}</pre>
|
|
140
|
+
|
|
141
|
+
%(entry-title)<a name="clustering"> BackgrounDRb Clustering </a>%
|
|
142
|
+
|
|
143
|
+
By using following option in your @backgroundrb.yml@ you can cluster more than
|
|
144
|
+
one backgroundrb server.
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
<pre class="multiline">:backgroundrb:
|
|
148
|
+
:ip: 0.0.0.0
|
|
149
|
+
:port: 11006
|
|
150
|
+
:environment: production
|
|
151
|
+
:client: "10.0.0.1:11006,10.0.0.2:11007"</pre>
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
So what happens here is, now BackgrounDRb client will talk to bdrb
|
|
155
|
+
servers running on both @10.0.0.1:11006@ and @10.0.0.2:11007@. So when you invoke
|
|
156
|
+
a task like this:
|
|
157
|
+
|
|
158
|
+
<pre class="boxed">MiddleMan.worker(:foo_worker).async_some_task(:arg => data) </pre>
|
|
159
|
+
|
|
160
|
+
Your task gets executed in round robin manner in specified servers by default.
|
|
161
|
+
Also, once a server goes down, it will automatically stop participating in clustering and
|
|
162
|
+
when it comes back, it will be automatically start participating in clustering.
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
In addition to default round robin task distribution, you can override this behaviour
|
|
166
|
+
by passing additional @:host@ option while invoking task from rails.For example:
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
<pre class="multiline">
|
|
170
|
+
# run method 'some_task' on all backgroundrb servers
|
|
171
|
+
MiddleMan.worker(:hello_worker).async_some_task(:arg => data,
|
|
172
|
+
:job_key => session[:user_id],:host => :all)
|
|
173
|
+
|
|
174
|
+
# run method 'some_task' on only locally configured server
|
|
175
|
+
MiddleMan.worker(:hello_worker).async_some_task(:arg => data,
|
|
176
|
+
:job_key => session[:user_id],:host => :local)
|
|
177
|
+
|
|
178
|
+
# run the task on specified server
|
|
179
|
+
MiddleMan.worker(:hello_worker).async_some_task(:arg => data,:job_key => \
|
|
180
|
+
session[:user_id],:host => "10.0.0.2:11210")
|
|
181
|
+
</pre>
|
|
182
|
+
</div>
|