pgbus 0.3.1 → 0.3.3

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.
@@ -1,13 +1,6 @@
1
1
  ---
2
2
  ja:
3
3
  pgbus:
4
- dialogs:
5
- cancel: キャンセル
6
- confirm: 確認
7
- confirm_title: よろしいですか?
8
- delete: 削除
9
- delete_title: 削除
10
- ok: OK
11
4
  dashboard:
12
5
  processes_table:
13
6
  empty: 実行中のプロセスはありません
@@ -90,6 +83,13 @@ ja:
90
83
  payload: ペイロード
91
84
  retry: 再試行
92
85
  title: 'DLQメッセージ #%{id}'
86
+ dialogs:
87
+ cancel: キャンセル
88
+ confirm: 確認
89
+ confirm_title: よろしいですか?
90
+ delete: 削除
91
+ delete_title: 削除
92
+ ok: OK
93
93
  events:
94
94
  index:
95
95
  processed_empty: まだ処理されたイベントはありません
@@ -157,6 +157,10 @@ ja:
157
157
  jobs:
158
158
  enqueued_table:
159
159
  arguments: 引数
160
+ discard: 破棄
161
+ discard_all: すべて破棄
162
+ discard_all_confirm: キュー内のすべてのジョブを破棄し、ロックを解放しますか?この操作は元に戻せません。
163
+ discard_confirm: このメッセージを破棄しますか?
160
164
  empty: キューに入っているジョブはありません
161
165
  full_json_payload: 完全なJSONペイロード
162
166
  headers:
@@ -176,13 +180,9 @@ ja:
176
180
  scheduled: スケジュール済み:
177
181
  timezone: タイムゾーン:
178
182
  visible_at: 表示可能日時:
179
- title: キューに入れられたジョブ
180
- discard: 破棄
181
- discard_confirm: このメッセージを破棄しますか?
182
- discard_all: すべて破棄
183
- discard_all_confirm: キュー内のすべてのジョブを破棄し、ロックを解放しますか?この操作は元に戻せません。
184
183
  retry: リトライ
185
184
  retry_confirm: 可視性タイムアウトをリセットしてリトライしますか?
185
+ title: キューに入れられたジョブ
186
186
  failed_table:
187
187
  discard: 破棄
188
188
  discard_confirm: このジョブを破棄しますか?
@@ -282,9 +282,13 @@ ja:
282
282
  pid: PID
283
283
  status: ステータス
284
284
  queues:
285
+ destroy:
286
+ success: キュー %{name} を削除しました。
285
287
  index:
286
288
  title: キュー
287
289
  queues_list:
290
+ delete: 削除
291
+ delete_confirm: キュー %{name} を完全に削除しますか?この操作は取り消せません。
288
292
  empty: キューが見つかりません
289
293
  headers:
290
294
  actions: アクション
@@ -294,16 +298,12 @@ ja:
294
298
  queue: キュー
295
299
  total_ever: 合計数
296
300
  visible: 表示中
297
- delete: 削除
298
- delete_confirm: キュー %{name} を完全に削除しますか?この操作は取り消せません。
299
301
  pause: 一時停止
300
302
  pause_confirm: "%{name} の処理を一時停止しますか?"
301
303
  paused: 一時停止中
302
304
  purge: パージ
303
305
  purge_confirm: "%{name} からすべてのメッセージを削除しますか?"
304
306
  resume: 再開
305
- destroy:
306
- success: キュー %{name} を削除しました。
307
307
  show:
308
308
  delete_confirm: このキューを完全に削除しますか?この操作は取り消せません。
309
309
  delete_queue: キューを削除
@@ -1,13 +1,6 @@
1
1
  ---
2
2
  nb:
3
3
  pgbus:
4
- dialogs:
5
- cancel: Avbryt
6
- confirm: Bekreft
7
- confirm_title: Er du sikker?
8
- delete: Slett
9
- delete_title: Slett
10
- ok: OK
11
4
  dashboard:
12
5
  processes_table:
13
6
  empty: Ingen prosesser kjører
@@ -90,6 +83,13 @@ nb:
90
83
  payload: Innhold
91
84
  retry: Prøv igjen
92
85
  title: 'DLQ-melding #%{id}'
86
+ dialogs:
87
+ cancel: Avbryt
88
+ confirm: Bekreft
89
+ confirm_title: Er du sikker?
90
+ delete: Slett
91
+ delete_title: Slett
92
+ ok: OK
93
93
  events:
94
94
  index:
95
95
  processed_empty: Ingen hendelser behandlet ennå
@@ -157,6 +157,10 @@ nb:
157
157
  jobs:
158
158
  enqueued_table:
159
159
  arguments: Argumenter
160
+ discard: Forkast
161
+ discard_all: Forkast alle
162
+ discard_all_confirm: Forkast alle køede jobber og frigi låsene? Dette kan ikke angres.
163
+ discard_confirm: Forkaste denne meldingen?
160
164
  empty: Ingen kølagte jobber
161
165
  full_json_payload: Full JSON-payload
162
166
  headers:
@@ -176,13 +180,9 @@ nb:
176
180
  scheduled: 'Planlagt:'
177
181
  timezone: 'Tidssone:'
178
182
  visible_at: 'Synlig fra:'
179
- title: Kølagte jobber
180
- discard: Forkast
181
- discard_confirm: Forkaste denne meldingen?
182
- discard_all: Forkast alle
183
- discard_all_confirm: Forkast alle køede jobber og frigi låsene? Dette kan ikke angres.
184
183
  retry: Prøv igjen
185
184
  retry_confirm: Tilbakestill synlighetstidsavbrudd og prøv igjen?
185
+ title: Kølagte jobber
186
186
  failed_table:
187
187
  discard: Forkast
188
188
  discard_confirm: Forkast denne jobben?
@@ -282,9 +282,13 @@ nb:
282
282
  pid: PID
283
283
  status: Status
284
284
  queues:
285
+ destroy:
286
+ success: Køen %{name} slettet.
285
287
  index:
286
288
  title: Køer
287
289
  queues_list:
290
+ delete: Slett
291
+ delete_confirm: Slette køen %{name} permanent? Dette kan ikke angres.
288
292
  empty: Ingen køer funnet
289
293
  headers:
290
294
  actions: Handlinger
@@ -294,16 +298,12 @@ nb:
294
298
  queue: Kø
295
299
  total_ever: Totalt noensinne
296
300
  visible: Synlig
297
- delete: Slett
298
- delete_confirm: Slette køen %{name} permanent? Dette kan ikke angres.
299
301
  pause: Pause
300
302
  pause_confirm: Pause behandling for %{name}?
301
303
  paused: Pauset
302
304
  purge: Rens
303
305
  purge_confirm: Rens alle meldinger fra %{name}?
304
306
  resume: Gjenoppta
305
- destroy:
306
- success: Køen %{name} slettet.
307
307
  show:
308
308
  delete_confirm: Slette denne køen permanent? Dette kan ikke angres.
309
309
  delete_queue: Slett kø
@@ -1,13 +1,6 @@
1
1
  ---
2
2
  nl:
3
3
  pgbus:
4
- dialogs:
5
- cancel: Annuleren
6
- confirm: Bevestigen
7
- confirm_title: Weet u het zeker?
8
- delete: Verwijderen
9
- delete_title: Verwijderen
10
- ok: OK
11
4
  dashboard:
12
5
  processes_table:
13
6
  empty: Geen processen actief
@@ -90,6 +83,13 @@ nl:
90
83
  payload: Inhoud
91
84
  retry: Opnieuw proberen
92
85
  title: 'DLQ Bericht #%{id}'
86
+ dialogs:
87
+ cancel: Annuleren
88
+ confirm: Bevestigen
89
+ confirm_title: Weet u het zeker?
90
+ delete: Verwijderen
91
+ delete_title: Verwijderen
92
+ ok: OK
93
93
  events:
94
94
  index:
95
95
  processed_empty: Nog geen gebeurtenissen verwerkt
@@ -157,6 +157,10 @@ nl:
157
157
  jobs:
158
158
  enqueued_table:
159
159
  arguments: Argumenten
160
+ discard: Verwerpen
161
+ discard_all: Alles verwijderen
162
+ discard_all_confirm: Alle taken in de wachtrij verwijderen en hun vergrendelingen vrijgeven? Dit kan niet ongedaan worden gemaakt.
163
+ discard_confirm: Dit bericht verwerpen?
160
164
  empty: Geen in de wachtrij geplaatste taken
161
165
  full_json_payload: Volledige JSON payload
162
166
  headers:
@@ -176,13 +180,9 @@ nl:
176
180
  scheduled: 'Gepland:'
177
181
  timezone: 'Tijdzone:'
178
182
  visible_at: 'Zichtbaar op:'
179
- title: Taken in de wachtrij
180
- discard: Verwerpen
181
- discard_confirm: Dit bericht verwerpen?
182
- discard_all: Alles verwijderen
183
- discard_all_confirm: Alle taken in de wachtrij verwijderen en hun vergrendelingen vrijgeven? Dit kan niet ongedaan worden gemaakt.
184
183
  retry: Opnieuw proberen
185
184
  retry_confirm: Zichtbaarheidstimeout resetten en opnieuw proberen?
185
+ title: Taken in de wachtrij
186
186
  failed_table:
187
187
  discard: Verwijderen
188
188
  discard_confirm: Deze taak verwijderen?
@@ -282,9 +282,13 @@ nl:
282
282
  pid: PID
283
283
  status: Status
284
284
  queues:
285
+ destroy:
286
+ success: Wachtrij %{name} verwijderd.
285
287
  index:
286
288
  title: Wachtrijen
287
289
  queues_list:
290
+ delete: Verwijderen
291
+ delete_confirm: Wachtrij %{name} permanent verwijderen? Dit kan niet ongedaan worden gemaakt.
288
292
  empty: Geen wachtrijen gevonden
289
293
  headers:
290
294
  actions: Acties
@@ -294,16 +298,12 @@ nl:
294
298
  queue: Wachtrij
295
299
  total_ever: Totaal ooit
296
300
  visible: Zichtbaar
297
- delete: Verwijderen
298
- delete_confirm: Wachtrij %{name} permanent verwijderen? Dit kan niet ongedaan worden gemaakt.
299
301
  pause: Pauzeren
300
302
  pause_confirm: Verwerking pauzeren voor %{name}?
301
303
  paused: Gepauzeerd
302
304
  purge: Opschonen
303
305
  purge_confirm: Alle berichten verwijderen uit %{name}?
304
306
  resume: Hervatten
305
- destroy:
306
- success: Wachtrij %{name} verwijderd.
307
307
  show:
308
308
  delete_confirm: Deze wachtrij permanent verwijderen? Dit kan niet ongedaan worden gemaakt.
309
309
  delete_queue: Wachtrij verwijderen
@@ -1,13 +1,6 @@
1
1
  ---
2
2
  pt:
3
3
  pgbus:
4
- dialogs:
5
- cancel: Cancelar
6
- confirm: Confirmar
7
- confirm_title: Tem certeza?
8
- delete: Excluir
9
- delete_title: Excluir
10
- ok: OK
11
4
  dashboard:
12
5
  processes_table:
13
6
  empty: Nenhum processo em execução
@@ -90,6 +83,13 @@ pt:
90
83
  payload: Carga útil
91
84
  retry: Tentar novamente
92
85
  title: 'Mensagem DLQ #%{id}'
86
+ dialogs:
87
+ cancel: Cancelar
88
+ confirm: Confirmar
89
+ confirm_title: Tem certeza?
90
+ delete: Excluir
91
+ delete_title: Excluir
92
+ ok: OK
93
93
  events:
94
94
  index:
95
95
  processed_empty: Nenhum evento processado ainda
@@ -157,6 +157,10 @@ pt:
157
157
  jobs:
158
158
  enqueued_table:
159
159
  arguments: Argumentos
160
+ discard: Descartar
161
+ discard_all: Descartar todos
162
+ discard_all_confirm: Descartar todos os trabalhos na fila e liberar seus bloqueios? Esta ação não pode ser desfeita.
163
+ discard_confirm: Descartar esta mensagem?
160
164
  empty: Nenhum trabalho enfileirado
161
165
  full_json_payload: Carga JSON completa
162
166
  headers:
@@ -176,13 +180,9 @@ pt:
176
180
  scheduled: 'Agendado:'
177
181
  timezone: 'Fuso horário:'
178
182
  visible_at: 'Visível em:'
179
- title: Trabalhos Enfileirados
180
- discard: Descartar
181
- discard_confirm: Descartar esta mensagem?
182
- discard_all: Descartar todos
183
- discard_all_confirm: Descartar todos os trabalhos na fila e liberar seus bloqueios? Esta ação não pode ser desfeita.
184
183
  retry: Tentar novamente
185
184
  retry_confirm: Redefinir tempo de visibilidade e tentar novamente?
185
+ title: Trabalhos Enfileirados
186
186
  failed_table:
187
187
  discard: Descartar
188
188
  discard_confirm: Descartar este trabalho?
@@ -282,9 +282,13 @@ pt:
282
282
  pid: PID
283
283
  status: Status
284
284
  queues:
285
+ destroy:
286
+ success: Fila %{name} excluída.
285
287
  index:
286
288
  title: Filas
287
289
  queues_list:
290
+ delete: Excluir
291
+ delete_confirm: Excluir permanentemente a fila %{name}? Esta ação não pode ser desfeita.
288
292
  empty: Nenhuma fila encontrada
289
293
  headers:
290
294
  actions: Ações
@@ -294,16 +298,12 @@ pt:
294
298
  queue: Fila
295
299
  total_ever: Total de todos os tempos
296
300
  visible: Visível
297
- delete: Excluir
298
- delete_confirm: Excluir permanentemente a fila %{name}? Esta ação não pode ser desfeita.
299
301
  pause: Pausar
300
302
  pause_confirm: Pausar processamento por %{name}?
301
303
  paused: Pausado
302
304
  purge: Limpar
303
305
  purge_confirm: Limpar todas as mensagens de %{name}?
304
306
  resume: Retomar
305
- destroy:
306
- success: Fila %{name} excluída.
307
307
  show:
308
308
  delete_confirm: Excluir permanentemente esta fila? Esta ação não pode ser desfeita.
309
309
  delete_queue: Excluir fila
@@ -1,13 +1,6 @@
1
1
  ---
2
2
  sv:
3
3
  pgbus:
4
- dialogs:
5
- cancel: Avbryt
6
- confirm: Bekräfta
7
- confirm_title: Är du säker?
8
- delete: Ta bort
9
- delete_title: Ta bort
10
- ok: OK
11
4
  dashboard:
12
5
  processes_table:
13
6
  empty: Inga processer körs
@@ -90,6 +83,13 @@ sv:
90
83
  payload: Innehåll
91
84
  retry: Försök igen
92
85
  title: 'DLQ-meddelande #%{id}'
86
+ dialogs:
87
+ cancel: Avbryt
88
+ confirm: Bekräfta
89
+ confirm_title: Är du säker?
90
+ delete: Ta bort
91
+ delete_title: Ta bort
92
+ ok: OK
93
93
  events:
94
94
  index:
95
95
  processed_empty: Inga händelser behandlade än
@@ -157,6 +157,10 @@ sv:
157
157
  jobs:
158
158
  enqueued_table:
159
159
  arguments: Argument
160
+ discard: Kassera
161
+ discard_all: Kassera alla
162
+ discard_all_confirm: Kassera alla köade jobb och frigör deras lås? Detta kan inte ångras.
163
+ discard_confirm: Kassera detta meddelande?
160
164
  empty: Inga köade jobb
161
165
  full_json_payload: Fullständig JSON-payload
162
166
  headers:
@@ -176,13 +180,9 @@ sv:
176
180
  scheduled: 'Schemalagt:'
177
181
  timezone: 'Tidszon:'
178
182
  visible_at: 'Synlig vid:'
179
- title: Köade jobb
180
- discard: Kassera
181
- discard_confirm: Kassera detta meddelande?
182
- discard_all: Kassera alla
183
- discard_all_confirm: Kassera alla köade jobb och frigör deras lås? Detta kan inte ångras.
184
183
  retry: Försök igen
185
184
  retry_confirm: Återställ synlighetstimeout och försök igen?
185
+ title: Köade jobb
186
186
  failed_table:
187
187
  discard: Kassera
188
188
  discard_confirm: Kassera detta jobb?
@@ -282,9 +282,13 @@ sv:
282
282
  pid: PID
283
283
  status: Status
284
284
  queues:
285
+ destroy:
286
+ success: Kön %{name} borttagen.
285
287
  index:
286
288
  title: Köer
287
289
  queues_list:
290
+ delete: Ta bort
291
+ delete_confirm: Ta bort kön %{name} permanent? Detta kan inte ångras.
288
292
  empty: Inga köer hittades
289
293
  headers:
290
294
  actions: Åtgärder
@@ -294,16 +298,12 @@ sv:
294
298
  queue: Kö
295
299
  total_ever: Totalt någonsin
296
300
  visible: Synliga
297
- delete: Ta bort
298
- delete_confirm: Ta bort kön %{name} permanent? Detta kan inte ångras.
299
301
  pause: Pausa
300
302
  pause_confirm: Pausa bearbetning för %{name}?
301
303
  paused: Pausad
302
304
  purge: Rensa
303
305
  purge_confirm: Rensa alla meddelanden från %{name}?
304
306
  resume: Återuppta
305
- destroy:
306
- success: Kön %{name} borttagen.
307
307
  show:
308
308
  delete_confirm: Ta bort denna kö permanent? Detta kan inte ångras.
309
309
  delete_queue: Ta bort kö
@@ -23,7 +23,7 @@ module Pgbus
23
23
  payload_hash = Concurrency.inject_metadata(active_job, payload_hash)
24
24
  payload_hash = Uniqueness.inject_metadata(active_job, payload_hash)
25
25
  payload_hash = inject_batch_metadata(payload_hash)
26
- delay = [(timestamp - Time.now.to_f).ceil, 0].max
26
+ delay = [(timestamp - Time.current.to_f).ceil, 0].max
27
27
 
28
28
  return active_job if uniqueness_rejected?(active_job, payload_hash)
29
29
 
@@ -34,7 +34,7 @@ module Pgbus
34
34
  # Jobs with uniqueness must go through individual enqueue to acquire locks
35
35
  unique, bulk = active_jobs.partition { |j| Uniqueness.uniqueness_config(j) }
36
36
  unique.each do |j|
37
- if j.scheduled_at && j.scheduled_at > Time.now
37
+ if scheduled_in_future?(j)
38
38
  enqueue_at(j, j.scheduled_at.to_f)
39
39
  else
40
40
  enqueue(j)
@@ -42,8 +42,9 @@ module Pgbus
42
42
  end
43
43
 
44
44
  bulk.group_by { |j| j.queue_name || Pgbus.configuration.default_queue }.each do |queue, jobs|
45
- enqueue_immediate(queue, jobs.reject { |j| j.scheduled_at && j.scheduled_at > Time.now })
46
- jobs.select { |j| j.scheduled_at && j.scheduled_at > Time.now }.each { |j| enqueue_at(j, j.scheduled_at.to_f) }
45
+ immediate, scheduled = jobs.partition { |j| !scheduled_in_future?(j) }
46
+ enqueue_immediate(queue, immediate)
47
+ scheduled.each { |j| enqueue_at(j, j.scheduled_at.to_f) }
47
48
  end
48
49
 
49
50
  active_jobs.count
@@ -159,6 +160,10 @@ module Pgbus
159
160
  raise
160
161
  end
161
162
 
163
+ def scheduled_in_future?(job)
164
+ job.scheduled_at && job.scheduled_at > Time.current
165
+ end
166
+
162
167
  def enqueue_after_transaction_commit?
163
168
  true
164
169
  end
@@ -118,7 +118,12 @@ module Pgbus
118
118
  enqueued_at_str = message.enqueued_at
119
119
  return unless enqueued_at_str
120
120
 
121
- enqueued_at = Time.parse(enqueued_at_str.to_s)
121
+ str = enqueued_at_str.to_s
122
+ # PGMQ enqueued_at is TIMESTAMPTZ (always UTC internally).
123
+ # If the string lacks an explicit offset, assume UTC to avoid
124
+ # misinterpretation when the system timezone is non-UTC.
125
+ str = "#{str} UTC" unless str.match?(/[+-]\d{2}:?\d{2}\s*$|Z\s*$/i)
126
+ enqueued_at = Time.parse(str)
122
127
  [((Time.now.utc - enqueued_at) * 1000).round, 0].max
123
128
  rescue ArgumentError, TypeError
124
129
  nil
@@ -29,10 +29,10 @@ module Pgbus
29
29
 
30
30
  def paused?(queue_name)
31
31
  cached = @pause_cache[queue_name]
32
- return cached[:paused] if cached && (Time.now - cached[:checked_at]) < @pause_cache_ttl
32
+ return cached[:paused] if cached && (Time.current - cached[:checked_at]) < @pause_cache_ttl
33
33
 
34
34
  paused = check_paused(queue_name)
35
- @pause_cache[queue_name] = { paused: paused, checked_at: Time.now }
35
+ @pause_cache[queue_name] = { paused: paused, checked_at: Time.current }
36
36
  paused
37
37
  end
38
38
 
@@ -13,7 +13,7 @@ module Pgbus
13
13
  queue_name: queue_name,
14
14
  payload: JSON.generate(payload),
15
15
  priority: priority,
16
- expires_at: Time.now.utc + duration
16
+ expires_at: Time.current + duration
17
17
  )
18
18
  end
19
19
 
@@ -45,7 +45,7 @@ module Pgbus
45
45
  # Delete blocked executions that have expired.
46
46
  # Returns the count of deleted rows.
47
47
  def expire_stale
48
- Pgbus::BlockedExecution.expired(Time.now.utc).delete_all
48
+ Pgbus::BlockedExecution.expired(Time.current).delete_all
49
49
  end
50
50
 
51
51
  # Count blocked executions for a given key. Useful for testing/monitoring.
@@ -59,7 +59,7 @@ module Pgbus
59
59
  scheduled_at = payload["scheduled_at"]
60
60
  return default_delay unless scheduled_at
61
61
 
62
- [Time.parse(scheduled_at).to_f - Time.now.to_f, 0].max.ceil
62
+ [Time.parse(scheduled_at).to_f - Time.current.to_f, 0].max.ceil
63
63
  rescue StandardError
64
64
  default_delay
65
65
  end
@@ -7,7 +7,7 @@ module Pgbus
7
7
  # Attempt to acquire a slot in the semaphore for the given key.
8
8
  # Returns :acquired if a slot was available, :blocked if the limit is reached.
9
9
  def acquire(key, max_value, duration)
10
- expires_at = Time.now.utc + duration
10
+ expires_at = Time.current + duration
11
11
  Pgbus::Semaphore.acquire!(key, max_value, expires_at)
12
12
  end
13
13
 
@@ -23,7 +23,7 @@ module Pgbus
23
23
  result = Pgbus::Semaphore.connection.exec_query(
24
24
  "DELETE FROM pgbus_semaphores WHERE expires_at < $1 RETURNING key",
25
25
  "Pgbus Semaphore Expire",
26
- [Time.now.utc]
26
+ [Time.current]
27
27
  )
28
28
  result.rows.map { |row| { "key" => row[0] } }
29
29
  end
@@ -21,15 +21,15 @@ module Pgbus
21
21
  def initialize(config: Pgbus.configuration)
22
22
  @config = config
23
23
  @shutting_down = false
24
- @last_cleanup_at = Time.now
25
- @last_reap_at = Time.now
26
- @last_concurrency_at = Time.now
27
- @last_batch_cleanup_at = Time.now
28
- @last_recurring_cleanup_at = Time.now
29
- @last_archive_compaction_at = Time.now
30
- @last_outbox_cleanup_at = Time.now
31
- @last_job_lock_cleanup_at = Time.now
32
- @last_stats_cleanup_at = Time.now
24
+ @last_cleanup_at = monotonic_now
25
+ @last_reap_at = monotonic_now
26
+ @last_concurrency_at = monotonic_now
27
+ @last_batch_cleanup_at = monotonic_now
28
+ @last_recurring_cleanup_at = monotonic_now
29
+ @last_archive_compaction_at = monotonic_now
30
+ @last_outbox_cleanup_at = monotonic_now
31
+ @last_job_lock_cleanup_at = monotonic_now
32
+ @last_stats_cleanup_at = monotonic_now
33
33
  end
34
34
 
35
35
  def run
@@ -65,7 +65,7 @@ module Pgbus
65
65
  private
66
66
 
67
67
  def run_maintenance
68
- now = Time.now
68
+ now = monotonic_now
69
69
 
70
70
  run_if_due(now, :@last_cleanup_at, CLEANUP_INTERVAL) { cleanup_processed_events }
71
71
  run_if_due(now, :@last_reap_at, REAP_INTERVAL) { reap_stale_processes }
@@ -93,7 +93,7 @@ module Pgbus
93
93
  ttl = config.idempotency_ttl
94
94
  return unless ttl&.positive?
95
95
 
96
- deleted = ProcessedEvent.expired(Time.now.utc - ttl).delete_all
96
+ deleted = ProcessedEvent.expired(Time.current - ttl).delete_all
97
97
  Pgbus.logger.debug { "[Pgbus] Cleaned up #{deleted} expired processed events" } if deleted.positive?
98
98
  rescue StandardError => e
99
99
  Pgbus.logger.warn { "[Pgbus] Idempotency cleanup failed: #{e.message}" }
@@ -101,7 +101,7 @@ module Pgbus
101
101
 
102
102
  def reap_stale_processes
103
103
  threshold = Heartbeat::ALIVE_THRESHOLD
104
- deleted = ProcessEntry.stale(Time.now.utc - threshold).delete_all
104
+ deleted = ProcessEntry.stale(Time.current - threshold).delete_all
105
105
  Pgbus.logger.info { "[Pgbus] Reaped #{deleted} stale processes" } if deleted.positive?
106
106
  rescue StandardError => e
107
107
  Pgbus.logger.warn { "[Pgbus] Stale process reaping failed: #{e.message}" }
@@ -127,7 +127,7 @@ module Pgbus
127
127
  end
128
128
 
129
129
  def cleanup_batches
130
- deleted = Batch.cleanup(older_than: Time.now.utc - (7 * 24 * 3600)) # 7 days
130
+ deleted = Batch.cleanup(older_than: Time.current - (7 * 24 * 3600)) # 7 days
131
131
  Pgbus.logger.debug { "[Pgbus] Cleaned up #{deleted} finished batches" } if deleted.positive?
132
132
  rescue StandardError => e
133
133
  Pgbus.logger.warn { "[Pgbus] Batch cleanup failed: #{e.message}" }
@@ -139,7 +139,7 @@ module Pgbus
139
139
  retention = config.stats_retention
140
140
  return unless retention&.positive?
141
141
 
142
- deleted = JobStat.cleanup!(older_than: Time.now.utc - retention)
142
+ deleted = JobStat.cleanup!(older_than: Time.current - retention)
143
143
  Pgbus.logger.debug { "[Pgbus] Cleaned up #{deleted} old job stats" } if deleted.positive?
144
144
  end
145
145
 
@@ -162,7 +162,7 @@ module Pgbus
162
162
  retention = config.outbox_retention
163
163
  return unless retention&.positive?
164
164
 
165
- deleted = OutboxEntry.published_before(Time.now.utc - retention).delete_all
165
+ deleted = OutboxEntry.published_before(Time.current - retention).delete_all
166
166
  Pgbus.logger.debug { "[Pgbus] Cleaned up #{deleted} published outbox entries" } if deleted.positive?
167
167
  rescue StandardError => e
168
168
  Pgbus.logger.warn { "[Pgbus] Outbox cleanup failed: #{e.message}" }
@@ -176,7 +176,7 @@ module Pgbus
176
176
  retention = config.archive_retention
177
177
  return unless retention&.positive?
178
178
 
179
- cutoff = Time.now.utc - retention
179
+ cutoff = Time.current - retention
180
180
  batch_size = config.archive_compaction_batch_size || 1000
181
181
  prefix = config.queue_prefix
182
182
 
@@ -200,12 +200,16 @@ module Pgbus
200
200
  retention = config.recurring_execution_retention
201
201
  return unless retention&.positive?
202
202
 
203
- deleted = RecurringExecution.older_than(Time.now.utc - retention).delete_all
203
+ deleted = RecurringExecution.older_than(Time.current - retention).delete_all
204
204
  Pgbus.logger.debug { "[Pgbus] Cleaned up #{deleted} old recurring executions" } if deleted.positive?
205
205
  rescue StandardError => e
206
206
  Pgbus.logger.warn { "[Pgbus] Recurring execution cleanup failed: #{e.message}" }
207
207
  end
208
208
 
209
+ def monotonic_now
210
+ ::Process.clock_gettime(::Process::CLOCK_MONOTONIC)
211
+ end
212
+
209
213
  def start_heartbeat
210
214
  @heartbeat = Heartbeat.new(kind: "dispatcher", metadata: { pid: ::Process.pid })
211
215
  @heartbeat.start
@@ -23,7 +23,8 @@ module Pgbus
23
23
  @jobs_failed = Concurrent::AtomicFixnum.new(0)
24
24
  @in_flight = Concurrent::AtomicFixnum.new(0)
25
25
  @rate_counter = RateCounter.new(:processed, :failed, :dequeued)
26
- @started_at = Time.now
26
+ @started_at = Time.current
27
+ @started_at_monotonic = monotonic_now
27
28
  @executor = Pgbus::ActiveJob::Executor.new
28
29
  @pool = Concurrent::FixedThreadPool.new(threads)
29
30
  @circuit_breaker = Pgbus::CircuitBreaker.new(config: config)
@@ -271,7 +272,7 @@ module Pgbus
271
272
  end
272
273
 
273
274
  def exceeded_max_lifetime?
274
- return false unless config.max_worker_lifetime && (Time.now - @started_at) > config.max_worker_lifetime
275
+ return false unless config.max_worker_lifetime && (monotonic_now - @started_at_monotonic) > config.max_worker_lifetime
275
276
 
276
277
  Pgbus.logger.info { "[Pgbus] Worker recycling: lifetime exceeded" }
277
278
  true
@@ -10,7 +10,7 @@ module Pgbus
10
10
  @tasks = load_tasks
11
11
  end
12
12
 
13
- def due_tasks(time = Time.now)
13
+ def due_tasks(time = Time.current)
14
14
  tasks.select { |task| task_due?(task, time) }
15
15
  end
16
16
 
@@ -30,7 +30,7 @@ module Pgbus
30
30
  process_signals
31
31
  break if @shutting_down
32
32
 
33
- tick(Time.now)
33
+ tick(Time.current)
34
34
  break if @shutting_down
35
35
 
36
36
  interruptible_sleep(config.recurring_schedule_interval)
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.1"
4
+ VERSION = "0.3.3"
5
5
  end