class Gnomon

Gnomon Class: Root Class for Gnomon.

Gnomon Class

Constants

DEFAULT_GRANULARITY

Defaults

VERSION

Version

Public Class Methods

new(granularity = DEFAULT_GRANULARITY) click to toggle source

Construct: Creates a new Gnomon instance. @param [Float] granularity The desired resolution of the event queue, in seconds

# File lib/gnomon.rb, line 25
def initialize granularity = DEFAULT_GRANULARITY

        # Set Granularity
        @granularity = granularity

        # Create Event Queue
        @equeue = []

        # Create Event Schedule
        @esched = []

        # Create Lock
        @lock = Mutex.new
end

Public Instance Methods

deschedule(id, keep_running = false) click to toggle source

De-schedule: Removes one or more previously-scheduled events from the scheduler. @param [Object] id The ID of the event(s) to remove (all events with this ID will be removed) @param [Object] keep_running When true, the next trigger is maintained

# File lib/gnomon.rb, line 106
def deschedule id, keep_running = false

        # Synchronize
        @lock.synchronize do

                # De-schedule Event
                @esched.delete_if { |e| e[:id] == id }

                # De-queue any next run
                @equeue.delete_if { |e| e[:event][:id] == id } unless keep_running
                @equeue.each { |e| e[:event][:last_run] = true if e[:event][:id] == id } if keep_running
        end
end
schedule(id, mode, mode_options, timespec, *args, &block) click to toggle source

Schedule Event: Schedules a generic event. @param [Object] id An ID for later de-scheduling of this event @param [Symbol] mode The mode of scheduling - can be any of [ :at, :in, :every ] @param [Hash] mode_options Mode-specific options hash - See documentation for desired mode @param [Object] timespec Mode-specific time-specification for 'when' to trigger the event @param [Object] args Arguments to be passed as-is to the event's block upon execution @param [Object] block A block to be executed upon event trigger

# File lib/gnomon.rb, line 48
def schedule id, mode, mode_options, timespec, *args, &block

        # Synchronize
        @lock.synchronize do

                # Create Event
                e =  {
                        id: id,
                        ts: timespec,
                        mode: mode,
                        mopt: mode_options,
                        args: args,
                        blck: block
                }

                # Register Event Scheduling
                @esched << e

                # Enqueue Next Run
                enqueue_next_run e
        end
end
schedule_at(id, date_time, *args, &block) click to toggle source

Schedule Event at a given date/time: Shortcut to schedule an event to be triggered once at a specific date/time. @param [Object] id @param [String] date_time A date / time string @param [Object] args @param [Object] block

# File lib/gnomon.rb, line 77
def schedule_at id, date_time, *args, &block
        schedule id, :at, {}, date_time, *args, &block
end
schedule_every(id, interval, async, *args, &block) click to toggle source

Schedule Event at a given interval (seconds): Shortcut to schedule an event to be triggered periodically at a given time interval. @param [Object] id @param [Float] interval @param [boolean] async When true, schedule the next trigger before actually running the event's block - otherwise, schedule the next trigger only once the event block completes @param [Object] args @param [Object] block

# File lib/gnomon.rb, line 98
def schedule_every id, interval, async, *args, &block
        schedule id, :every, { async: async }, interval, *args, &block
end
schedule_in(id, time, *args, &block) click to toggle source

Schedule Event in a given number of seconds: Shortcut to schedule an event to be triggered once after a given amount of time. @param [Object] id @param [Float] time @param [Object] args @param [Object] block

# File lib/gnomon.rb, line 87
def schedule_in id, time, *args, &block
        schedule id, :in, {}, time, *args, &block
end

Private Instance Methods

enqueue_next_run(event) click to toggle source

Enqueue Next Run: Registers the next run for a given event into the event queue. @param [Hash] event

# File lib/gnomon.rb, line 126
def enqueue_next_run event

        # Determine Next Run
        next_run = next_run event[:mode], event[:ts]

        # Determine position in Event Queue
        pos = @equeue.index { |p| p[:next_run] >= next_run } || @equeue.size

        # Insert
        @equeue.insert pos, { next_run: next_run, event: event }
end
next_run(mode, ts) click to toggle source

Determine Next Run: Determines when to trigger the next run for a given event. @param [Symbol] mode @param [Object] ts @return [Float] A floating-point timestamp representing the time at which to trigger the next run

# File lib/gnomon.rb, line 143
def next_run mode, ts
        case mode
                when :at
                        DateTime.parse(ts).to_time.to_f
                when :in, :every
                        Time.at(Time.now.to_f + ts.to_f).to_f
                else
                        raise "Unknown scheduling mode [#{mode}]"
        end
end
run() click to toggle source

Run: Executes the main loop.

# File lib/gnomon.rb, line 156
def run
        update until @stop
end
trigger(event) click to toggle source

Trigger Event: Triggers an event, executing its block and re-scheduling the next run when appropriate. @param [Hash] event

# File lib/gnomon.rb, line 174
def trigger event

        # Spawn Thread around Event's Block
        Thread.new do

                # De-schedule non-periodic events
                @esched.delete event unless event[:mode] == :every
                @equeue.delete_if { |e| e[:event] == event } unless event[:mode] == :every

                # Enqueue next run BEFORE calling block for asynchronous periodic events
                enqueue_next_run event if event[:mode] == :every && event[:mopt][:async] && !(event[:last_run])

                # Pass Event Args to Event Block
                event[:blck].call(*(event[:args]))

                # Enqueue next run AFTER calling block for synchronous periodic events
                enqueue_next_run event if event[:mode] == :every && !(event[:mopt][:async]) && !(event[:last_run])
        end
end
update() click to toggle source

Update: Updates Gnomon's internal states.

# File lib/gnomon.rb, line 162
def update

        # Synchronize { Trigger Next Event in Queue }
        @lock.synchronize { trigger @equeue.shift[:event] while @equeue.first && @equeue.first[:next_run] <= Time.now.to_f }

        # Sleep
        sleep @granularity
end