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.
@@ -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
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PGMQ
4
+ # Current version of the pgmq-ruby gem
5
+ VERSION = '0.3.0'
6
+ end
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.1.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
- description: A Ruby driver for PGMQ - a lightweight message queue built on PostgreSQL
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
- - contact@karafka.io
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: