Class: Ztimer
- Inherits:
-
Object
- Object
- Ztimer
- Defined in:
- lib/ztimer.rb,
lib/ztimer/slot.rb,
lib/ztimer/version.rb,
lib/ztimer/watcher.rb,
lib/ztimer/sorted_store.rb
Overview
Implements a timer which allows to execute a block with a delay, recurrently or asynchronously.
Defined Under Namespace
Classes: Slot, SortedStore, Watcher
Constant Summary collapse
- VERSION =
'1.0.0'
Instance Attribute Summary collapse
-
#concurrency ⇒ Object
Returns the value of attribute concurrency.
-
#count ⇒ Object
readonly
Returns the value of attribute count.
-
#queue ⇒ Object
readonly
Returns the value of attribute queue.
-
#running ⇒ Object
readonly
Returns the value of attribute running.
-
#watcher ⇒ Object
readonly
Returns the value of attribute watcher.
Class Method Summary collapse
Instance Method Summary collapse
-
#after(milliseconds, &callback) ⇒ Object
Execute the code block after the specified delay.
-
#async(&callback) ⇒ Object
Execute the code block asyncrhonously right now.
-
#at(datetime, &callback) ⇒ Object
Execute the code block at a specific datetime.
- #daily(days, offset: 0, &callback) ⇒ Object
- #day_of_week(day, &callback) ⇒ Object
- #days_of_week(*args, &callback) ⇒ Object
-
#every(milliseconds, start_at: nil, &callback) ⇒ Object
Execute the code block every N milliseconds.
-
#hourly(hours, offset: 0, &callback) ⇒ Object
Run ztimer every N hours, starting at the nearest time slot (ex. hourly(2) will run at hour 0, 2, 4, 6, etc.).
-
#initialize(concurrency: 20) ⇒ Ztimer
constructor
A new instance of Ztimer.
- #jobs_count ⇒ Object
-
#minutely(minutes, offset: 0, &callback) ⇒ Object
Run ztimer every N minutes, starting at the nearest time slot (ex. minutely(2) will run at minute 0, 2, 4, 6, etc.).
-
#secondly(seconds, offset: 0, &callback) ⇒ Object
Run ztimer every N seconds, starting with the nearest time slot (ex. secondly(5) will run at second 0, 5, 10, 15, etc.).
- #stats ⇒ Object
Constructor Details
#initialize(concurrency: 20) ⇒ Ztimer
Returns a new instance of Ztimer.
14 15 16 17 18 19 20 21 22 |
# File 'lib/ztimer.rb', line 14 def initialize(concurrency: 20) @concurrency = concurrency @watcher = Ztimer::Watcher.new { |slot| execute(slot) } @workers_lock = Mutex.new @count_lock = Mutex.new @queue = Queue.new @running = 0 @count = 0 end |
Instance Attribute Details
#concurrency ⇒ Object
Returns the value of attribute concurrency.
12 13 14 |
# File 'lib/ztimer.rb', line 12 def concurrency @concurrency end |
#count ⇒ Object (readonly)
Returns the value of attribute count.
12 13 14 |
# File 'lib/ztimer.rb', line 12 def count @count end |
#queue ⇒ Object (readonly)
Returns the value of attribute queue.
12 13 14 |
# File 'lib/ztimer.rb', line 12 def queue @queue end |
#running ⇒ Object (readonly)
Returns the value of attribute running.
12 13 14 |
# File 'lib/ztimer.rb', line 12 def running @running end |
#watcher ⇒ Object (readonly)
Returns the value of attribute watcher.
12 13 14 |
# File 'lib/ztimer.rb', line 12 def watcher @watcher end |
Class Method Details
Instance Method Details
#after(milliseconds, &callback) ⇒ Object
Execute the code block after the specified delay
36 37 38 39 40 41 42 43 44 |
# File 'lib/ztimer.rb', line 36 def after(milliseconds, &callback) enqueued_at = utc_microseconds expires_at = enqueued_at + milliseconds * 1000 slot = Slot.new(enqueued_at, expires_at, -1, &callback) add(slot) slot end |
#async(&callback) ⇒ Object
Execute the code block asyncrhonously right now
25 26 27 28 29 30 31 32 33 |
# File 'lib/ztimer.rb', line 25 def async(&callback) enqueued_at = utc_microseconds slot = Slot.new(enqueued_at, enqueued_at, -1, &callback) incr_counter! execute(slot) slot end |
#at(datetime, &callback) ⇒ Object
Execute the code block at a specific datetime
47 48 49 50 51 52 53 54 |
# File 'lib/ztimer.rb', line 47 def at(datetime, &callback) enqueued_at = datetime.to_f * 1_000_000 slot = Slot.new(enqueued_at, enqueued_at, -1, &callback) add(slot) slot end |
#daily(days, offset: 0, &callback) ⇒ Object
92 93 94 95 96 |
# File 'lib/ztimer.rb', line 92 def daily(days, offset: 0, &callback) raise ArgumentError, "Days number should be > 0: #{days.inspect}" if days.to_f <= 0 hourly(days.to_f * 24, offset: offset.to_f * 24, &callback) end |
#day_of_week(day, &callback) ⇒ Object
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 |
# File 'lib/ztimer.rb', line 98 def day_of_week(day, &callback) days = %w[sun mon tue thu wen fri sat] current_day = Time.now.wday index = day.to_i if day.is_a?(String) # Find day number by day name index = days.index { |day_name| day.strip.downcase == day_name } raise ArgumentError, "Invalid week day: #{day.inspect}" if index.nil? elsif index.negative? || index > 6 raise ArgumentError, "Invalid week day: #{day.inspect}" end offset = 0 offset = (current_day > index ? index - current_day : current_day - index) if current_day != index daily(7, offset: offset, &callback) end |
#days_of_week(*args, &callback) ⇒ Object
117 118 119 |
# File 'lib/ztimer.rb', line 117 def days_of_week(*args, &callback) args.map { |day| day_of_week(day, &callback) } end |
#every(milliseconds, start_at: nil, &callback) ⇒ Object
Execute the code block every N milliseconds. When :start_at is specified, the first execution will start at specified date/time
58 59 60 61 62 63 64 65 66 |
# File 'lib/ztimer.rb', line 58 def every(milliseconds, start_at: nil, &callback) enqueued_at = start_at ? start_at.to_f * 1_000_000 : utc_microseconds expires_at = enqueued_at + milliseconds * 1000 slot = Slot.new(enqueued_at, expires_at, milliseconds * 1000, &callback) add(slot) slot end |
#hourly(hours, offset: 0, &callback) ⇒ Object
Run ztimer every N hours, starting at the nearest time slot (ex. hourly(2) will run at hour 0, 2, 4, 6, etc.)
88 89 90 |
# File 'lib/ztimer.rb', line 88 def hourly(hours, offset: 0, &callback) minutely(hours.to_f * 60, offset: offset.to_f * 60, &callback) end |
#jobs_count ⇒ Object
121 122 123 |
# File 'lib/ztimer.rb', line 121 def jobs_count @watcher.jobs end |
#minutely(minutes, offset: 0, &callback) ⇒ Object
Run ztimer every N minutes, starting at the nearest time slot (ex. minutely(2) will run at minute 0, 2, 4, 6, etc.)
83 84 85 |
# File 'lib/ztimer.rb', line 83 def minutely(minutes, offset: 0, &callback) secondly(minutes.to_f * 60, offset: offset.to_f * 60, &callback) end |
#secondly(seconds, offset: 0, &callback) ⇒ Object
Run ztimer every N seconds, starting with the nearest time slot (ex. secondly(5) will run at second 0, 5, 10, 15, etc.)
70 71 72 73 74 75 76 77 78 79 80 |
# File 'lib/ztimer.rb', line 70 def secondly(seconds, offset: 0, &callback) start_time = utc_microseconds milliseconds = (seconds.to_f * 1000).to_i enqueued_at = start_time - (start_time % (milliseconds * 1000)) + offset * 1_000_000 expires_at = enqueued_at + milliseconds * 1000 slot = Slot.new(enqueued_at, expires_at, milliseconds * 1000, &callback) add(slot) slot end |
#stats ⇒ Object
132 133 134 135 136 137 138 139 |
# File 'lib/ztimer.rb', line 132 def stats { running: @running, scheduled: @watcher.jobs, executing: @queue.size, total: @count } end |