tomykaira/clockwork — pull request #114 by robisenberg (2014-08-11 20:25:04+00:00)
Title: Database events: major refactor

@tomykaira I didn't want to go ahead and merge this change without consulting you first. I know originally you were happy to include this feature because I was able to keep the code in a single file. However, to keep things maintainable I felt it necessary to split out the code into a modular structure.

Also, I'm aware I've broken backwards compatibility for people using the database events feature. I'm not sure how we should bump the Clockwork version to indicate this.

What are your thoughts? I'm happy to take your guidance. If you feel this feature really should be in a separate gem e.g. `clockwork-database-events` that just _uses_ the `clockwork` gem, I'm willing to do that if you think it's best.

--------------

# Summary

The code to implement database events wasn't well factored, with `DatabaseEventSyncPerformer` taking on too many responsibilities. The refactor improves this, and creates a nice modular structure for the feature. It also removes some unsightliness the first incarnation has.

This improvement comes, however, at a price, and the changes are __not backwards compatible__.

# Main Changes

## Usage

* __Warning:__ not backwards compatible.

Actual model instance is now passed as the job, rather than just name. This greatly simplifies use of database events: users do not need to implement their own `#name` method on their model, and instead of this ugliness:

```ruby
sync_database_tasks model: MyScheduledTask, every: 1.minute do |instance_job_name|
id = instance_job_name.split(':').last
task = MyScheduledTask.find(id)
# use task to help do some work...
# e.g. task.perform
end
```

you now have convenient access to the model instance, should you need it:

```ruby
sync_database_events model: MyScheduledTask, every: 1.minute do |model_instance|
# use model_instance without having to fetch it
# e.g. model_instance.perform
end
```

* Renamed `sync_database_tasks` to `sync_database_events`, but providing alias for backwards-compatibility

## Technical

* create module structure for `DatabaseEvents` module putting various classes under `lib/database_events`

* separate concerns into separate classes:
- `DatabaseEvents::Event` (subclass of standard `Clockwork::Event` and responsible for representing the database event within clockwork)
- `DatabaseEvents::Manager` (subclassed, drop-in replacement of standard `Clockwork::Manager` to allow use of database events)
- `DatabaseEvents ::Registry` (responsible for keeping track of the database events registered with clockwork)
- `DatabaseEvents::SyncPerformer` (responsible for syncing database events with clockwork),

* use consistent terminology to improve clarity of code

* improve README to hopefully reduce confusion

* refactor tests to:
- restructure them to match new modular structure
- use new `ActiveRecordFake` class which allows for more real-world, fluent code, e.g. `DatabaseEventModelClass.create(:frequency => 1.day, :at => '16:20, 18:10')`
- use new `setup_sync` helper to avoid visual clutter of calling `@manager.sync_database_tasks` each time