pgbus 0.3.1 → 0.3.2
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 +4 -4
- data/Rakefile +6 -1
- data/app/models/pgbus/job_lock.rb +26 -18
- data/lib/pgbus/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d895049be3463d74d039e29485fc7d26c4c06ca96419e8a46327a4be6538db1f
|
|
4
|
+
data.tar.gz: f685673eaf24780e820486b9eb1f752493caf1765241b0063293d1d8d4b98e25
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 33cb5c4fbf7ae36a8bb82a780d39bd0a32fd2c3167d0d7aaaed74a60608778a90e32eac53c1db2808ffa5956184298a83478488a8d11edcc89b052ec5fe8b0a5
|
|
7
|
+
data.tar.gz: 4a9cc394b02ee99e1681ab26a86db25c57f38f92e901dab0c2c48c1025224bb4089009abcd865a2432c3b37a988b51511faa64be976709069a4dbef70e3ec5ed
|
data/Rakefile
CHANGED
|
@@ -31,7 +31,12 @@ namespace :bench do
|
|
|
31
31
|
ruby "benchmarks/memory_profile.rb"
|
|
32
32
|
end
|
|
33
33
|
|
|
34
|
-
desc "Run
|
|
34
|
+
desc "Run integration benchmarks (requires PGBUS_DATABASE_URL)"
|
|
35
|
+
task :integration do
|
|
36
|
+
ruby "benchmarks/integration_bench.rb"
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
desc "Run all benchmarks (unit-level, no DB required)"
|
|
35
40
|
task all: %i[serialization client executor]
|
|
36
41
|
end
|
|
37
42
|
|
|
@@ -16,42 +16,50 @@ module Pgbus
|
|
|
16
16
|
# Atomically try to acquire a lock.
|
|
17
17
|
# Cleans up expired locks for this key first (crash recovery at acquire time).
|
|
18
18
|
# Returns true if acquired, false if already locked.
|
|
19
|
-
|
|
19
|
+
#
|
|
20
|
+
# Uses raw SQL on the hot path to minimize ActiveRecord allocations
|
|
21
|
+
# (~29 objects vs ~304 per acquire+release cycle with AR query builder).
|
|
22
|
+
def self.acquire!(lock_key, job_class:, ttl:, job_id: nil, state: "queued", owner_pid: nil, owner_hostname: nil) # rubocop:disable Naming/PredicateMethod
|
|
23
|
+
expires_at = Time.current + ttl
|
|
24
|
+
|
|
20
25
|
# Remove any expired lock for this key inline (last-resort TTL recovery)
|
|
21
|
-
|
|
26
|
+
connection.exec_delete(
|
|
27
|
+
"DELETE FROM #{table_name} WHERE lock_key = $1 AND expires_at < $2",
|
|
28
|
+
"JobLock Expire", [lock_key, Time.current]
|
|
29
|
+
)
|
|
22
30
|
|
|
23
|
-
result =
|
|
24
|
-
{
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
expires_at: Time.current + ttl
|
|
28
|
-
},
|
|
29
|
-
unique_by: :lock_key
|
|
31
|
+
result = connection.exec_query(
|
|
32
|
+
"INSERT INTO #{table_name} (lock_key, job_class, job_id, state, owner_pid, owner_hostname, expires_at) " \
|
|
33
|
+
"VALUES ($1, $2, $3, $4, $5, $6, $7) ON CONFLICT (lock_key) DO NOTHING RETURNING id",
|
|
34
|
+
"JobLock Acquire", [lock_key, job_class, job_id, state, owner_pid, owner_hostname, expires_at]
|
|
30
35
|
)
|
|
31
36
|
result.rows.any?
|
|
32
|
-
rescue ActiveRecord::RecordNotUnique
|
|
33
|
-
false
|
|
34
37
|
end
|
|
35
38
|
|
|
36
39
|
# Transition a queued lock to executing state and claim ownership.
|
|
37
40
|
# Called when a worker starts executing a job that was locked at enqueue time.
|
|
38
41
|
def self.claim_for_execution!(lock_key, owner_pid:, owner_hostname:, ttl:)
|
|
39
|
-
|
|
40
|
-
state
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
expires_at: Time.current + ttl
|
|
42
|
+
connection.exec_update(
|
|
43
|
+
"UPDATE #{table_name} SET state = $1, owner_pid = $2, owner_hostname = $3, expires_at = $4 " \
|
|
44
|
+
"WHERE lock_key = $5",
|
|
45
|
+
"JobLock Claim", ["executing", owner_pid, owner_hostname, Time.current + ttl, lock_key]
|
|
44
46
|
)
|
|
45
47
|
end
|
|
46
48
|
|
|
47
49
|
# Release a lock by key.
|
|
48
50
|
def self.release!(lock_key)
|
|
49
|
-
|
|
51
|
+
connection.exec_delete(
|
|
52
|
+
"DELETE FROM #{table_name} WHERE lock_key = $1",
|
|
53
|
+
"JobLock Release", [lock_key]
|
|
54
|
+
)
|
|
50
55
|
end
|
|
51
56
|
|
|
52
57
|
# Check if a lock is currently held (regardless of expiry — reaper handles orphans).
|
|
53
58
|
def self.locked?(lock_key)
|
|
54
|
-
|
|
59
|
+
result = connection.select_value(
|
|
60
|
+
"SELECT 1 FROM #{table_name} WHERE lock_key = $1 LIMIT 1", "JobLock Check", [lock_key]
|
|
61
|
+
)
|
|
62
|
+
!result.nil?
|
|
55
63
|
end
|
|
56
64
|
|
|
57
65
|
# Reap orphaned locks: locks in 'executing' state whose owner_pid
|
data/lib/pgbus/version.rb
CHANGED