Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ tmp
/.bundle
Gemfile.lock
.ruby-version
.byebug_history
1 change: 1 addition & 0 deletions clockwork.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,5 @@ Gem::Specification.new do |s|
s.add_development_dependency "minitest", "~> 5.8"
s.add_development_dependency "mocha"
s.add_development_dependency "test-unit"
s.add_development_dependency "byebug"
end
5 changes: 3 additions & 2 deletions lib/clockwork/at.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
require 'clockwork/at/failed_to_parse'

module Clockwork
class At
class FailedToParse < StandardError; end

NOT_SPECIFIED = nil
WDAYS = %w[sunday monday tuesday wednesday thursday friday saturday].each.with_object({}).with_index do |(w, wdays), index|
[w, w.capitalize, w[0...3], w[0...3].capitalize].each do |k|
Expand Down Expand Up @@ -53,6 +53,7 @@ def == other
end

private

def valid?
@min == NOT_SPECIFIED || (0..59).cover?(@min) &&
@hour == NOT_SPECIFIED || (0..23).cover?(@hour) &&
Expand Down
5 changes: 5 additions & 0 deletions lib/clockwork/at/failed_to_parse.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module Clockwork
class At
class FailedToParse < StandardError; end
end
end
12 changes: 6 additions & 6 deletions lib/clockwork/database_events.rb
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
require_relative 'database_events/event'
require_relative 'database_events/synchronizer'
require_relative 'database_events/event_store'
require_relative 'database_events/manager'
require 'clockwork/database_events/event'
require 'clockwork/database_events/synchronizer'
require 'clockwork/database_events/event_collection'
require 'clockwork/database_events/event_store'
require 'clockwork/database_events/manager'

# TERMINOLOGY
#
# For clarity, we have chosen to define terms as follows for better communication in the code, and when
# For clarity, we have chosen to define terms as follows for better communication in the code, and when
# discussing the database event implementation.
#
# "Event": "Native" Clockwork events, whether Clockwork::Event or Clockwork::DatabaseEvents::Event
# "Model": Database-backed model instances representing events to be created in Clockwork

module Clockwork

module Methods
def sync_database_events(options={}, &block)
DatabaseEvents::Synchronizer.setup(options, &block)
Expand Down
4 changes: 0 additions & 4 deletions lib/clockwork/database_events/event.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
module Clockwork

module DatabaseEvents

class Event < Clockwork::Event

attr_accessor :event_store, :model_attributes

def initialize(manager, period, job, block, event_store, model_attributes, options={})
Expand All @@ -29,6 +26,5 @@ def frequency
@period
end
end

end
end
1 change: 0 additions & 1 deletion lib/clockwork/database_events/event_collection.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
module Clockwork
module DatabaseEvents
class EventCollection

def initialize(manager=Clockwork.manager)
@events = []
@manager = manager
Expand Down
6 changes: 0 additions & 6 deletions lib/clockwork/database_events/event_store.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
require_relative './event_collection'

# How EventStore and Clockwork manager events are kept in sync...
#
# The normal Clockwork::Manager is responsible for keeping track of
Expand All @@ -24,11 +22,8 @@
# - it creates a new DatabaseEvents::Event
# - DatabaseEvents::Event#initialize registers it with the EventStore
module Clockwork

module DatabaseEvents

class EventStore

def initialize(block_to_perform_on_event_trigger)
@related_events = {}
@block_to_perform_on_event_trigger = block_to_perform_on_event_trigger
Expand Down Expand Up @@ -131,6 +126,5 @@ def at_strings_for(model)
model.at.split(',').map(&:strip)
end
end

end
end
3 changes: 0 additions & 3 deletions lib/clockwork/database_events/manager.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
module Clockwork

module DatabaseEvents

class Manager < Clockwork::Manager

def unregister(event)
@events.delete(event)
end
Expand Down
6 changes: 0 additions & 6 deletions lib/clockwork/database_events/synchronizer.rb
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
require_relative '../database_events'

module Clockwork

module DatabaseEvents

class Synchronizer

def self.setup(options={}, &block_to_perform_on_event_trigger)
model_class = options.fetch(:model) { raise KeyError, ":model must be set to the model class" }
every = options.fetch(:every) { raise KeyError, ":every must be set to the database sync frequency" }
Expand All @@ -18,6 +13,5 @@ def self.setup(options={}, &block_to_perform_on_event_trigger)
end
end
end

end
end
1 change: 1 addition & 0 deletions lib/clockwork/event.rb
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ def to_s
end

private

def execute
@block.call(@job, @last)
rescue => e
Expand Down
5 changes: 3 additions & 2 deletions lib/clockwork/manager.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
require 'clockwork/manager/no_handler_defined'

module Clockwork
class Manager
class NoHandlerDefined < RuntimeError; end

attr_reader :config

def initialize
Expand Down Expand Up @@ -159,6 +159,7 @@ def log(msg)
end

private

def events_to_run(t)
@events.select{ |event| event.run_now?(t) }
end
Expand Down
6 changes: 6 additions & 0 deletions lib/clockwork/manager/no_handler_defined.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module Clockwork
class Manager
class NoHandlerDefined < RuntimeError; end
end
end

22 changes: 10 additions & 12 deletions test/database_events/support/active_record_fake.rb
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
module ActiveRecordFake

def self.included(base)
base.instance_variable_set(:@items, [])
base.instance_variable_set(:@next_id, 1)
base.instance_variable_set(:@next_id, 1)
base.extend(ClassMethods)
end


attr_accessor :id

def initialize options={}
Expand All @@ -28,10 +26,10 @@ def attributes
end

module ClassMethods
def create *args
new *args
def create(*args)
new(*args)
end

def delete_all
@items.clear
reset_id
Expand All @@ -41,8 +39,8 @@ def delete_all
def all
@items.dup
end


def add instance
@items << instance
end
Expand All @@ -64,7 +62,7 @@ def reset_id

private

def set_attribute_values_from_options options
options.each{|attr, value| self.send("#{attr}=".to_sym, value) }
end
end
def set_attribute_values_from_options options
options.each{|attr, value| self.send("#{attr}=".to_sym, value) }
end
end
12 changes: 7 additions & 5 deletions test/database_events/synchronizer_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
require 'mocha/setup'
require 'time'
require 'active_support/time'
require 'byebug'

require_relative '../../lib/clockwork'
require_relative '../../lib/clockwork/database_events'
Expand Down Expand Up @@ -164,7 +165,7 @@ def log(msg); end # silence log output
end

describe "when #name is defined" do
it 'runs daily event with at from databse only once' do
it 'runs daily event with at from database only once' do
DatabaseEventModel.create(:frequency => 1.day, :at => next_minute(@now).strftime('%H:%M'))
setup_sync(model: DatabaseEventModel, :every => @sync_frequency, :events_run => @events_run)

Expand All @@ -176,7 +177,7 @@ def log(msg); end # silence log output
end

describe "when #name is not defined" do
it 'runs daily event with at from databse only once' do
it 'runs daily event with at from database only once' do
DatabaseEventModelWithoutName.create(:frequency => 1.day, :at => next_minute(next_minute(@now)).strftime('%H:%M'))
setup_sync(model: DatabaseEventModelWithoutName, :every => @sync_frequency, :events_run => @events_run)

Expand Down Expand Up @@ -221,12 +222,13 @@ def log(msg); end # silence log output
end

it 'runs event only once within the model frequency period' do
# creates one immediately, and another in 5 minutes.
DatabaseEventModel.create(:frequency => 5.minutes)
setup_sync(model: DatabaseEventModel, :every => 1.minute, :events_run => @events_run)
# We will let 9 minutes pass, so the model will have been created 2x only.
tick_at(@now, :and_every_second_for => 9.minutes)

tick_at(@now, :and_every_second_for => 5.minutes)

assert_equal 1, @events_run.length
assert_equal 2, @events_run.length
end
end

Expand Down
18 changes: 10 additions & 8 deletions test/database_events/test_helpers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,22 +33,23 @@ def normalize_time t
t.is_a?(String) ? Time.parse(t) : t
end


class DatabaseEventModel
include ActiveRecordFake
attr_accessor :name, :frequency, :at, :tz
attr_writer :name
attr_accessor :frequency, :at, :tz

def name
@name || "#{self.class}:#{id}"
@name ||= "#{self.class}:#{id}"
end
end

class DatabaseEventModel2
include ActiveRecordFake
attr_accessor :name, :frequency, :at, :tz
attr_writer :name
attr_accessor :frequency, :at, :tz

def name
@name || "#{self.class}:#{id}"
@name ||= "#{self.class}:#{id}"
end
end

Expand All @@ -59,13 +60,14 @@ class DatabaseEventModelWithoutName

class DatabaseEventModelWithIf
include ActiveRecordFake
attr_accessor :name, :frequency, :at, :tz, :if_state
attr_writer :name
attr_accessor :frequency, :at, :tz, :if_state

def name
@name || "#{self.class}:#{id}"
@name ||= "#{self.class}:#{id}"
end

def if?(time)
@if_state
end
end
end
2 changes: 1 addition & 1 deletion test/signal_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class SignalTest < Test::Unit::TestCase
assert_equal 'done', File.read(LOGFILE)
end

test 'should forcely shutdown with SIGINT' do
test 'should force shutdown with SIGINT' do
Process.kill(:INT, @pid)
sleep 0.2
assert_equal 'start', File.read(LOGFILE)
Expand Down