pgmq-ruby 0.4.0 → 0.6.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,268 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PGMQ
4
+ class Client
5
+ # Topic routing operations (AMQP-like patterns)
6
+ #
7
+ # This module provides AMQP-style topic routing for PGMQ, allowing messages
8
+ # to be routed to multiple queues based on pattern matching.
9
+ #
10
+ # Topic patterns support wildcards:
11
+ # - `*` matches exactly one word between dots (e.g., `orders.*` matches `orders.new`)
12
+ # - `#` matches zero or more words (e.g., `orders.#` matches `orders.new.urgent`)
13
+ #
14
+ # @note Requires PGMQ v1.11.0+
15
+ module Topics
16
+ # Binds a topic pattern to a queue
17
+ #
18
+ # Messages sent with routing keys matching this pattern will be delivered
19
+ # to the specified queue.
20
+ #
21
+ # @param pattern [String] topic pattern with optional wildcards (* or #)
22
+ # @param queue_name [String] name of the queue to bind
23
+ # @return [void]
24
+ #
25
+ # @example Bind exact routing key
26
+ # client.bind_topic("orders.new", "new_orders")
27
+ #
28
+ # @example Bind with single-word wildcard
29
+ # client.bind_topic("orders.*", "all_order_events")
30
+ #
31
+ # @example Bind with multi-word wildcard
32
+ # client.bind_topic("orders.#", "order_audit_log")
33
+ def bind_topic(pattern, queue_name)
34
+ validate_queue_name!(queue_name)
35
+
36
+ with_connection do |conn|
37
+ conn.exec_params(
38
+ "SELECT pgmq.bind_topic($1::text, $2::text)",
39
+ [pattern, queue_name]
40
+ )
41
+ end
42
+
43
+ nil
44
+ end
45
+
46
+ # Unbinds a topic pattern from a queue
47
+ #
48
+ # @param pattern [String] topic pattern to unbind
49
+ # @param queue_name [String] name of the queue to unbind from
50
+ # @return [Boolean] true if the binding was removed, false if it didn't exist
51
+ #
52
+ # @example
53
+ # client.unbind_topic("orders.new", "new_orders")
54
+ def unbind_topic(pattern, queue_name)
55
+ validate_queue_name!(queue_name)
56
+
57
+ result = with_connection do |conn|
58
+ conn.exec_params(
59
+ "SELECT pgmq.unbind_topic($1::text, $2::text)",
60
+ [pattern, queue_name]
61
+ )
62
+ end
63
+
64
+ result[0]["unbind_topic"] == "t"
65
+ end
66
+
67
+ # Sends a message via topic routing
68
+ #
69
+ # The message will be delivered to all queues whose bound patterns match
70
+ # the routing key.
71
+ #
72
+ # @param routing_key [String] dot-separated routing key (e.g., "orders.new.priority")
73
+ # @param message [String] message as JSON string
74
+ # @param headers [String, nil] optional headers as JSON string
75
+ # @param delay [Integer] delay in seconds before message becomes visible
76
+ # @return [Integer] count of queues the message was delivered to
77
+ #
78
+ # @example Basic topic send
79
+ # count = client.produce_topic("orders.new", '{"order_id":123}')
80
+ #
81
+ # @example With headers and delay
82
+ # count = client.produce_topic("orders.new.priority",
83
+ # '{"order_id":123}',
84
+ # headers: '{"trace_id":"abc"}',
85
+ # delay: 30)
86
+ def produce_topic(routing_key, message, headers: nil, delay: 0)
87
+ result = with_connection do |conn|
88
+ if headers
89
+ conn.exec_params(
90
+ "SELECT pgmq.send_topic($1::text, $2::jsonb, $3::jsonb, $4::integer)",
91
+ [routing_key, message, headers, delay]
92
+ )
93
+ elsif delay > 0
94
+ conn.exec_params(
95
+ "SELECT pgmq.send_topic($1::text, $2::jsonb, $3::integer)",
96
+ [routing_key, message, delay]
97
+ )
98
+ else
99
+ conn.exec_params(
100
+ "SELECT pgmq.send_topic($1::text, $2::jsonb)",
101
+ [routing_key, message]
102
+ )
103
+ end
104
+ end
105
+
106
+ result[0]["send_topic"].to_i
107
+ end
108
+
109
+ # Sends multiple messages via topic routing
110
+ #
111
+ # All messages will be delivered to all queues whose bound patterns match
112
+ # the routing key.
113
+ #
114
+ # @param routing_key [String] dot-separated routing key
115
+ # @param messages [Array<String>] array of message payloads as JSON strings
116
+ # @param headers [Array<String>, nil] optional array of headers as JSON strings
117
+ # @param delay [Integer] delay in seconds before messages become visible
118
+ # @return [Array<Hash>] array of hashes with :queue_name and :msg_id
119
+ #
120
+ # @example Batch topic send
121
+ # results = client.produce_batch_topic("orders.new", [
122
+ # '{"order_id":1}',
123
+ # '{"order_id":2}'
124
+ # ])
125
+ # # => [{ queue_name: "new_orders", msg_id: "1" }, ...]
126
+ def produce_batch_topic(routing_key, messages, headers: nil, delay: 0)
127
+ return [] if messages.empty?
128
+
129
+ if headers && headers.length != messages.length
130
+ raise ArgumentError,
131
+ "headers array length (#{headers.length}) must match messages array length (#{messages.length})"
132
+ end
133
+
134
+ result = with_connection do |conn|
135
+ encoder = PG::TextEncoder::Array.new
136
+ encoded_messages = encoder.encode(messages)
137
+
138
+ if headers
139
+ encoded_headers = encoder.encode(headers)
140
+ conn.exec_params(
141
+ "SELECT * FROM pgmq.send_batch_topic($1::text, $2::jsonb[], $3::jsonb[], $4::integer)",
142
+ [routing_key, encoded_messages, encoded_headers, delay]
143
+ )
144
+ elsif delay > 0
145
+ conn.exec_params(
146
+ "SELECT * FROM pgmq.send_batch_topic($1::text, $2::jsonb[], $3::integer)",
147
+ [routing_key, encoded_messages, delay]
148
+ )
149
+ else
150
+ conn.exec_params(
151
+ "SELECT * FROM pgmq.send_batch_topic($1::text, $2::jsonb[])",
152
+ [routing_key, encoded_messages]
153
+ )
154
+ end
155
+ end
156
+
157
+ result.map do |row|
158
+ { queue_name: row["queue_name"], msg_id: row["msg_id"] }
159
+ end
160
+ end
161
+
162
+ # Lists all topic bindings
163
+ #
164
+ # @param queue_name [String, nil] optional queue name to filter by
165
+ # @return [Array<Hash>] array of binding hashes with pattern, queue_name, bound_at
166
+ #
167
+ # @example List all bindings
168
+ # bindings = client.list_topic_bindings
169
+ # # => [{ pattern: "orders.*", queue_name: "orders", bound_at: "..." }, ...]
170
+ #
171
+ # @example List bindings for specific queue
172
+ # bindings = client.list_topic_bindings(queue_name: "orders")
173
+ def list_topic_bindings(queue_name: nil)
174
+ result = with_connection do |conn|
175
+ if queue_name
176
+ validate_queue_name!(queue_name)
177
+ conn.exec_params(
178
+ "SELECT pattern, queue_name, bound_at FROM pgmq.list_topic_bindings($1::text)",
179
+ [queue_name]
180
+ )
181
+ else
182
+ conn.exec("SELECT pattern, queue_name, bound_at FROM pgmq.list_topic_bindings()")
183
+ end
184
+ end
185
+
186
+ result.map do |row|
187
+ {
188
+ pattern: row["pattern"],
189
+ queue_name: row["queue_name"],
190
+ bound_at: row["bound_at"]
191
+ }
192
+ end
193
+ end
194
+
195
+ # Tests which queues a routing key would match
196
+ #
197
+ # Useful for debugging topic routing configurations.
198
+ #
199
+ # @param routing_key [String] routing key to test
200
+ # @return [Array<Hash>] array of matched bindings with pattern and queue_name
201
+ #
202
+ # @example Test routing
203
+ # matches = client.test_routing("orders.new.priority")
204
+ # # => [{ pattern: "orders.*", queue_name: "new_orders" }, ...]
205
+ def test_routing(routing_key)
206
+ result = with_connection do |conn|
207
+ conn.exec_params(
208
+ "SELECT pattern, queue_name FROM pgmq.test_routing($1::text)",
209
+ [routing_key]
210
+ )
211
+ end
212
+
213
+ result.map do |row|
214
+ { pattern: row["pattern"], queue_name: row["queue_name"] }
215
+ end
216
+ end
217
+
218
+ # Validates a routing key
219
+ #
220
+ # Routing keys are dot-separated words (no wildcards allowed).
221
+ # Returns false for invalid routing keys (PGMQ raises an error for invalid keys).
222
+ #
223
+ # @param routing_key [String] routing key to validate
224
+ # @return [Boolean] true if valid, false if invalid
225
+ #
226
+ # @example
227
+ # client.validate_routing_key("orders.new.priority") # => true
228
+ # client.validate_routing_key("orders.*") # => false (wildcards not allowed)
229
+ def validate_routing_key(routing_key)
230
+ result = with_connection do |conn|
231
+ conn.exec_params(
232
+ "SELECT pgmq.validate_routing_key($1::text)",
233
+ [routing_key]
234
+ )
235
+ end
236
+
237
+ result[0]["validate_routing_key"] == "t"
238
+ rescue PGMQ::Errors::ConnectionError => e
239
+ # PGMQ raises an error for invalid routing keys
240
+ return false if e.message.include?("invalid characters")
241
+
242
+ raise
243
+ end
244
+
245
+ # Validates a topic pattern
246
+ #
247
+ # Topic patterns can include wildcards: * (single word) or # (zero or more words).
248
+ #
249
+ # @param pattern [String] topic pattern to validate
250
+ # @return [Boolean] true if valid
251
+ #
252
+ # @example
253
+ # client.validate_topic_pattern("orders.*") # => true
254
+ # client.validate_topic_pattern("orders.#") # => true
255
+ # client.validate_topic_pattern("orders.new") # => true
256
+ def validate_topic_pattern(pattern)
257
+ result = with_connection do |conn|
258
+ conn.exec_params(
259
+ "SELECT pgmq.validate_topic_pattern($1::text)",
260
+ [pattern]
261
+ )
262
+ end
263
+
264
+ result[0]["validate_topic_pattern"] == "t"
265
+ end
266
+ end
267
+ end
268
+ end
data/lib/pgmq/client.rb CHANGED
@@ -31,8 +31,9 @@ module PGMQ
31
31
  include Consumer # Single-queue reading operations
32
32
  include MultiQueue # Multi-queue operations
33
33
  include MessageLifecycle # Message state transitions (pop, delete, archive)
34
- include Maintenance # Queue maintenance (purge, detach_archive)
34
+ include Maintenance # Queue maintenance (purge, notifications)
35
35
  include Metrics # Monitoring and metrics
36
+ include Topics # Topic routing (AMQP-like patterns, PGMQ v1.11.0+)
36
37
 
37
38
  # Default visibility timeout in seconds
38
39
  DEFAULT_VT = 30
@@ -65,15 +66,15 @@ module PGMQ
65
66
  auto_reconnect: true
66
67
  )
67
68
  @connection = if conn_params.is_a?(Connection)
68
- conn_params
69
- else
70
- Connection.new(
71
- conn_params,
72
- pool_size: pool_size,
73
- pool_timeout: pool_timeout,
74
- auto_reconnect: auto_reconnect
75
- )
76
- end
69
+ conn_params
70
+ else
71
+ Connection.new(
72
+ conn_params,
73
+ pool_size: pool_size,
74
+ pool_timeout: pool_timeout,
75
+ auto_reconnect: auto_reconnect
76
+ )
77
+ end
77
78
  end
78
79
 
79
80
  # Closes all connections in the pool
@@ -109,7 +110,7 @@ module PGMQ
109
110
  if queue_name.nil? || queue_name.to_s.strip.empty?
110
111
  raise(
111
112
  Errors::InvalidQueueNameError,
112
- 'Queue name cannot be empty'
113
+ "Queue name cannot be empty"
113
114
  )
114
115
  end
115
116
 
@@ -131,7 +132,7 @@ module PGMQ
131
132
  raise(
132
133
  Errors::InvalidQueueNameError,
133
134
  "Invalid queue name '#{queue_name}': must start with a letter or underscore " \
134
- 'and contain only letters, digits, and underscores'
135
+ "and contain only letters, digits, and underscores"
135
136
  )
136
137
  end
137
138
  end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'pg'
4
- require 'connection_pool'
3
+ require "pg"
4
+ require "connection_pool"
5
5
 
6
6
  module PGMQ
7
7
  # Manages database connections for PGMQ
@@ -45,7 +45,7 @@ module PGMQ
45
45
  if conn_params.nil?
46
46
  raise(
47
47
  PGMQ::Errors::ConfigurationError,
48
- 'Connection parameters are required'
48
+ "Connection parameters are required"
49
49
  )
50
50
  end
51
51
 
@@ -113,12 +113,12 @@ module PGMQ
113
113
  def connection_lost_error?(error)
114
114
  # Common connection lost errors
115
115
  lost_connection_messages = [
116
- 'server closed the connection',
117
- 'connection not open',
118
- 'no connection to the server',
119
- 'terminating connection',
120
- 'connection to server was lost',
121
- 'could not receive data from server'
116
+ "server closed the connection",
117
+ "connection not open",
118
+ "no connection to the server",
119
+ "terminating connection",
120
+ "connection to server was lost",
121
+ "could not receive data from server"
122
122
  ]
123
123
 
124
124
  message = error.message.downcase
@@ -145,7 +145,7 @@ module PGMQ
145
145
  return parse_connection_string(params) if params.is_a?(String)
146
146
  return params if params.is_a?(Hash) && !params.empty?
147
147
 
148
- raise PGMQ::Errors::ConfigurationError, 'Invalid connection parameters format'
148
+ raise PGMQ::Errors::ConfigurationError, "Invalid connection parameters format"
149
149
  end
150
150
 
151
151
  # Parses a PostgreSQL connection string
@@ -169,11 +169,34 @@ module PGMQ
169
169
  # @return [ConnectionPool]
170
170
  def create_pool
171
171
  params = @conn_params
172
+ seen_connections = ObjectSpace::WeakKeyMap.new
173
+ seen_mutex = Mutex.new
172
174
 
173
175
  ConnectionPool.new(size: @pool_size, timeout: @pool_timeout) do
174
- create_connection(params)
176
+ conn = create_connection(params)
177
+
178
+ # Detect shared connections: if a callable returns the same PG::Connection
179
+ # object to multiple pool slots, concurrent use will corrupt libpq state
180
+ # (nil results, segfaults, wrong data). Fail fast with a clear message.
181
+ if conn.is_a?(PG::Connection)
182
+ seen_mutex.synchronize do
183
+ if seen_connections.key?(conn)
184
+ raise PGMQ::Errors::ConfigurationError,
185
+ "Connection callable returned the same PG::Connection object " \
186
+ "(object_id: #{conn.object_id}) to multiple pool slots. " \
187
+ "PG::Connection is NOT thread-safe — concurrent use causes nil results, " \
188
+ "segfaults, and data corruption. Ensure your callable returns a unique " \
189
+ "PG::Connection instance on each invocation (for example, by calling " \
190
+ "PG.connect inside the callable)."
191
+ end
192
+
193
+ seen_connections[conn] = true
194
+ end
195
+ end
196
+
197
+ conn
175
198
  end
176
- rescue StandardError => e
199
+ rescue => e
177
200
  raise PGMQ::Errors::ConnectionError, "Failed to create connection pool: #{e.message}"
178
201
  end
179
202
 
data/lib/pgmq/message.rb CHANGED
@@ -11,12 +11,13 @@ module PGMQ
11
11
  # puts msg.msg_id # => "123" (String from PG)
12
12
  # puts msg.read_ct # => "1" (String from PG)
13
13
  # puts msg.enqueued_at # => "2025-01-15 10:30:00+00" (String from PG)
14
+ # puts msg.last_read_at # => "2025-01-15 10:31:00+00" (String from PG, nil if never read)
14
15
  # puts msg.vt # => "2025-01-15 10:30:30+00" (String from PG)
15
16
  # puts msg.message # => "{\"order_id\":456}" (Raw JSONB string)
16
17
  # puts msg.headers # => "{\"trace_id\":\"abc123\"}" (Raw JSONB string, optional)
17
18
  # puts msg.queue_name # => "my_queue" (only present for multi-queue operations)
18
19
  class Message < Data.define(
19
- :msg_id, :read_ct, :enqueued_at, :vt, :message, :headers, :queue_name
20
+ :msg_id, :read_ct, :enqueued_at, :last_read_at, :vt, :message, :headers, :queue_name
20
21
  )
21
22
  class << self
22
23
  # Creates a new Message from a database row
@@ -27,19 +28,20 @@ module PGMQ
27
28
  # No parsing, no deserialization, no transformation
28
29
  # The pg gem returns JSONB as String by default
29
30
  super(
30
- msg_id: row['msg_id'],
31
- read_ct: row['read_ct'],
32
- enqueued_at: row['enqueued_at'],
33
- vt: row['vt'],
34
- message: row['message'],
35
- headers: row['headers'], # JSONB column for metadata (optional)
36
- queue_name: row['queue_name'] # nil for single-queue operations
31
+ msg_id: row["msg_id"],
32
+ read_ct: row["read_ct"],
33
+ enqueued_at: row["enqueued_at"],
34
+ last_read_at: row["last_read_at"], # nil if message has never been read
35
+ vt: row["vt"],
36
+ message: row["message"],
37
+ headers: row["headers"], # JSONB column for metadata (optional)
38
+ queue_name: row["queue_name"] # nil for single-queue operations
37
39
  )
38
40
  end
39
41
  end
40
42
 
41
43
  # Alias for msg_id (common in messaging systems)
42
44
  # @return [String]
43
- alias id msg_id
45
+ alias_method :id, :msg_id
44
46
  end
45
47
  end
data/lib/pgmq/metrics.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'time'
3
+ require "time"
4
4
 
5
5
  module PGMQ
6
6
  # Represents metrics for a PGMQ queue
@@ -24,12 +24,12 @@ module PGMQ
24
24
  def new(row, **)
25
25
  # Return raw values as-is from PostgreSQL
26
26
  super(
27
- queue_name: row['queue_name'],
28
- queue_length: row['queue_length'],
29
- newest_msg_age_sec: row['newest_msg_age_sec'],
30
- oldest_msg_age_sec: row['oldest_msg_age_sec'],
31
- total_messages: row['total_messages'],
32
- scrape_time: row['scrape_time']
27
+ queue_name: row["queue_name"],
28
+ queue_length: row["queue_length"],
29
+ newest_msg_age_sec: row["newest_msg_age_sec"],
30
+ oldest_msg_age_sec: row["oldest_msg_age_sec"],
31
+ total_messages: row["total_messages"],
32
+ scrape_time: row["scrape_time"]
33
33
  )
34
34
  end
35
35
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'time'
3
+ require "time"
4
4
 
5
5
  module PGMQ
6
6
  # Represents metadata about a PGMQ queue
@@ -18,20 +18,20 @@ module PGMQ
18
18
  def new(row, **)
19
19
  # Return raw values as-is from PostgreSQL
20
20
  super(
21
- queue_name: row['queue_name'],
22
- created_at: row['created_at'],
23
- is_partitioned: row['is_partitioned'],
24
- is_unlogged: row['is_unlogged']
21
+ queue_name: row["queue_name"],
22
+ created_at: row["created_at"],
23
+ is_partitioned: row["is_partitioned"],
24
+ is_unlogged: row["is_unlogged"]
25
25
  )
26
26
  end
27
27
  end
28
28
 
29
29
  # Alias for is_partitioned
30
30
  # @return [String] 't' or 'f' from PostgreSQL
31
- alias partitioned? is_partitioned
31
+ alias_method :partitioned?, :is_partitioned
32
32
 
33
33
  # Alias for is_unlogged
34
34
  # @return [String] 't' or 'f' from PostgreSQL
35
- alias unlogged? is_unlogged
35
+ alias_method :unlogged?, :is_unlogged
36
36
  end
37
37
  end
data/lib/pgmq/version.rb CHANGED
@@ -2,5 +2,5 @@
2
2
 
3
3
  module PGMQ
4
4
  # Current version of the pgmq-ruby gem
5
- VERSION = '0.4.0'
5
+ VERSION = "0.6.0"
6
6
  end
data/lib/pgmq.rb CHANGED
@@ -1,11 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'zeitwerk'
4
- require 'time'
3
+ require "zeitwerk"
4
+ require "time"
5
5
 
6
6
  loader = Zeitwerk::Loader.for_gem
7
7
  loader.inflector.inflect(
8
- 'pgmq' => 'PGMQ'
8
+ "pgmq" => "PGMQ"
9
9
  )
10
10
  loader.setup
11
11
  loader.eager_load
data/pgmq-ruby.gemspec CHANGED
@@ -1,32 +1,32 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'lib/pgmq/version'
3
+ require_relative "lib/pgmq/version"
4
4
 
5
5
  Gem::Specification.new do |spec|
6
- spec.name = 'pgmq-ruby'
6
+ spec.name = "pgmq-ruby"
7
7
  spec.version = PGMQ::VERSION
8
- spec.authors = ['Maciej Mensfeld']
9
- spec.email = ['maciej@mensfeld.pl']
8
+ spec.authors = ["Maciej Mensfeld"]
9
+ spec.email = ["maciej@mensfeld.pl"]
10
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'
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.3.0"
17
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'
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
24
 
25
- spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(spec|examples)/}) }
26
- spec.require_paths = ['lib']
25
+ spec.files = Dir["lib/**/*", "CHANGELOG.md", "LICENSE", "README.md", "pgmq-ruby.gemspec"]
26
+ spec.require_paths = ["lib"]
27
27
 
28
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'
29
+ spec.add_dependency "connection_pool", "~> 2.4"
30
+ spec.add_dependency "pg", "~> 1.5"
31
+ spec.add_dependency "zeitwerk", "~> 2.6"
32
32
  end
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.0
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Maciej Mensfeld
@@ -59,20 +59,9 @@ executables: []
59
59
  extensions: []
60
60
  extra_rdoc_files: []
61
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
62
  - CHANGELOG.md
70
- - Gemfile
71
- - Gemfile.lock
72
63
  - LICENSE
73
64
  - README.md
74
- - Rakefile
75
- - docker-compose.yml
76
65
  - lib/pgmq.rb
77
66
  - lib/pgmq/client.rb
78
67
  - lib/pgmq/client/consumer.rb
@@ -82,6 +71,7 @@ files:
82
71
  - lib/pgmq/client/multi_queue.rb
83
72
  - lib/pgmq/client/producer.rb
84
73
  - lib/pgmq/client/queue_management.rb
74
+ - lib/pgmq/client/topics.rb
85
75
  - lib/pgmq/connection.rb
86
76
  - lib/pgmq/errors.rb
87
77
  - lib/pgmq/message.rb
@@ -90,7 +80,6 @@ files:
90
80
  - lib/pgmq/transaction.rb
91
81
  - lib/pgmq/version.rb
92
82
  - pgmq-ruby.gemspec
93
- - renovate.json
94
83
  homepage: https://github.com/mensfeld/pgmq-ruby
95
84
  licenses:
96
85
  - LGPL-3.0
@@ -108,14 +97,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
108
97
  requirements:
109
98
  - - ">="
110
99
  - !ruby/object:Gem::Version
111
- version: 3.2.0
100
+ version: 3.3.0
112
101
  required_rubygems_version: !ruby/object:Gem::Requirement
113
102
  requirements:
114
103
  - - ">="
115
104
  - !ruby/object:Gem::Version
116
105
  version: '0'
117
106
  requirements: []
118
- rubygems_version: 4.0.3
107
+ rubygems_version: 4.0.6
119
108
  specification_version: 4
120
109
  summary: Ruby client for PGMQ (Postgres Message Queue)
121
110
  test_files: []
data/.coditsu/ci.yml DELETED
@@ -1,3 +0,0 @@
1
- repository_id: '401d7537-5ac7-4691-ae02-f11fb24646d9'
2
- api_key: <%= ENV['CODITSU_API_KEY'] %>
3
- api_secret: <%= ENV['CODITSU_API_SECRET'] %>