Skip to content

Commit 929e010

Browse files
authored
fix: Use monotonic clock so postgres timeouts are unaffected by system clock changes (#141)
1 parent 98ebdcc commit 929e010

File tree

2 files changed

+9
-8
lines changed

2 files changed

+9
-8
lines changed

lib/with_advisory_lock/core_advisory.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,8 @@ def advisory_lock_and_yield(lock_name, lock_str, lock_stack_item, options, &)
7070

7171
def yield_with_lock_and_timeout(lock_keys, lock_name, lock_str, lock_stack_item, shared, transaction,
7272
timeout_seconds, &)
73-
give_up_at = timeout_seconds ? Time.now + timeout_seconds : nil
74-
while give_up_at.nil? || Time.now < give_up_at
73+
give_up_at = timeout_seconds ? Process.clock_gettime(Process::CLOCK_MONOTONIC) + timeout_seconds : nil
74+
while give_up_at.nil? || Process.clock_gettime(Process::CLOCK_MONOTONIC) < give_up_at
7575
r = yield_with_lock(lock_keys, lock_name, lock_str, lock_stack_item, shared, transaction, 0, &)
7676
return r if r.lock_was_acquired?
7777

test/with_advisory_lock/lock_test.rb

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -200,13 +200,14 @@ def setup
200200

201201
begin
202202
# Attempt to acquire with a short timeout - should fail quickly
203-
start_time = Time.now
204-
result = model_class.with_advisory_lock(lock_name, timeout_seconds: 1) { 'success' }
205-
elapsed = Time.now - start_time
203+
elapsed = Benchmark.realtime do
204+
result = model_class.with_advisory_lock(lock_name, timeout_seconds: 1) { 'success' }
205+
206+
# Should return false and complete within reasonable time (< 3 seconds)
207+
# If it were using Ruby polling, it would take longer
208+
assert_not result
209+
end
206210

207-
# Should return false and complete within reasonable time (< 3 seconds)
208-
# If it were using Ruby polling, it would take longer
209-
assert_not result
210211
assert elapsed < 3.0, "Expected quick timeout, but took #{elapsed} seconds"
211212
ensure
212213
other_conn.query_value("SELECT RELEASE_LOCK(#{other_conn.quote(lock_keys.first)})")

0 commit comments

Comments
 (0)