pgmq-ruby 0.1.0 → 0.3.0
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/.coditsu/ci.yml +3 -0
- data/.github/workflows/ci.yml +161 -0
- data/.github/workflows/push.yml +35 -0
- data/.gitignore +67 -0
- data/.rspec +1 -0
- data/.ruby-version +1 -0
- data/.yard-lint.yml +168 -0
- data/CHANGELOG.md +103 -0
- data/Gemfile +15 -0
- data/Gemfile.lock +65 -0
- data/LICENSE +165 -0
- data/README.md +627 -0
- data/Rakefile +4 -0
- data/docker-compose.yml +22 -0
- data/lib/pgmq/client/consumer.rb +155 -0
- data/lib/pgmq/client/maintenance.rb +46 -0
- data/lib/pgmq/client/message_lifecycle.rb +240 -0
- data/lib/pgmq/client/metrics.rb +49 -0
- data/lib/pgmq/client/multi_queue.rb +193 -0
- data/lib/pgmq/client/producer.rb +80 -0
- data/lib/pgmq/client/queue_management.rb +112 -0
- data/lib/pgmq/client.rb +138 -0
- data/lib/pgmq/connection.rb +196 -0
- data/lib/pgmq/errors.rb +30 -0
- data/lib/pgmq/message.rb +45 -0
- data/lib/pgmq/metrics.rb +37 -0
- data/lib/pgmq/queue_metadata.rb +37 -0
- data/lib/pgmq/transaction.rb +105 -0
- data/lib/pgmq/version.rb +6 -0
- data/lib/pgmq.rb +53 -0
- data/pgmq-ruby.gemspec +32 -0
- data/renovate.json +18 -0
- metadata +66 -4
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module PGMQ
|
|
4
|
+
# Low-level transaction support for PGMQ operations
|
|
5
|
+
#
|
|
6
|
+
# Provides atomic execution of PGMQ operations within PostgreSQL transactions.
|
|
7
|
+
# Transactions are a database primitive - this is a thin wrapper around
|
|
8
|
+
# PostgreSQL's native transaction support.
|
|
9
|
+
#
|
|
10
|
+
# This is analogous to rdkafka-ruby providing Kafka transaction support -
|
|
11
|
+
# it's a protocol/database feature, not a framework abstraction.
|
|
12
|
+
#
|
|
13
|
+
# @example Atomic multi-queue operations
|
|
14
|
+
# client.transaction do |txn|
|
|
15
|
+
# txn.send("orders", { order_id: 123 })
|
|
16
|
+
# txn.send("notifications", { type: "order_created" })
|
|
17
|
+
# end
|
|
18
|
+
#
|
|
19
|
+
# @example Automatic rollback on error
|
|
20
|
+
# client.transaction do |txn|
|
|
21
|
+
# txn.send("orders", { order_id: 123 })
|
|
22
|
+
# raise "Error" # Both operations rolled back
|
|
23
|
+
# end
|
|
24
|
+
module Transaction
|
|
25
|
+
# Executes PGMQ operations atomically within a database transaction
|
|
26
|
+
#
|
|
27
|
+
# Obtains a connection from the pool, starts a transaction, and yields
|
|
28
|
+
# a client that uses that transaction for all operations.
|
|
29
|
+
#
|
|
30
|
+
# @yield [PGMQ::Client] transactional client using the same connection
|
|
31
|
+
# @return [Object] result of the block
|
|
32
|
+
# @raise [PGMQ::Errors::ConnectionError] if transaction fails
|
|
33
|
+
#
|
|
34
|
+
# @example
|
|
35
|
+
# client.transaction do |txn|
|
|
36
|
+
# msg_id = txn.send("queue", { data: "test" })
|
|
37
|
+
# txn.delete("queue", msg_id)
|
|
38
|
+
# end
|
|
39
|
+
def transaction
|
|
40
|
+
@connection.with_connection do |conn|
|
|
41
|
+
conn.transaction do
|
|
42
|
+
yield TransactionalClient.new(self, conn)
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
rescue PG::Error, StandardError => e
|
|
46
|
+
raise PGMQ::Errors::ConnectionError, "Transaction failed: #{e.message}"
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Minimal wrapper that ensures all operations use the transaction connection
|
|
50
|
+
#
|
|
51
|
+
# @private
|
|
52
|
+
class TransactionalClient
|
|
53
|
+
# @param parent [PGMQ::Client] parent client instance
|
|
54
|
+
# @param conn [PG::Connection] transaction connection
|
|
55
|
+
def initialize(
|
|
56
|
+
parent,
|
|
57
|
+
conn
|
|
58
|
+
)
|
|
59
|
+
@parent = parent
|
|
60
|
+
@conn = conn
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# Forward all method calls to parent, but use our transaction connection
|
|
64
|
+
# @param method [Symbol] method name
|
|
65
|
+
# @return [Object] result of method call
|
|
66
|
+
def method_missing(method, ...)
|
|
67
|
+
@parent.respond_to?(method, true) ? @parent.__send__(method, ...) : super
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Override Object#send to call parent's send method
|
|
71
|
+
# @param queue_name [String] queue name
|
|
72
|
+
# @param message [String] message as JSON string
|
|
73
|
+
# @param delay [Integer] delay in seconds
|
|
74
|
+
# @return [String] message ID
|
|
75
|
+
def send(
|
|
76
|
+
queue_name,
|
|
77
|
+
message,
|
|
78
|
+
delay: 0
|
|
79
|
+
)
|
|
80
|
+
@parent.send(queue_name, message, delay: delay)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# Check if method exists on parent
|
|
84
|
+
# @param method [Symbol] method name
|
|
85
|
+
# @param include_private [Boolean] include private methods
|
|
86
|
+
# @return [Boolean] true if method exists
|
|
87
|
+
def respond_to_missing?(
|
|
88
|
+
method,
|
|
89
|
+
include_private = false
|
|
90
|
+
)
|
|
91
|
+
@parent.respond_to?(method, include_private) || super
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# Inject our transaction connection instead of using the pool
|
|
95
|
+
def with_connection
|
|
96
|
+
yield @conn
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# Expose parent's connection (for tests/inspection)
|
|
100
|
+
def connection
|
|
101
|
+
@parent.connection
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|
data/lib/pgmq/version.rb
ADDED
data/lib/pgmq.rb
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'zeitwerk'
|
|
4
|
+
require 'time'
|
|
5
|
+
|
|
6
|
+
loader = Zeitwerk::Loader.for_gem
|
|
7
|
+
loader.inflector.inflect(
|
|
8
|
+
'pgmq' => 'PGMQ'
|
|
9
|
+
)
|
|
10
|
+
loader.setup
|
|
11
|
+
loader.eager_load
|
|
12
|
+
|
|
13
|
+
# PGMQ - Low-level Ruby client for Postgres Message Queue
|
|
14
|
+
#
|
|
15
|
+
# This is a low-level library providing direct access to PGMQ operations.
|
|
16
|
+
# For higher-level abstractions, job processing, and framework integrations,
|
|
17
|
+
# see pgmq-framework (similar to how rdkafka-ruby relates to Karafka).
|
|
18
|
+
#
|
|
19
|
+
# @example Basic usage
|
|
20
|
+
# require 'pgmq'
|
|
21
|
+
#
|
|
22
|
+
# # Create client with connection parameters
|
|
23
|
+
# client = PGMQ::Client.new(
|
|
24
|
+
# host: 'localhost',
|
|
25
|
+
# port: 5432,
|
|
26
|
+
# dbname: 'mydb',
|
|
27
|
+
# user: 'postgres',
|
|
28
|
+
# password: 'postgres'
|
|
29
|
+
# )
|
|
30
|
+
#
|
|
31
|
+
# # Or with connection string
|
|
32
|
+
# client = PGMQ::Client.new('postgres://localhost/mydb')
|
|
33
|
+
#
|
|
34
|
+
# # Basic queue operations
|
|
35
|
+
# client.create('orders')
|
|
36
|
+
# msg_id = client.send('orders', { order_id: 123 })
|
|
37
|
+
# msg = client.read('orders', vt: 30)
|
|
38
|
+
# client.delete('orders', msg.msg_id)
|
|
39
|
+
# client.drop_queue('orders')
|
|
40
|
+
module PGMQ
|
|
41
|
+
class << self
|
|
42
|
+
# Convenience method to create a new client
|
|
43
|
+
#
|
|
44
|
+
# @return [PGMQ::Client] new client instance
|
|
45
|
+
# @see PGMQ::Client#initialize
|
|
46
|
+
#
|
|
47
|
+
# @example
|
|
48
|
+
# client = PGMQ.new('postgres://localhost/mydb')
|
|
49
|
+
def new(*, **)
|
|
50
|
+
Client.new(*, **)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
data/pgmq-ruby.gemspec
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'lib/pgmq/version'
|
|
4
|
+
|
|
5
|
+
Gem::Specification.new do |spec|
|
|
6
|
+
spec.name = 'pgmq-ruby'
|
|
7
|
+
spec.version = PGMQ::VERSION
|
|
8
|
+
spec.authors = ['Maciej Mensfeld']
|
|
9
|
+
spec.email = ['maciej@mensfeld.pl']
|
|
10
|
+
|
|
11
|
+
spec.summary = 'Ruby client for PGMQ (Postgres Message Queue)'
|
|
12
|
+
spec.description = 'A Ruby driver for PGMQ - a lightweight message queue built on PostgreSQL. ' \
|
|
13
|
+
'Like AWS SQS and RSMQ, but on Postgres.'
|
|
14
|
+
spec.homepage = 'https://github.com/mensfeld/pgmq-ruby'
|
|
15
|
+
spec.license = 'LGPL-3.0'
|
|
16
|
+
spec.required_ruby_version = '>= 3.2.0'
|
|
17
|
+
|
|
18
|
+
spec.metadata['homepage_uri'] = spec.homepage
|
|
19
|
+
spec.metadata['source_code_uri'] = 'https://github.com/mensfeld/pgmq-ruby'
|
|
20
|
+
spec.metadata['changelog_uri'] = 'https://github.com/mensfeld/pgmq-ruby/blob/master/CHANGELOG.md'
|
|
21
|
+
spec.metadata['bug_tracker_uri'] = 'https://github.com/mensfeld/pgmq-ruby/issues'
|
|
22
|
+
spec.metadata['documentation_uri'] = 'https://github.com/mensfeld/pgmq-ruby#readme'
|
|
23
|
+
spec.metadata['rubygems_mfa_required'] = 'true'
|
|
24
|
+
|
|
25
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(spec|examples)/}) }
|
|
26
|
+
spec.require_paths = ['lib']
|
|
27
|
+
|
|
28
|
+
# Runtime dependencies
|
|
29
|
+
spec.add_dependency 'connection_pool', '~> 2.4'
|
|
30
|
+
spec.add_dependency 'pg', '~> 1.5'
|
|
31
|
+
spec.add_dependency 'zeitwerk', '~> 2.6'
|
|
32
|
+
end
|
data/renovate.json
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
|
3
|
+
"extends": [
|
|
4
|
+
"config:recommended"
|
|
5
|
+
],
|
|
6
|
+
"github-actions": {
|
|
7
|
+
"enabled": true,
|
|
8
|
+
"pinDigests": true
|
|
9
|
+
},
|
|
10
|
+
"packageRules": [
|
|
11
|
+
{
|
|
12
|
+
"matchManagers": [
|
|
13
|
+
"github-actions"
|
|
14
|
+
],
|
|
15
|
+
"minimumReleaseAge": "7 days"
|
|
16
|
+
}
|
|
17
|
+
]
|
|
18
|
+
}
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: pgmq-ruby
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Maciej Mensfeld
|
|
@@ -9,6 +9,20 @@ bindir: bin
|
|
|
9
9
|
cert_chain: []
|
|
10
10
|
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: connection_pool
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - "~>"
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '2.4'
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - "~>"
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '2.4'
|
|
12
26
|
- !ruby/object:Gem::Dependency
|
|
13
27
|
name: pg
|
|
14
28
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -23,13 +37,60 @@ dependencies:
|
|
|
23
37
|
- - "~>"
|
|
24
38
|
- !ruby/object:Gem::Version
|
|
25
39
|
version: '1.5'
|
|
26
|
-
|
|
40
|
+
- !ruby/object:Gem::Dependency
|
|
41
|
+
name: zeitwerk
|
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
|
43
|
+
requirements:
|
|
44
|
+
- - "~>"
|
|
45
|
+
- !ruby/object:Gem::Version
|
|
46
|
+
version: '2.6'
|
|
47
|
+
type: :runtime
|
|
48
|
+
prerelease: false
|
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
50
|
+
requirements:
|
|
51
|
+
- - "~>"
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
version: '2.6'
|
|
54
|
+
description: A Ruby driver for PGMQ - a lightweight message queue built on PostgreSQL.
|
|
55
|
+
Like AWS SQS and RSMQ, but on Postgres.
|
|
27
56
|
email:
|
|
28
|
-
-
|
|
57
|
+
- maciej@mensfeld.pl
|
|
29
58
|
executables: []
|
|
30
59
|
extensions: []
|
|
31
60
|
extra_rdoc_files: []
|
|
32
|
-
files:
|
|
61
|
+
files:
|
|
62
|
+
- ".coditsu/ci.yml"
|
|
63
|
+
- ".github/workflows/ci.yml"
|
|
64
|
+
- ".github/workflows/push.yml"
|
|
65
|
+
- ".gitignore"
|
|
66
|
+
- ".rspec"
|
|
67
|
+
- ".ruby-version"
|
|
68
|
+
- ".yard-lint.yml"
|
|
69
|
+
- CHANGELOG.md
|
|
70
|
+
- Gemfile
|
|
71
|
+
- Gemfile.lock
|
|
72
|
+
- LICENSE
|
|
73
|
+
- README.md
|
|
74
|
+
- Rakefile
|
|
75
|
+
- docker-compose.yml
|
|
76
|
+
- lib/pgmq.rb
|
|
77
|
+
- lib/pgmq/client.rb
|
|
78
|
+
- lib/pgmq/client/consumer.rb
|
|
79
|
+
- lib/pgmq/client/maintenance.rb
|
|
80
|
+
- lib/pgmq/client/message_lifecycle.rb
|
|
81
|
+
- lib/pgmq/client/metrics.rb
|
|
82
|
+
- lib/pgmq/client/multi_queue.rb
|
|
83
|
+
- lib/pgmq/client/producer.rb
|
|
84
|
+
- lib/pgmq/client/queue_management.rb
|
|
85
|
+
- lib/pgmq/connection.rb
|
|
86
|
+
- lib/pgmq/errors.rb
|
|
87
|
+
- lib/pgmq/message.rb
|
|
88
|
+
- lib/pgmq/metrics.rb
|
|
89
|
+
- lib/pgmq/queue_metadata.rb
|
|
90
|
+
- lib/pgmq/transaction.rb
|
|
91
|
+
- lib/pgmq/version.rb
|
|
92
|
+
- pgmq-ruby.gemspec
|
|
93
|
+
- renovate.json
|
|
33
94
|
homepage: https://github.com/mensfeld/pgmq-ruby
|
|
34
95
|
licenses:
|
|
35
96
|
- LGPL-3.0
|
|
@@ -38,6 +99,7 @@ metadata:
|
|
|
38
99
|
source_code_uri: https://github.com/mensfeld/pgmq-ruby
|
|
39
100
|
changelog_uri: https://github.com/mensfeld/pgmq-ruby/blob/master/CHANGELOG.md
|
|
40
101
|
bug_tracker_uri: https://github.com/mensfeld/pgmq-ruby/issues
|
|
102
|
+
documentation_uri: https://github.com/mensfeld/pgmq-ruby#readme
|
|
41
103
|
rubygems_mfa_required: 'true'
|
|
42
104
|
rdoc_options: []
|
|
43
105
|
require_paths:
|