To run your code in cloud you need to do three things:
While you can use REST APIs for that, it's easier to use an IronWorker library created specifically for your language of choice, such as this gem, IronWorkerNG.
You'll need to register at http://iron.io/ and get your credentials to use IronWorkerNG. Each account can have an unlimited number of projects, so take advantage of it by creating separate projects for development, testing and production. Each project is identified by a unique project ID and requires your access token before it will perform any action, like uploading or queuing workers.
Also, you'll need a Ruby 1.9 interpreter and the IronWorkerNG gem. Install it using following command.
gem install iron_worker_ng
Each IronWorkerNG Ruby worker is just Ruby code. It can be as simple or as complex as you want. For example, the following is an acceptable worker:
puts "Hello Worker!"
puts "My task_id is #{@iron_task_id}"
puts "I got '#{params}' parameters"
All output to STDOUT
will be logged and available for your review when your worker finishes execution.
Before you can use IronWorker, be sure you've created a free account with Iron.io and setup your Iron.io credentials on your system (either in a json file or using ENV variables). You only need to do that once for your machine. If you've done that, then you can continue.
Since our worker will be executed in the cloud, you'll need to bundle all the necessary gems,
supplementary data, and other dependencies with it. .worker
files make it easy to define your worker.
# define the runtime language, this can be ruby, java, node, php, go, etc.
# also you could set version of language(check of available versions via iron_worker stacks)
runtime "ruby","2.1"
# exec is the file that will be executed:
exec "hello_worker.rb"
You can read more about .worker
files here: http://dev.iron.io/worker/reference/dotworker/
If your .worker file is called hello.worker
, then run:
iron_worker upload hello
This will upload your worker with the name "hello" so you can reference it like that when queuing up tasks for it.
You can quicky queue up a task for your worker from the command line using:
iron_worker queue hello
Use the -p
parameter to pass in a payload:
iron_worker queue hello -p "{\"hi\": \"world\"}"
Use the --wait
parameter to queue a task, wait for it to complete and print the log.
iron_worker queue hello -p "{\"hi\": \"world\"}" --wait
Most commonly you'll be queuing up tasks from code though, so you can do this:
require "iron_worker_ng"
client = IronWorkerNG::Client.new
100.times do
client.tasks.create("hello", "foo"=>"bar")
end
You can specify priority of the task using --priority
parameter:
iron_worker queue hello --priority 0 # default value, lowest priority
iron_worker queue hello --priority 1 --label 'medium priority task' # medium priority
Value of priority parameter means the priority queue to run the task in. Valid values are 0, 1, and 2. 0 is the default.
From code you can set the priority like it done in snippet below:
client.tasks.create("hello", some_params, priority: 2) # highest priority
You can specify not only priority:
When you call iron_worker queue X
, you'll see the task ID in the output which you can use to get the status.
iron_worker info task 5032f7360a4681382838e082
Similar to getting status, get the task ID in the queue command output, then:
iron_worker log 5032f7360a4681382838e082 --wait
You can retry task by id using same payload and options:
iron_worker retry 5032f7360a4681382838e082
or
client.tasks.retry('5032f7360a4681382838e082', :delay => 10)
## Pause or Resume task processing
You can temporarily pause or resume queued and scheduled tasks processing by code name:
iron_worker pause hello
iron_worker resume hello
or by code:
Pause or resume for the code package specified by `code_id`.
```ruby
response = client.codes.pause_task_queue('1234567890')
response = client.codes.resume_task_queue('1234567890')
To get a bunch of extra output to debug things, turn it on using:
IronCore::Logger.logger.level = ::Logger::DEBUG
The IronWorkerNG::Code::Base class will help you package your code for upload, but to upload it to the cloud, you'll need to use the IronWorkerNG::Client
class.
Create new code package with the specified args.
code_from_workerfile = IronWorkerNG::Code::Base.new(:workerfile => 'example.worker')
code_with_name = IronWorkerNG::Code::Base.new(:exec => 'example.rb', :name => 'Example')
code_with_guessed_name = IronWorkerNG::Code::Base.new(:exec => 'example.rb')
code = IronWorkerNG::Code::Base.new
Return the code package's runtime.
puts code.runtime
Sets the code package's runtime. If no runtime provided it defaults to 'ruby'.
code.runtime = 'ruby'
Return the code package's name.
puts code.name
Sets the code package's name.
code.name = 'CoolWorker'
Command which will be executed once (on worker upload). Can be used for heavy tasks like building your worker from sources. Check https://github.com/iron-io/iron_worker_examples/tree/master/binary/phantomjs for real world example.
code.remote_build_command('curl http://www.kernel.org/pub/linux/kernel/v3.0/linux-3.4.6.tar.bz2 -o linux-3.4.6.tar.bz2 && tar xf linux-3.4.6.tar.bz2')
If set to true, activates full remote build mode. In this mode iron_worker will try to resolve as much things as possible at build step. For example, all gems will be installed at build step, which will allow you to use gems with native extensions.
Alias for full_remote_build(true)
.
Runs code package on your local box. Can be useful for testing.
code.run
Merge the file located at path
into the code package. If dest
is set, it will be used as the path to a directory within the zip, into which the file will be merged. If the directory does not exist, it will be automatically created.
code.merge_file '../config/database.yml' # will be in the same directory as worker
code.merge_file 'clients.csv', 'information/clients' # will be in information/clients subdirectory
Recursively merge the directory located at path into the code package. If dest
is set, it will be used as the path to a directory within the zip, into which the directory specified by path
will be merged. If dest
is set but does not exist, it will be automatically created.
code.merge_dir '../config' # will be in the same directory as worker
code.merge_dir 'lib', 'utils' # will be in utils subdirectory, accessible as utils/lib
Merges provided deb package into your worker. Please note that it should be x86-64 deb and we don't do any dependencies resolving. It might not work for some packages which expects to find things it predefined place (e.g. imagemagick looks for codecs in /usr/lib/ImageMagick-X.X.X/codecs). If you are uploading from non-debian OS, just use full remote build, so deb manipulations will be done on IronWorker servers. Following example brings power of pdftk to your worker.
code.merge_deb 'http://mirror.pnl.gov/ubuntu/pool/universe/p/pdftk/pdftk_1.44-3_amd64.deb'
code.merge_deb 'http://mirror.pnl.gov/ubuntu/pool/main/g/gcj-4.6/libgcj12_4.6.1-4ubuntu2_amd64.deb'
Specific methods for ruby runtime.
Merge the exec located at path
. If klass
is provided, it'll try to instantiate it, set attrs from params and fire up run
method when executed.
code.merge_exec 'my_worker.rb'
Merge a gem with dependencies. Gems with native extensions will not be merged by default, switching to full remote build should fix this. You can use version constrains if you need a specific gem version. Please note that git
and path
gems aren't supported yet.
code.merge_gem 'activerecord'
code.merge_gem 'paperclip', '< 3.0.0,>= 2.1.0'
Merge all gems from specified the groups in a Gemfile. Please note that this will not auto-require the gems when executing the worker.
code.merge_gemfile '../Gemfile', 'common', 'worker' # merges gems from common and worker groups
Specific methods for binary (freeform) runtime.
Merge the exec located at path
.
code.merge_exec 'my_worker.sh'
Specific methods for go runtime. It'll run provided exec via 'go run'.
Merge the exec located at path
.
code.merge_exec 'my_worker.go'
Specific methods for java runtime.
Merge the exec located at path
. If class isn't provided, it'll relay on jar's manifest.
code.merge_exec 'my_worker.jar'
Merge the jar located at path
. It'll be added to classpath when executing your worker.
code.merge_jar 'xerces.jar'
Specific methods for mono (.net) runtime.
Merge the exec located at path
.
code.merge_exec 'my_worker.exe'
Specific methods for node runtime.
Merge the exec located at path
.
code.merge_exec 'my_worker.js'
Specific methods for perl runtime.
Merge the exec located at path
.
code.merge_exec 'my_worker.pl'
Specific methods for PHP runtime.
Merge the exec located at path
.
code.merge_exec 'my_worker.php'
Specific methods for python runtime.
Merge the exec located at path
.
code.merge_exec 'my_worker.py'
Merge a pip package with dependencies. If any pip package contains native extensions, switch to full remote build. You can use version constrains if you need a specific pip package version.
code.merge_pip 'iron_mq'
code.merge_pip 'iron_worker', '==0.2'
Merge all libraries from a python standard requirements.txt. The requirements.txt example file after freezing may look like as follows:
Flask==0.8
Jinja2==2.6
Werkzeug==0.8.3
certifi==0.0.8
chardet==1.0.
code.merge_requirements '../requirements.txt'
When you have your code package, you are ready to upload and run it on the IronWorker cloud.
# Initialize the client
client = IronWorkerNG::Client.new(:token => 'IRON_IO_TOKEN', :project_id => 'IRON_IO_PROJECT_ID')
# Upload the code
client.codes.create(code)
NOTE: You only need to call client.codes.create(code)
once for each time your code changes.
Now that the code is uploaded, we can create/queue up tasks. You can call this over and over for as many tasks as you want.
client.tasks.create('MyWorker', {:client => 'Joe'})
Stack is a docker image based on ubuntu + some custom software(ruby/python/mono/java...) You can use different stacks to launch your tasks. To get list of available stacks you could do:
client.stacks_list
or using cli
iron_worker stacks
And to specify stack add following line in your .worker file
runtime 'ruby', '2.1'
Or
exec 'java.sh'
runtime 'binary'
stack 'java-1.7'
exec 'java.sh'
You can use the IronWorkerNG::Client
class to upload code packages, queue tasks, create schedules, and more.
Create a client object used for all your interactions with the IronWorker cloud.
client = IronWorkerNG::Client.new(:token => 'IRON_IO_TOKEN', :project_id => 'IRON_IO_PROJECT_ID')
Return an array of information about uploaded code packages. Visit http://dev.iron.io/worker/reference/api/#list_code_packages for more information about the available options and the code package object format.
client.codes.list.each do |code|
puts code.inspect
end
Return information about an uploaded code package with the specified ID. Visit http://dev.iron.io/worker/reference/api/#get_info_about_a_code_package for more information about the code package object format.
puts client.codes.get('1234567890').name
Upload an IronWorkerNG::Code::Ruby
object to the IronWorker cloud.
client.codes.create(code)
Delete the code package specified by code_id
from the IronWorker cloud.
client.codes.delete('1234567890')
Get an array of revision information for the code package specified by code_id
. Visit http://dev.iron.io/worker/reference/api/#list_code_package_revisions for more information about the available options and the revision objects.
client.codes.revisions('1234567890').each do |revision|
puts revision.inspect
end
Download the code package specified by code_id
and return it as an array of bytes. Visit http://dev.iron.io/worker/reference/api/#download_a_code_package for more information about the available options.
data = client.codes.download('1234567890')
Retrieve an array of information about your workers' tasks. Visit http://dev.iron.io/worker/reference/api/#list_tasks for more information about the available options and the task object format.
client.tasks.list.each do |task|
puts task.inspect
end
Return information about the task specified by task_id
. Visit http://dev.iron.io/worker/reference/api/#get_info_about_a_task for more information about the task object format.
puts client.tasks.get('1234567890').code_name
Queue a new task for the code package specified by code_name
, passing the params
hash to it as a payload and returning a task object with only the id
field filled. Visit http://dev.iron.io/worker/reference/api/#queue_a_task for more information about the available options.
task = client.tasks.create('MyWorker', {:client => 'Joe'}, {:delay => 180})
puts task.id
Cancel the task specified by task_id
.
client.tasks.cancel('1234567890')
Cancel all tasks for the code package specified by code_id
.
client.tasks.cancel_all('1234567890')
Retrieve the full task log for the task specified by task_id
. Please note that log is available only after the task has completed execution. The log will include any output to STDOUT
.
puts client.tasks.log('1234567890')
Set the progress information for the task specified by task_id
. This should be used from within workers to inform you about worker execution status, which you can retrieve with a tasks.get
call. Visit http://dev.iron.io/worker/reference/api/#set_a_tasks_progress for more information about the available options.
client.tasks.set_progress('1234567890', {:msg => 'Still running...'})
Wait (block) while the task specified by task_id
executes. Options can contain a :sleep
parameter used to modify the delay between API invocations; the default is 5 seconds. If a block is provided (as in the example below), it will be called after each API call with the task object as parameter.
client.tasks.wait_for('1234567890') do |task|
puts task.msg
end
Return an array of scheduled tasks. Visit http://dev.iron.io/worker/reference/api/#list_scheduled_tasks for more information about the available options and the scheduled task object format.
client.schedules.list.each do |schedule|
puts schedule.inspect
end
Return information about the scheduled task specified by schedule_id
. Visit http://dev.iron.io/worker/reference/api/#get_info_about_a_scheduled_task for more information about the scheduled task object format.
puts client.schedules.get('1234567890').last_run_time
Create a new scheduled task for the code package specified by code_name
, passing the params hash to it as a data payload and returning a scheduled task object with only the id
field filled. Visit http://dev.iron.io/worker/reference/api/#schedule_a_task for more information about the available options.
schedule = client.schedules.create('MyWorker', {:client => 'Joe'}, {:start_at => Time.now + 3600, :run_every =>60, :priority => 0, :run_times => 100, :end_at: Time.now + 2592000, Time.now + 84600})
puts schedule.id
Update a scheduled task specified by id
client.schedules.update('545b3cb829acd33ea10016e4', {label: 'new_label'})
Or you can update a scheduled task for your worker from the command line using:
iron_worker update schedule 545b3cb829acd33ea10016e4 -s '{"label": "new_label"}'
Cancel the scheduled task specified by schedule_id
.
client.schedules.cancel('1234567890')
If you have an uploaded worker named super_code
with files qux.rb, bar.rb, etc.
and want to replace the content of bar.rb
with a local file foo.rb
, qux.rb
with baz.rb
just run a command:
iron_worker patch super_code -p 'foo.rb=bar.rb,baz.rb=lib/qux.rb.rb,foo.rb,foo2.rb'
No need to pass the same two file names foo.rb=foo.rb
, only one foo.rb
would be enough. Normally the patched version is put in place of the originals.