pgbus 0.3.5 → 0.3.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a25921e6a7a0ac72023501978b6dec0b38645a18b45cece73bf15ddbc655dae8
4
- data.tar.gz: 810980a58f382aad948b660a9102cdb6ea3a3af57c3768f1205c3582b0705003
3
+ metadata.gz: bd4586e94a76eaf20987039101a038af4e64a9d3bcfd5d68b5b2ef984f3459f3
4
+ data.tar.gz: 98f2e88891c3e7f00963d697d4fc135271a61eccef04aa89dbfb40e0d568b240
5
5
  SHA512:
6
- metadata.gz: 597fbc986e88b2c37339156de5f21a576d50f45bab5f72343dc3eaed02b730d35dce777285f65b63f3264f4a91d76fa0b7a001635a6c103b08ef95454c6dc71f
7
- data.tar.gz: 2a305826eb3b9b0618e64c99e0724c2daf020047933e83d231a35866d8e8b1e334a45c45c03a7fbef577b8dd2243686dc4e351595a671a8d8cd1a63f940602ed
6
+ metadata.gz: f2df68ef64f8b4ac37dfe509c800688c51e811910855f69807c28a5e3777d0eff10dc989ea4e0180b17ee9feada2549a6faa182052c2bbf88be225ccfa7a45d2
7
+ data.tar.gz: 4890d5ab0a55df38ba8d74bb704c00a6d82a4abe17784600e19615288b6dfebec50ac07ac7a89a0cdffa95c85299b795071d4a5dbcc9d351bac076a5baca8bc9
@@ -11,7 +11,10 @@ module Pgbus
11
11
  end
12
12
 
13
13
  def due_tasks(time = Time.current)
14
- tasks.select { |task| task_due?(task, time) }
14
+ tasks.filter_map do |task|
15
+ run_at = canonical_run_at(task, time)
16
+ [task, run_at] if run_at
17
+ end
15
18
  end
16
19
 
17
20
  def enqueue_task(task, run_at:)
@@ -34,6 +37,12 @@ module Pgbus
34
37
  end
35
38
  end
36
39
  rescue AlreadyRecorded
40
+ # AlreadyRecorded means this (task_key, run_at) was already enqueued.
41
+ # If we acquired a NEW lock (prior lock was already released because the
42
+ # job completed), release it — no message will use it. If we didn't
43
+ # acquire a lock (nil or :already_locked), there's nothing to release.
44
+ # In either case, we are NOT opening a race window because the job for
45
+ # this run_at already ran or is running.
37
46
  release_uniqueness_lock(acquired_key)
38
47
  Pgbus.logger.debug { "[Pgbus] Recurring task #{task.key} already enqueued for #{run_at.iso8601}" }
39
48
  rescue StandardError
@@ -75,23 +84,31 @@ module Pgbus
75
84
  end
76
85
  end
77
86
 
78
- def task_due?(task, time)
79
- # A task is due when its most recent cron occurrence (previous_time)
80
- # falls within the current tick window. We also check match? to
81
- # handle the exact-boundary case where time == cron time.
87
+ # Returns the canonical run_at time if the task is due, or nil if not.
88
+ # This ensures a consistent run_at regardless of which tick detects
89
+ # the cron occurrence fixing a bug where match?(t) at the exact
90
+ # boundary returns previous_time=T-1, while a tick 1s later gets
91
+ # previous_time=T, producing different run_at values for the same
92
+ # cron occurrence and bypassing RecurringExecution deduplication.
93
+ def canonical_run_at(task, time)
82
94
  cron = task.parsed_schedule
83
- return false unless cron
84
-
85
- # Check if `time` itself matches the cron (exact boundary hit)
86
- return true if cron.match?(time)
95
+ return nil unless cron
96
+
97
+ # Exact boundary hit: cron.match?(time) is true.
98
+ # previous_time returns the PRIOR occurrence here, but the cron
99
+ # time that fired is `time` itself (truncated to the minute).
100
+ if cron.match?(time)
101
+ # Fugit next_time from 1 second before gives us the current cron time
102
+ return cron.next_time(time - 1).to_t
103
+ end
87
104
 
88
- # Check if the previous occurrence was recent enough that we should
89
- # still fire it (handles the case where we tick slightly after the
90
- # cron time). The window is the scheduler interval.
105
+ # Within the scheduler interval window after the cron time.
91
106
  prev = task.previous_time(time)
92
- return false unless prev
107
+ return nil unless prev
93
108
 
94
- (time - prev) <= @config.recurring_schedule_interval
109
+ return prev if (time - prev) <= @config.recurring_schedule_interval
110
+
111
+ nil
95
112
  end
96
113
 
97
114
  def resolve_queue(task)
@@ -40,10 +40,7 @@ module Pgbus
40
40
  end
41
41
 
42
42
  def tick(now)
43
- schedule.due_tasks(now).each do |task|
44
- run_at = task.previous_time(now)
45
- next unless run_at
46
-
43
+ schedule.due_tasks(now).each do |task, run_at|
47
44
  schedule.enqueue_task(task, run_at: run_at)
48
45
  @last_runs[task.key] = now
49
46
  rescue StandardError => e
data/lib/pgbus/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Pgbus
4
- VERSION = "0.3.5"
4
+ VERSION = "0.3.6"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pgbus
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.5
4
+ version: 0.3.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mikael Henriksson