surfliner-metadata_consumer 0.1.0.pre.alpha.4 → 0.1.0.pre.alpha.6
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/CHANGES.md +46 -1
- data/Dockerfile +1 -1
- data/Gemfile.lock +35 -29
- data/README.md +61 -22
- data/bin/index-on-publish +33 -0
- data/bin/simulate-publish-event +30 -20
- data/lib/surfliner/metadata_consumer/consumer.rb +41 -17
- data/lib/surfliner/metadata_consumer/version.rb +1 -2
- data/lib/surfliner/metadata_consumer.rb +4 -1
- data/lib/surfliner/mq/connection.rb +135 -0
- data/lib/surfliner/mq/connection_config.rb +83 -0
- data/lib/surfliner/mq/queue_config.rb +49 -0
- data/lib/surfliner/mq/topic.rb +65 -0
- data/lib/surfliner/mq/topic_config.rb +37 -0
- data/lib/surfliner/mq.rb +4 -0
- data/lib/surfliner/util/assert.rb +21 -0
- data/lib/surfliner/util.rb +4 -0
- metadata +64 -30
- data/bin/daylight-index-listen +0 -23
- data/lib/surfliner/metadata_consumer/mq_config.rb +0 -79
- data/lib/surfliner/metadata_consumer/mq_connection.rb +0 -136
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 25566009d8ccce03904d9020a0340511bbeb2fac08b5151c65705cd2d6117096
|
4
|
+
data.tar.gz: 24136a3ca25672bf7fcc8670ea61f11a34c547b515022f92e46b440fe1d315cc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fef5c2196922e8f5476422ffd83400bc17edc957b0822a323628dd9cd525440e231e1d7402b761c71894806282c2ad11c8c450eb6dc37a6a6e99dac7d3adc9c5
|
7
|
+
data.tar.gz: 5014bdadb04910ca9888d8fe445342641462e33f6ec445333c4502dd322e428df5c5ecd01710018d7f905e80a889ce84815f7ff59b1d3908c00b405d5f02c048
|
data/CHANGES.md
CHANGED
@@ -1,3 +1,48 @@
|
|
1
|
+
# 0.1.0.pre.alpha.6 (2025-04-25)
|
2
|
+
|
3
|
+
- Update to Bunny 2.24
|
4
|
+
- Allow `Mq::Connection#connect` to take a block, in which case the method
|
5
|
+
yields the open connection, closing the connection and channel afterwards.
|
6
|
+
- Add an option `await_response_on_close` to `Mq::ConnectionConfig`, defaulting
|
7
|
+
to true, to indicate whether the RabbitMQ client should wait for a response
|
8
|
+
when closing a session, along with a corresponding environment variable
|
9
|
+
`RABBITMQ_AWAIT_ON_CLOSE`
|
10
|
+
- Allows passing additional options to `Mq:ConnectionConfig#initialize` and
|
11
|
+
`#from_env`, which will then be passed to `Bunny::Session#initialize`
|
12
|
+
|
13
|
+
# 0.1.0.pre.alpha.5 (2025-03-25)
|
14
|
+
|
15
|
+
In order to support using one connection (and one underlying `Bunny::Session`)
|
16
|
+
with multiple topics, queues, and/or routing keys, as well as publishing to
|
17
|
+
a topic without creating or subscribing to a queue, this release introduces
|
18
|
+
the following **breaking changes**:
|
19
|
+
|
20
|
+
- RabbitMQ-related configuration and connection code (i.e. not specific to
|
21
|
+
the consumer/handler setup) has been moved from `Surfliner::MetadataConsumer`
|
22
|
+
to `Surfliner::Mq`. This may move to a separate gem in a future release.
|
23
|
+
- `MetadataConsumer::MqConnection` is now `Mq::Connection`
|
24
|
+
- `MetadataConsumer::MqConfig` is now `Mq::ConnectionConfig`
|
25
|
+
- `ConnectionConfig` no longer includes topic or queue configuration;
|
26
|
+
topics are configured with `TopicConfig` and queues with
|
27
|
+
`QueueConfig`.
|
28
|
+
- The `MqConnection#open` method, which yielded a `Bunny::Queue`, has been
|
29
|
+
replaced by the `Connection#with_topic` method, which yields an
|
30
|
+
`Mq::Topic` object wrapping a single topic; call `Mq::Topic#bind_queue`
|
31
|
+
to bind to a queue. Like the removed`#open`, `#with_topic` opens and
|
32
|
+
closes the connection implicitly and allows connecting only to a single
|
33
|
+
topic.
|
34
|
+
- The `Mq::Connection#topic_from(config)` method allows you to connect to
|
35
|
+
any number of topics, but you must open and close the connection
|
36
|
+
explicitly.
|
37
|
+
- The `MqConnection#publish` method has been moved to `Mq::Topic` and can
|
38
|
+
now take an explicit routing key, although if one is not provided it will
|
39
|
+
still default to `ENV["RABBITMQ_PLATFORM_ROUTING_KEY"]`.
|
40
|
+
- `MetadataConsumer::Consumer` now requires an explicit `Mq:Connection`
|
41
|
+
instead of creating one by default.
|
42
|
+
|
43
|
+
In addition, the `daylight-index-listen` script has been renamed to the more
|
44
|
+
generic `index-on-publish`.
|
45
|
+
|
1
46
|
# 0.1.0.pre.alpha.4 (2025-03-17)
|
2
47
|
|
3
48
|
- lower required Ruby version to 3.2
|
@@ -19,4 +64,4 @@
|
|
19
64
|
|
20
65
|
# 0.1.0.pre.alpha (2025-02-12)
|
21
66
|
|
22
|
-
- Initial release
|
67
|
+
- Initial release
|
data/Dockerfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
surfliner-metadata_consumer (0.1.0.pre.alpha.
|
5
|
-
bunny (~> 2.
|
4
|
+
surfliner-metadata_consumer (0.1.0.pre.alpha.6)
|
5
|
+
bunny (~> 2.24)
|
6
6
|
opentelemetry-exporter-otlp (~> 0.26.3)
|
7
7
|
opentelemetry-instrumentation-all (~> 0.60.0)
|
8
8
|
opentelemetry-sdk (~> 1.4.1)
|
@@ -14,11 +14,11 @@ GEM
|
|
14
14
|
addressable (2.8.7)
|
15
15
|
public_suffix (>= 2.0.2, < 7.0)
|
16
16
|
amq-protocol (2.3.3)
|
17
|
-
ast (2.4.
|
17
|
+
ast (2.4.3)
|
18
18
|
bigdecimal (3.1.9)
|
19
19
|
builder (3.3.0)
|
20
|
-
bunny (2.
|
21
|
-
amq-protocol (~> 2.3
|
20
|
+
bunny (2.24.0)
|
21
|
+
amq-protocol (~> 2.3)
|
22
22
|
sorted_set (~> 1, >= 1.0.2)
|
23
23
|
ci_reporter (2.1.0)
|
24
24
|
builder (>= 2.1.2)
|
@@ -34,28 +34,29 @@ GEM
|
|
34
34
|
debug (1.9.2)
|
35
35
|
irb (~> 1.10)
|
36
36
|
reline (>= 0.3.8)
|
37
|
-
diff-lcs (1.6.
|
37
|
+
diff-lcs (1.6.1)
|
38
38
|
docile (1.4.1)
|
39
39
|
dotenv (2.8.1)
|
40
|
-
faraday (2.
|
40
|
+
faraday (2.13.1)
|
41
41
|
faraday-net_http (>= 2.0, < 3.5)
|
42
42
|
json
|
43
43
|
logger
|
44
44
|
faraday-net_http (3.4.0)
|
45
45
|
net-http (>= 0.5.0)
|
46
|
-
|
47
|
-
|
46
|
+
github-markup (5.0.1)
|
47
|
+
google-protobuf (3.25.7)
|
48
|
+
googleapis-common-protos-types (1.19.0)
|
48
49
|
google-protobuf (>= 3.18, < 5.a)
|
49
50
|
hashdiff (1.1.2)
|
50
51
|
io-console (0.8.0)
|
51
|
-
irb (1.15.
|
52
|
+
irb (1.15.2)
|
52
53
|
pp (>= 0.6.0)
|
53
54
|
rdoc (>= 4.0.0)
|
54
55
|
reline (>= 0.4.2)
|
55
|
-
json (2.
|
56
|
+
json (2.11.3)
|
56
57
|
language_server-protocol (3.17.0.4)
|
57
58
|
lint_roller (1.1.0)
|
58
|
-
logger (1.
|
59
|
+
logger (1.7.0)
|
59
60
|
net-http (0.6.0)
|
60
61
|
uri
|
61
62
|
opentelemetry-api (1.5.0)
|
@@ -254,13 +255,14 @@ GEM
|
|
254
255
|
opentelemetry-semantic_conventions
|
255
256
|
opentelemetry-semantic_conventions (1.11.0)
|
256
257
|
opentelemetry-api (~> 1.0)
|
257
|
-
parallel (1.
|
258
|
-
parser (3.3.
|
258
|
+
parallel (1.27.0)
|
259
|
+
parser (3.3.8.0)
|
259
260
|
ast (~> 2.4.1)
|
260
261
|
racc
|
261
262
|
pp (0.6.2)
|
262
263
|
prettyprint
|
263
264
|
prettyprint (0.2.0)
|
265
|
+
prism (1.4.0)
|
264
266
|
psych (5.2.3)
|
265
267
|
date
|
266
268
|
stringio
|
@@ -269,10 +271,11 @@ GEM
|
|
269
271
|
rainbow (3.1.1)
|
270
272
|
rake (13.2.1)
|
271
273
|
rbtree (0.4.6)
|
272
|
-
rdoc (6.
|
274
|
+
rdoc (6.13.1)
|
273
275
|
psych (>= 4.0.0)
|
276
|
+
redcarpet (3.6.1)
|
274
277
|
regexp_parser (2.10.0)
|
275
|
-
reline (0.6.
|
278
|
+
reline (0.6.1)
|
276
279
|
io-console (~> 0.5)
|
277
280
|
rexml (3.4.1)
|
278
281
|
rsolr (2.6.0)
|
@@ -291,7 +294,7 @@ GEM
|
|
291
294
|
diff-lcs (>= 1.2.0, < 2.0)
|
292
295
|
rspec-support (~> 3.13.0)
|
293
296
|
rspec-support (3.13.2)
|
294
|
-
rubocop (1.
|
297
|
+
rubocop (1.75.3)
|
295
298
|
json (~> 2.3)
|
296
299
|
language_server-protocol (~> 3.17.0.2)
|
297
300
|
lint_roller (~> 1.1.0)
|
@@ -299,14 +302,15 @@ GEM
|
|
299
302
|
parser (>= 3.3.0.2)
|
300
303
|
rainbow (>= 2.2.2, < 4.0)
|
301
304
|
regexp_parser (>= 2.9.3, < 3.0)
|
302
|
-
rubocop-ast (>= 1.
|
305
|
+
rubocop-ast (>= 1.44.0, < 2.0)
|
303
306
|
ruby-progressbar (~> 1.7)
|
304
307
|
unicode-display_width (>= 2.4.0, < 4.0)
|
305
|
-
rubocop-ast (1.
|
306
|
-
parser (>= 3.3.
|
307
|
-
|
308
|
+
rubocop-ast (1.44.1)
|
309
|
+
parser (>= 3.3.7.2)
|
310
|
+
prism (~> 1.4)
|
311
|
+
rubocop-performance (1.25.0)
|
308
312
|
lint_roller (~> 1.1)
|
309
|
-
rubocop (>= 1.
|
313
|
+
rubocop (>= 1.75.0, < 2.0)
|
310
314
|
rubocop-ast (>= 1.38.0, < 2.0)
|
311
315
|
ruby-progressbar (1.13.0)
|
312
316
|
set (1.1.1)
|
@@ -322,19 +326,19 @@ GEM
|
|
322
326
|
sorted_set (1.0.3)
|
323
327
|
rbtree
|
324
328
|
set (~> 1.0)
|
325
|
-
standard (1.
|
329
|
+
standard (1.49.0)
|
326
330
|
language_server-protocol (~> 3.17.0.2)
|
327
331
|
lint_roller (~> 1.0)
|
328
|
-
rubocop (~> 1.
|
332
|
+
rubocop (~> 1.75.2)
|
329
333
|
standard-custom (~> 1.0.0)
|
330
|
-
standard-performance (~> 1.
|
334
|
+
standard-performance (~> 1.8)
|
331
335
|
standard-custom (1.0.2)
|
332
336
|
lint_roller (~> 1.0)
|
333
337
|
rubocop (~> 1.50)
|
334
|
-
standard-performance (1.
|
338
|
+
standard-performance (1.8.0)
|
335
339
|
lint_roller (~> 1.1)
|
336
|
-
rubocop-performance (~> 1.
|
337
|
-
stringio (3.1.
|
340
|
+
rubocop-performance (~> 1.25.0)
|
341
|
+
stringio (3.1.7)
|
338
342
|
unicode-display_width (3.1.4)
|
339
343
|
unicode-emoji (~> 4.0, >= 4.0.4)
|
340
344
|
unicode-emoji (4.0.4)
|
@@ -354,7 +358,9 @@ DEPENDENCIES
|
|
354
358
|
colorize (~> 0.8)
|
355
359
|
debug (~> 1.9.2)
|
356
360
|
dotenv (~> 2.7)
|
361
|
+
github-markup (~> 5.0)
|
357
362
|
rake (~> 13.0)
|
363
|
+
redcarpet (~> 3.6)
|
358
364
|
rspec (~> 3.13)
|
359
365
|
simplecov (~> 0.22)
|
360
366
|
simplecov-cobertura (~> 2.1)
|
@@ -364,4 +370,4 @@ DEPENDENCIES
|
|
364
370
|
yard (~> 0.9.37)
|
365
371
|
|
366
372
|
BUNDLED WITH
|
367
|
-
2.6.
|
373
|
+
2.6.7
|
data/README.md
CHANGED
@@ -36,23 +36,60 @@ if prior steps succeed.
|
|
36
36
|
|
37
37
|
## Configuration
|
38
38
|
|
39
|
-
|
40
|
-
|
41
|
-
|
39
|
+
> Note: Sample values taken from Surfliner's development
|
40
|
+
> [daylight-listener.sh](https://gitlab.com/surfliner/surfliner/-/blob/trunk/docker-compose/env/daylight-listener.sh).)
|
41
|
+
|
42
|
+
An `Mq::Connection` object, suitable for listening or publishing, can be configured
|
43
|
+
explicitly with a `ConnectionConfig` object, or implicitly, reading a default
|
44
|
+
configuration with `ConnectionConfig#from_env`. `ConnectionConfig#from_env` expects
|
45
|
+
the following environment variables:
|
46
|
+
|
47
|
+
| Variable | Sample value | Description |
|
48
|
+
|-----------------------------|--------------|-----------------------------------------------------------|
|
49
|
+
| `RABBITMQ_HOST` | `rabbitmq` | Hostname of RabbitMQ server |
|
50
|
+
| `RABBITMQ_NODE_PORT_NUMBER` | `5672` | Port name of RabbitMQ server |
|
51
|
+
| `RABBITMQ_USERNAME` | `user` | RabbitMQ username |
|
52
|
+
| `RABBITMQ_PASSWORD` | `bitnami` | RabbitMQ password |
|
53
|
+
| `RABBITMQ_AWAIT_ON_CLOSE` | `false` | Whether to wait on response when closing (default = true) |
|
54
|
+
|
55
|
+
The `Mq::Connection#with_topic` and `Mq::Connection#topic_from` can either take an
|
56
|
+
explicit `TopicConfig` object, or implicitly read a default configuration with
|
57
|
+
`TopicConfig#from_env`. `TopicConfig#from_env` expects the following environment variables:
|
58
|
+
|
59
|
+
| Variable | Sample value | Description |
|
60
|
+
|------------------|----------------------|---------------------|
|
61
|
+
| `RABBITMQ_TOPIC` | `surfliner.metadata` | RabbitMQ topic name |
|
62
|
+
|
63
|
+
Note that `TopicConfig#from_env` also accepts keyword options, which are passed through
|
64
|
+
to [`Bunny::Channel#topic`](https://api.rubybunny.info/Bunny/Channel.html#topic-instance_method).
|
65
|
+
E.g.
|
66
|
+
|
67
|
+
```ruby
|
68
|
+
topic_config = TopicConfig.from_env(durable: true, auto_delete: true)
|
69
|
+
connection.with_topic(topic_config) do |topic|
|
70
|
+
# ...
|
71
|
+
end
|
72
|
+
```
|
42
73
|
|
43
|
-
|
74
|
+
Similarly, `Mq::Topic#bind_queue` can either take an explicit `QueueConfig`, or implicitly
|
75
|
+
read a default with `QueConfig#from_env`. `QueueConfig#from_env` expects the following environment
|
76
|
+
variables:
|
44
77
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
RABBITMQ_QUEUE=surfliner.metadata
|
50
|
-
RABBITMQ_PLATFORM_ROUTING_KEY=surfliner.metadata.daylight
|
51
|
-
RABBITMQ_TOPIC=surfliner.metadata
|
52
|
-
RABBITMQ_USERNAME=user
|
53
|
-
```
|
78
|
+
| Variable | Sample value | Description |
|
79
|
+
|---------------------------------|-------------------------------|----------------------|
|
80
|
+
| `RABBITMQ_QUEUE` | `surfliner.metadata` | RabbitMQ queue name |
|
81
|
+
| `RABBITMQ_PLATFORM_ROUTING_KEY` | `surfliner.metadata.daylight` | RabbitMQ routing key |
|
54
82
|
|
55
|
-
|
83
|
+
And `QueueConfig#from_env` similarly accepts keyword options, which are forwarded to
|
84
|
+
[`Bunny::Channel#queue`](https://api.rubybunny.info/Bunny/Channel.html#queue-instance_method):
|
85
|
+
|
86
|
+
```ruby
|
87
|
+
connection.with_topic(topic_config) do |topic|
|
88
|
+
queue_config = QueueConfig.from_env(exclusive: true, durable: true)
|
89
|
+
queue = topic.bind_queue(queue_config)
|
90
|
+
# ...
|
91
|
+
end
|
92
|
+
```
|
56
93
|
|
57
94
|
The Solr / Daylight handler implementation (see below) additionally expects
|
58
95
|
a configured `SOLR_URL`, e.g.:
|
@@ -74,17 +111,19 @@ The `Surfliner::MetadataConsumer::Solr` package contains a handler that retrieve
|
|
74
111
|
metadata for `:published`/`:updated` events, transforms results for indexing, and
|
75
112
|
updates a target Solr index.
|
76
113
|
|
77
|
-
|
114
|
+
The `bin/index-on-publish` script starts a consumer using this handler, and accepts
|
115
|
+
(but does not require) the following environment variables:
|
78
116
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
117
|
+
| Variable | Sample value | Default | Description |
|
118
|
+
|---------------------|-------------------------------|----------------|----------------------------------|
|
119
|
+
| `OTEL_SDK_DISABLED` | `true` | (not set) | Whether to disable OpenTelemetry |
|
120
|
+
| `OTEL_SERVICE_NAME` | `surfliner-daylight-consumer` | name of script | OpenTelemetry service name |
|
121
|
+
| `OTEL_TRACER_NAME` | `DaylightConsumerTracer` | name of script | OpenTelemetry tracer name |
|
83
122
|
|
84
123
|
### Running the service
|
85
124
|
|
86
125
|
<!--
|
87
|
-
TODO: Dockerfile shouldn't be
|
126
|
+
TODO: Dockerfile shouldn't be index-on-publish specific
|
88
127
|
-->
|
89
128
|
|
90
129
|
Build the listener Dockerfile and tag it with the name `solr-listener`:
|
@@ -101,5 +140,5 @@ docker run --env-file <env-file> solr-listener
|
|
101
140
|
|
102
141
|
## Utility scripts
|
103
142
|
|
104
|
-
- `bin/
|
105
|
-
- `bin/simulate-publish-event` posts a publish event to the queue configured with `
|
143
|
+
- `bin/index-on-publish` script starts a consumer using `MetadataConsumer::Solr::MessageHandler`.
|
144
|
+
- `bin/simulate-publish-event` posts a publish event to the queue configured with `Mq::Connection`
|
@@ -0,0 +1,33 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require "bundler/setup"
|
3
|
+
require "logger"
|
4
|
+
|
5
|
+
require "surfliner/metadata_consumer"
|
6
|
+
require "surfliner/mq"
|
7
|
+
|
8
|
+
$stdout.sync = true # don't buffer log output
|
9
|
+
logger = Logger.new($stdout).tap do |logger|
|
10
|
+
logger.level = ENV.fetch("LOG_LEVEL", Logger::INFO)
|
11
|
+
end
|
12
|
+
|
13
|
+
unless ENV["OTEL_SDK_DISABLED"] == "true"
|
14
|
+
require "opentelemetry/sdk"
|
15
|
+
require "opentelemetry-exporter-otlp"
|
16
|
+
|
17
|
+
otel_service_name = ENV.fetch('OTEL_SERVICE_NAME', File.basename(__FILE__))
|
18
|
+
otel_tracer_name = ENV.fetch('OTEL_TRACER_NAME', File.basename(__FILE__))
|
19
|
+
|
20
|
+
OpenTelemetry::SDK.configure do |c|
|
21
|
+
c.service_name = otel_service_name
|
22
|
+
c.use_all # enables auto instrumentation for Bunny, Net::HTTP, etc...
|
23
|
+
end
|
24
|
+
|
25
|
+
tracer = OpenTelemetry.tracer_provider.tracer(otel_tracer_name)
|
26
|
+
end
|
27
|
+
|
28
|
+
consumer = Surfliner::MetadataConsumer::Consumer.new(
|
29
|
+
connection: Surfliner::Mq::Connection.new(logger: logger),
|
30
|
+
tracer: (tracer if defined?(tracer)),
|
31
|
+
handler: Surfliner::MetadataConsumer::Solr::MessageHandler
|
32
|
+
)
|
33
|
+
consumer.run(topic_config: Surfliner::Mq::TopicConfig.from_env(auto_delete: true))
|
data/bin/simulate-publish-event
CHANGED
@@ -4,24 +4,24 @@ require "json"
|
|
4
4
|
require "logger"
|
5
5
|
|
6
6
|
require "surfliner/metadata_consumer"
|
7
|
+
require "surfliner/mq"
|
7
8
|
|
8
9
|
module Surfliner
|
9
10
|
module MetadataConsumer
|
10
11
|
class Publisher
|
12
|
+
attr_reader :topic
|
13
|
+
attr_reader :api_base
|
14
|
+
attr_reader :routing_key
|
11
15
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
def initialize(logger:, topic_opts: {}, queue_opts: {})
|
17
|
-
@logger = logger
|
18
|
-
@topic_opts = topic_opts
|
19
|
-
@queue_opts = queue_opts
|
16
|
+
def initialize(topic, api_base:, routing_key:)
|
17
|
+
@topic = topic
|
18
|
+
@api_base = api_base
|
19
|
+
@routing_key = routing_key
|
20
20
|
end
|
21
21
|
|
22
22
|
def publish(resource_id)
|
23
23
|
payload = payload_for(resource_id)
|
24
|
-
|
24
|
+
topic.publish(payload, routing_key:)
|
25
25
|
end
|
26
26
|
|
27
27
|
def payload_for(id)
|
@@ -30,27 +30,37 @@ module Surfliner
|
|
30
30
|
time_stamp: DateTime.now }.to_json
|
31
31
|
end
|
32
32
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
@
|
33
|
+
class << self
|
34
|
+
# Connects with default (environment-configured) settings, yields a publisher
|
35
|
+
# for the specified topic, and closes the connection after the provided block
|
36
|
+
# completes.
|
37
|
+
#
|
38
|
+
# @param logger [Logger] the logger
|
39
|
+
# @param topic_opts [Hash] RabbitMQ queue options. (See Bunny::Channel#queue)
|
40
|
+
#
|
41
|
+
# @yieldparam publisher [Publisher] the publisher
|
42
|
+
def connect(logger:, **topic_opts)
|
43
|
+
topic_config = Mq::TopicConfig.from_env(**topic_opts)
|
44
|
+
Mq::Connection.new(logger:).with_topic(topic_config) do |topic|
|
45
|
+
yield Publisher.new(
|
46
|
+
topic,
|
47
|
+
api_base: ENV.fetch("METADATA_API_URL_BASE", "http://metadata.test/resources"),
|
48
|
+
routing_key: ENV.fetch("RABBITMQ_PLATFORM_ROUTING_KEY")
|
49
|
+
)
|
50
|
+
end
|
51
|
+
end
|
39
52
|
end
|
40
53
|
end
|
41
54
|
end
|
42
55
|
end
|
43
56
|
|
44
57
|
$stdout.sync = true # don't buffer log output
|
45
|
-
logger
|
58
|
+
logger = Logger.new($stdout).tap do |logger|
|
46
59
|
logger.level = ENV.fetch("LOG_LEVEL", Logger::INFO)
|
47
60
|
end
|
48
61
|
|
49
|
-
|
50
|
-
begin
|
62
|
+
Surfliner::MetadataConsumer::Publisher.connect(logger:, auto_delete: true) do |publisher|
|
51
63
|
ARGV.each do |resource_id|
|
52
64
|
publisher.publish(resource_id)
|
53
65
|
end
|
54
|
-
ensure
|
55
|
-
publisher.connection.close
|
56
66
|
end
|
@@ -1,5 +1,8 @@
|
|
1
1
|
require "rsolr"
|
2
|
-
require "surfliner/
|
2
|
+
require "surfliner/util/assert"
|
3
|
+
require "surfliner/mq/connection"
|
4
|
+
require "surfliner/mq/topic_config"
|
5
|
+
require "surfliner/mq/queue_config"
|
3
6
|
require "surfliner/metadata_consumer/solr/message_handler"
|
4
7
|
|
5
8
|
module Surfliner
|
@@ -7,29 +10,40 @@ module Surfliner
|
|
7
10
|
# A metadata consumer that subscribes to a RabbitMQ queue and passes
|
8
11
|
# messages to the specified handler.
|
9
12
|
class Consumer
|
10
|
-
|
13
|
+
include Util::Assert
|
14
|
+
|
15
|
+
# @return [Mq::Connection] the connection
|
16
|
+
attr_reader :connection
|
17
|
+
|
18
|
+
# @return [OpenTelemetry::Trace::Tracer] OpenTelemetry tracer
|
19
|
+
attr_reader :tracer
|
20
|
+
|
21
|
+
# @return [#handle] an object accepting a JSON string
|
22
|
+
attr_reader :handler
|
11
23
|
|
12
24
|
# Initializes a new `Consumer`
|
25
|
+
#
|
26
|
+
# @param connection [Mq::Connection] the connection
|
27
|
+
# @param handler [#handle] an object accepting a JSON string
|
13
28
|
# @param tracer [OpenTelemetry::Trace::Tracer] OpenTelemetry tracer
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
@connection = MqConnection.new(logger:)
|
18
|
-
@logger = logger
|
29
|
+
def initialize(connection:, handler:, tracer: nil)
|
30
|
+
@connection = not_nil!(connection, "connection")
|
31
|
+
@handler = not_nil!(handler, "handler")
|
19
32
|
@tracer = tracer
|
20
|
-
|
33
|
+
end
|
34
|
+
|
35
|
+
# @return [Logger] log message destination
|
36
|
+
def logger
|
37
|
+
connection.logger
|
21
38
|
end
|
22
39
|
|
23
40
|
# Starts listening to the message queue and passing messages to the handler.
|
24
|
-
# @param
|
25
|
-
# @param
|
26
|
-
def run(
|
27
|
-
connection.
|
28
|
-
queue.
|
29
|
-
|
30
|
-
handle(payload_json)
|
31
|
-
end
|
32
|
-
end
|
41
|
+
# @param topic_config [TopicConfig] topic configuration
|
42
|
+
# @param queue_config [QueueConfig] queue configuration
|
43
|
+
def run(topic_config: Mq::TopicConfig.from_env, queue_config: Mq::QueueConfig.from_env)
|
44
|
+
connection.with_topic(topic_config) do |topic|
|
45
|
+
queue = topic.bind_queue(queue_config)
|
46
|
+
queue.subscribe(block: true, &method(:on_delivery))
|
33
47
|
end
|
34
48
|
end
|
35
49
|
|
@@ -43,6 +57,16 @@ module Surfliner
|
|
43
57
|
rescue => err
|
44
58
|
logger.error(" [!] failed to handle message: #{err.full_message}")
|
45
59
|
end
|
60
|
+
|
61
|
+
private
|
62
|
+
|
63
|
+
def on_delivery(_delivery_info, _properties, payload_json)
|
64
|
+
return handle(payload_json) unless tracer
|
65
|
+
|
66
|
+
tracer.in_span("surfliner metadata consumer message") do |_span, _context|
|
67
|
+
handle(payload_json)
|
68
|
+
end
|
69
|
+
end
|
46
70
|
end
|
47
71
|
end
|
48
72
|
end
|
@@ -1 +1,4 @@
|
|
1
|
-
Dir.glob(File.expand_path("metadata_consumer/*.rb", __dir__)).
|
1
|
+
Dir.glob(File.expand_path("metadata_consumer/*.rb", __dir__)).each(&method(:require))
|
2
|
+
|
3
|
+
# Functionality specific to consuming RabbitMQ feeds
|
4
|
+
module Surfliner::MetadataConsumer; end
|