Module: Async::Loop

Defined in:
lib/async/loop.rb

Class Method Summary collapse

Class Method Details

.periodic(interval: 60, &block) ⇒ Object

Execute a block repeatedly with a fixed delay between executions.

Unlike quantized, this method waits for the specified interval after each execution completes. This means the actual time between the start of successive executions will be interval + execution_time.

If an error occurs during block execution, it is logged and the loop continues.

Examples:

Run every 5 seconds (plus execution time):

Async::Loop.periodic(interval: 5) do
	process_queue
end


72
73
74
75
76
77
78
79
80
81
82
# File 'lib/async/loop.rb', line 72

def self.periodic(interval: 60, &block)
	while true
		begin
			yield
		rescue => error
			Console.error(self, "Loop error:", error)
		end
		
		sleep(interval)
	end
end

.quantized(interval: 60, &block) ⇒ Object

Execute a block repeatedly at quantized (time-aligned) intervals.

The alignment is computed modulo the current clock time in seconds. For example, with interval: 60, executions will occur at 00:00, 01:00, 02:00, etc., regardless of when the loop is started. With interval: 300 (5 minutes), executions align to 00:00, 00:05, 00:10, etc.

This is particularly useful for tasks that should run at predictable wall-clock times, such as metrics collection, periodic cleanup, or scheduled jobs that need to align across multiple processes.

If an error occurs during block execution, it is logged and the loop continues.

Examples:

Run every minute at :00 seconds:

Async::Loop.quantized(interval: 60) do
	puts "Current time: #{Time.now}"
end

Run every 5 minutes aligned to the hour:

Async::Loop.quantized(interval: 300) do
	collect_metrics
end


38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/async/loop.rb', line 38

def self.quantized(interval: 60, &block)
	while true
		# Compute the wait time to the next interval:
		wait = interval - (Time.now.to_f % interval)
		if wait.positive?
			# Sleep until the next interval boundary:
			sleep(wait)
		end
		
		begin
			yield
		rescue => error
			Console.error(self, "Loop error:", error)
		end
	end
end