README.md in clockwork-0.7.2 vs README.md in clockwork-0.7.3
- old
+ new
@@ -101,10 +101,124 @@
every(1.hour, 'feeds.refresh') { Feed.send_later(:refresh) }
every(1.day, 'reminders.send', :at => '01:30') { Reminder.send_later(:send_reminders) }
```
+Use with database tasks
+-----------------------
+
+You can dynamically add tasks from a database to be scheduled along with the regular events in clock.rb.
+
+To do this, use the `sync_database_tasks` method call:
+
+```ruby
+require 'clockwork'
+require 'clockwork/manager_with_database_tasks'
+require_relative './config/boot'
+require_relative './config/environment'
+
+module Clockwork
+
+ # required to enable database syncing support
+ Clockwork.manager = ManagerWithDatabaseTasks.new
+
+ sync_database_tasks model: MyScheduledTask, every: 1.minute do |instance_job_name|
+ # Where your model will acts as a worker:
+ id = instance_job_name.split(':').last
+ task = MyScheduledTask.find(id)
+ task.perform_async
+
+ # Or, e.g. if your queue system just needs job names
+ # Stalker.enqueue(instance_job_name)
+ end
+
+ [...other tasks if you have...]
+
+end
+```
+
+This tells clockwork to fetch all MyScheduledTask instances from the database, and create an event for each, configured based on the instances' `frequency`, `name`, and `at` methods. It also says to reload the tasks from the database every 1.minute - we need to frequently do this as they could have changed (but you can choose a sensible reload frequency by changing the `every:` option). Note that the database sync event will always run on the minute-boundary (i.e. HH:MM::00), and that events which have been synced from the database won't be run in that same clock cycle (this prevents a task from the database being run twice).
+
+Rails ActiveRecord models are a perfect candidate for the model class, but you could use something else. The only requirements are:
+
+ 1. the class responds to `all` returning an array of instances from the database
+ 2. the instances returned respond to:
+ `frequency` returning the how frequently (in seconds) the database task should be run
+ `name` returning the task's job name (this is what gets passed into the block above)
+ `at` return nil or '' if not using :at, or any acceptable clockwork :at string
+
+Here's an example of one way of setting up your ActiveRecord models, using Sidekiq for background tasks, and making the model class a worker:
+
+```ruby
+# db/migrate/20140302220659_create_frequency_periods.rb
+class CreateFrequencyPeriods < ActiveRecord::Migration
+ def change
+ create_table :frequency_periods do |t|
+ t.string :name
+
+ t.timestamps
+ end
+ end
+end
+
+# 20140302221102_create_my_scheduled_tasks.rb
+class CreateMyScheduledTasks < ActiveRecord::Migration
+ def change
+ create_table :my_scheduled_tasks do |t|
+ t.integer :frequency_quantity
+ t.references :frequency_period
+ t.string :at
+
+ t.timestamps
+ end
+ add_index :my_scheduled_tasks, :frequency_period_id
+ end
+end
+
+# app/models/my_scheduled_task.rb
+class MyScheduledTask < ActiveRecord::Base
+ include Sidekiq::Worker
+
+ belongs_to :frequency_period
+ attr_accessible :frequency_quantity, :frequency_period_id, :at
+
+ # Used by clockwork to schedule how frequently this task should be run
+ # Should be the intended number of seconds between executions
+ def frequency
+ frequency_quantity.send(frequency_period.name.pluralize)
+ end
+
+ # Used by clockwork to name this task internally for its logging
+ # Should return a reference for this task to be used in clockwork
+ # Include the instance ID if you want to be able to retrieve the
+ # model instance inside the sync_database_tasks block in clock.rb
+ def name
+ "Database_MyScheduledTask:#{id}"
+ end
+
+ # Method required by Sidekiq
+ def perform
+ # the task that will be performed in the background
+ end
+end
+
+# app/models/frequency_period.rb
+class FrequencyPeriod < ActiveRecord::Base
+ attr_accessible :name
+end
+
+# db/seeds.rb
+...
+# creating the FrequencyPeriods
+[:second, :minute, :hour, :day, :week, :month].each do |period|
+ FrequencyPeriod.create(name: period)
+end
+...
+```
+
+You could, of course, create a separate Sidekiq or DelayedJob worker class under app/workers, and simply use the model referenced by clockwork to trigger that worker to run asynchronously.
+
Event Parameters
----------
### :at
@@ -321,9 +435,19 @@
on(:after_tick) do
puts "tock"
end
```
+
+Finally, you can use tasks synchronised from a database as described in detail above:
+
+```ruby
+sync_database_tasks model: MyScheduledTask, every: 1.minute do |instance_job_name|
+ # what to do with each instance
+end
+```
+
+You can use multiple `sync_database_tasks` if you wish, so long as you use different model classes for each (ActiveRecord Single Table Inheritance could be a good idea if you're doing this).
In production
-------------
Only one clock process should ever be running across your whole application