surfliner-metadata_consumer 0.1.0.pre.alpha.1 → 0.1.0.pre.alpha.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 60c60314d3c25079cbd39bca122dde8f505cf1060785420928b9e1cb2d105194
4
- data.tar.gz: 9b772b1024ca85075794c744d56bc977cf912d72262406c1fb03f906045c22c4
3
+ metadata.gz: fac43306c988b19a28f9cb92449724b7cb326a787f54c7da78c9b134a61220aa
4
+ data.tar.gz: af91a86d088e4b863425a45faf97b2473cbca69cb17178d75d4bcce19d79384a
5
5
  SHA512:
6
- metadata.gz: 4c97ddf2912e8eebe8ce02f3769b4de525154953d7c24297d384ed6313963e0ed85fc4462143359320799ad18da38c43ebcaa88100988e5bd21187d19fcb9e50
7
- data.tar.gz: c300e50c84ba5ecd631ec9307214ba879b08e2444ca633b11122c85e62e9a02d4d4397867fadbd79a42698d7feef09f36f26c57a947a0b03b335b47cbde21c28
6
+ metadata.gz: ea1dbf415bd4339f875562a7f629ea432915e3dc1b511ba1268765069db0227031dc5eb71e2acfcb7f4b5c434a3c82ba88b4cc266dec94b94479462ae3721781
7
+ data.tar.gz: d0840fc308daec6d1ed9f22038f62e2ed4974ea450054b3bec580e1a28f8aff52c5081cfd600e46137546785cc726a420190b0bdf82a0eb7f0c2db5fa447736b
data/CHANGES.md CHANGED
@@ -1,3 +1,14 @@
1
+ # 0.1.0.pre.alpha.3 (2025-03-07)
2
+
3
+ - improve topic/queue option override API
4
+ - clean up binscripts
5
+
6
+ # 0.1.0.pre.alpha.2 (2025-03-07)
7
+
8
+ - use METADATA_API_URL_BASE cf. surfliner apps
9
+ - allow overriding topic and queue options
10
+ - don't close channel if already closed
11
+
1
12
  # 0.1.0.pre.alpha.1 (2025-02-12)
2
13
 
3
14
  - CI pipeline gem release test
data/Gemfile CHANGED
@@ -2,5 +2,4 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
- # Specify your gem's dependencies in surfliner_schema.gemspec
6
5
  gemspec
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- surfliner-metadata_consumer (0.1.0.pre.alpha.1)
4
+ surfliner-metadata_consumer (0.1.0.pre.alpha.3)
5
5
  bunny (~> 2.23)
6
6
  opentelemetry-exporter-otlp (~> 0.26.3)
7
7
  opentelemetry-instrumentation-all (~> 0.60.0)
@@ -13,7 +13,7 @@ GEM
13
13
  specs:
14
14
  addressable (2.8.7)
15
15
  public_suffix (>= 2.0.2, < 7.0)
16
- amq-protocol (2.3.2)
16
+ amq-protocol (2.3.3)
17
17
  ast (2.4.2)
18
18
  bigdecimal (3.1.9)
19
19
  builder (3.3.0)
@@ -34,7 +34,7 @@ GEM
34
34
  debug (1.9.2)
35
35
  irb (~> 1.10)
36
36
  reline (>= 0.3.8)
37
- diff-lcs (1.5.1)
37
+ diff-lcs (1.6.0)
38
38
  docile (1.4.1)
39
39
  dotenv (2.8.1)
40
40
  faraday (2.12.2)
@@ -55,11 +55,11 @@ GEM
55
55
  json (2.10.1)
56
56
  language_server-protocol (3.17.0.4)
57
57
  lint_roller (1.1.0)
58
- logger (1.6.5)
58
+ logger (1.6.6)
59
59
  net-http (0.6.0)
60
60
  uri
61
- opentelemetry-api (1.4.0)
62
- opentelemetry-common (0.21.0)
61
+ opentelemetry-api (1.5.0)
62
+ opentelemetry-common (0.22.0)
63
63
  opentelemetry-api (~> 1.0)
64
64
  opentelemetry-exporter-otlp (0.26.3)
65
65
  google-protobuf (~> 3.14)
@@ -245,14 +245,14 @@ GEM
245
245
  opentelemetry-helpers-sql-obfuscation
246
246
  opentelemetry-instrumentation-base (~> 0.22.1)
247
247
  opentelemetry-semantic_conventions (>= 1.8.0)
248
- opentelemetry-registry (0.3.1)
248
+ opentelemetry-registry (0.4.0)
249
249
  opentelemetry-api (~> 1.1)
250
250
  opentelemetry-sdk (1.4.1)
251
251
  opentelemetry-api (~> 1.1)
252
252
  opentelemetry-common (~> 0.20)
253
253
  opentelemetry-registry (~> 0.2)
254
254
  opentelemetry-semantic_conventions
255
- opentelemetry-semantic_conventions (1.10.1)
255
+ opentelemetry-semantic_conventions (1.11.0)
256
256
  opentelemetry-api (~> 1.0)
257
257
  parallel (1.26.3)
258
258
  parser (3.3.7.1)
@@ -274,7 +274,7 @@ GEM
274
274
  regexp_parser (2.10.0)
275
275
  reline (0.6.0)
276
276
  io-console (~> 0.5)
277
- rexml (3.4.0)
277
+ rexml (3.4.1)
278
278
  rsolr (2.6.0)
279
279
  builder (>= 2.1.2)
280
280
  faraday (>= 0.9, < 3, != 2.0.0)
@@ -301,7 +301,7 @@ GEM
301
301
  rubocop-ast (>= 1.38.0, < 2.0)
302
302
  ruby-progressbar (~> 1.7)
303
303
  unicode-display_width (>= 2.4.0, < 4.0)
304
- rubocop-ast (1.38.0)
304
+ rubocop-ast (1.38.1)
305
305
  parser (>= 3.3.1.0)
306
306
  rubocop-performance (1.23.1)
307
307
  rubocop (>= 1.48.1, < 2.0)
@@ -332,11 +332,11 @@ GEM
332
332
  standard-performance (1.6.0)
333
333
  lint_roller (~> 1.1)
334
334
  rubocop-performance (~> 1.23.0)
335
- stringio (3.1.2)
335
+ stringio (3.1.5)
336
336
  unicode-display_width (3.1.4)
337
337
  unicode-emoji (~> 4.0, >= 4.0.4)
338
338
  unicode-emoji (4.0.4)
339
- uri (1.0.2)
339
+ uri (1.0.3)
340
340
  webmock (3.25.0)
341
341
  addressable (>= 2.8.0)
342
342
  crack (>= 0.3.2)
data/README.md CHANGED
@@ -61,11 +61,11 @@ a configured `SOLR_URL`, e.g.:
61
61
  SOLR_URL=http://admin:admin@solr:8983/solr/daylight-dev
62
62
  ```
63
63
 
64
- The `bin/simulate-publish-event` script expects an `API_BASE_URI`, used to generate resource URLs
64
+ The `bin/simulate-publish-event` script expects an `METADATA_API_URL_BASE`, used to generate resource URLs
65
65
  for provided IDs:
66
66
 
67
67
  ```sh
68
- API_BASE_URI=http://superskunk:3000
68
+ METADATA_API_URL_BASE=http://superskunk:3000/resources
69
69
  ```
70
70
 
71
71
  ## Solr / Daylight handler implementation
@@ -2,12 +2,8 @@
2
2
  require "bundler/setup"
3
3
  require "logger"
4
4
  require "opentelemetry/sdk"
5
- require "surfliner/metadata_consumer"
6
-
7
- $stdout.sync = true # don't buffer log output
8
5
 
9
- logger = Logger.new($stdout)
10
- logger.level = ENV.fetch("LOG_LEVEL") { Logger::INFO }
6
+ require "surfliner/metadata_consumer"
11
7
 
12
8
  unless ENV["OTEL_SDK_DISABLED"] == "true"
13
9
  OpenTelemetry::SDK.configure do |c|
@@ -15,9 +11,13 @@ unless ENV["OTEL_SDK_DISABLED"] == "true"
15
11
  c.use_all # enables auto instrumentation for Bunny, Net::HTTP, etc...
16
12
  end
17
13
  end
14
+ tracer = OpenTelemetry.tracer_provider.tracer("DaylightConsumerTracer")
18
15
 
19
- tracer = OpenTelemetry.tracer_provider.tracer("DaylightConsumerTracer")
20
-
21
- handler = Surfliner::MetadataConsumer::Solr::MessageHandler
16
+ $stdout.sync = true # don't buffer log output
17
+ logger = Logger.new($stdout).tap do |logger|
18
+ logger.level = ENV.fetch("LOG_LEVEL", Logger::INFO)
19
+ end
22
20
 
23
- Surfliner::MetadataConsumer::Consumer.run(logger:, tracer:, handler:)
21
+ handler = Surfliner::MetadataConsumer::Solr::MessageHandler
22
+ consumer = Surfliner::MetadataConsumer::Consumer.new(tracer:, logger:, handler:)
23
+ consumer.run
@@ -1,31 +1,56 @@
1
1
  #!/usr/bin/env ruby
2
2
  require "bundler/setup"
3
- require "date"
4
3
  require "json"
5
4
  require "logger"
6
5
 
7
- require "surfliner/metadata_consumer/mq_connection"
6
+ require "surfliner/metadata_consumer"
8
7
 
9
- api_base = ENV.fetch("API_BASE_URI") { "http://example.com/api" }
10
- logger = Logger.new($stdout)
11
- logger.level = ENV.fetch("LOG_LEVEL") { Logger::INFO }
8
+ module Surfliner
9
+ module MetadataConsumer
10
+ class Publisher
12
11
 
13
- connection = Surfliner::MetadataConsumer::MqConnection.new(logger: logger).connect
12
+ attr_reader :logger
13
+ attr_reader :topic_opts
14
+ attr_reader :queue_opts
14
15
 
16
+ def initialize(logger:, topic_opts: {}, queue_opts: {})
17
+ @logger = logger
18
+ @topic_opts = topic_opts
19
+ @queue_opts = queue_opts
20
+ end
21
+
22
+ def publish(resource_id)
23
+ payload = payload_for(resource_id)
24
+ connection.publish(payload)
25
+ end
26
+
27
+ def payload_for(id)
28
+ { resourceUrl: "#{api_base}/#{id}",
29
+ status: :published,
30
+ time_stamp: DateTime.now }.to_json
31
+ end
32
+
33
+ def connection
34
+ @connection ||= MqConnection.new(logger:).connect(topic_opts:, queue_opts:)
35
+ end
36
+
37
+ def api_base
38
+ @api_base ||= ENV.fetch("METADATA_API_URL_BASE", "http://metadata.test/resources")
39
+ end
40
+ end
41
+ end
42
+ end
43
+
44
+ $stdout.sync = true # don't buffer log output
45
+ logger = Logger.new($stdout).tap do |logger|
46
+ logger.level = ENV.fetch("LOG_LEVEL", Logger::INFO)
47
+ end
48
+
49
+ publisher = Surfliner::MetadataConsumer::Publisher.new(logger:)
15
50
  begin
16
- ARGV.each do |id|
17
- payload =
18
- {resourceUrl: "#{api_base}/resources/#{id}",
19
- status: :published,
20
- time_stamp: DateTime.now}.to_json
21
-
22
- logger.info "Publishing to #{connection.routing_key} with #{payload}"
23
- connection.exchange.publish(payload, routing_key: connection.routing_key)
51
+ ARGV.each do |resource_id|
52
+ publisher.publish(resource_id)
24
53
  end
25
54
  ensure
26
- begin
27
- connection&.channel
28
- ensure
29
- connection&.close
30
- end
55
+ publisher.connection.close
31
56
  end
@@ -20,28 +20,29 @@ module Surfliner
20
20
  @handler = handler
21
21
  end
22
22
 
23
- # Initializes and starts a new `Consumer`
24
- # @param tracer [OpenTelemetry::Trace::Tracer] OpenTelemetry tracer
25
- # @param logger [Logger] log message destination
26
- # @param handler #handle an object accepting a JSON string payload
27
- def self.run(tracer:, logger:, handler:)
28
- new(tracer:, logger:, handler:).run
29
- end
30
-
31
23
  # Starts listening to the message queue and passing messages to the handler.
32
- def run
33
- connection.open do |queue|
24
+ # @param queue_opts [Hash] RabbitMQ queue options. (See Bunny::Channel#queue)
25
+ # @param topic_opts [Hash] RabbitMQ topic options. (See Bunny::Channel#topic)
26
+ def run(queue_opts: {}, topic_opts: {})
27
+ connection.open(queue_opts:, topic_opts:) do |queue|
34
28
  queue.subscribe(block: true) do |_delivery_info, _properties, payload_json|
35
29
  tracer.in_span("surfliner metadata consumer message") do |_span|
36
- logger.info(" [  ] message received with payload: #{payload_json}")
37
-
38
- handler.handle(payload_json)
30
+ handle(payload_json)
39
31
  end
40
- rescue => err
41
- logger.error(" [❌] failed to handle message: #{err}\n#{err.backtrace}")
42
32
  end
43
33
  end
44
34
  end
35
+
36
+ # Dispatches the specified payload to the handler.
37
+ # @param payload_json [String] JSON message payload
38
+ def handle(payload_json)
39
+ logger.info(" [→] message received with payload: #{payload_json}")
40
+
41
+ handler.handle(payload_json)
42
+ logger.info(" [✓] message handled")
43
+ rescue => err
44
+ logger.error(" [!] failed to handle message: #{err.full_message}")
45
+ end
45
46
  end
46
47
  end
47
48
  end
@@ -32,17 +32,19 @@ module Surfliner
32
32
  end
33
33
 
34
34
  # Opens a connection.
35
+ # @param topic_opts [Hash] RabbitMQ topic options. (See Bunny::Channel#topic)
36
+ # @param queue_opts [Hash] RabbitMQ queue options. (See Bunny::Channel#queue)
35
37
  # @return [self]
36
38
  # @raise RuntimeError if already connected
37
- def connect
39
+ def connect(topic_opts: {}, queue_opts: {})
38
40
  raise "RabbitMQ connection #{connection} already open." if open?
39
41
 
40
42
  logger.info("Rabbitmq message broker connection url: #{config.redacted_url}")
41
43
  @connection = Bunny.new(config.connection_url, logger: logger)
42
44
  connect_on(connection)
43
45
  @channel = connection.create_channel
44
- @exchange = channel.topic(config.topic, auto_delete: true)
45
- @queue = channel.queue(config.queue_name, durable: true)
46
+ @exchange = channel.topic(config.topic, topic_opts)
47
+ @queue = channel.queue(config.queue_name, queue_opts)
46
48
  queue.bind(exchange, routing_key: config.routing_key)
47
49
 
48
50
  self
@@ -58,9 +60,11 @@ module Surfliner
58
60
 
59
61
  # Opens a connection, yields the queue, and closes the connection after
60
62
  # the provided block completes.
63
+ # @param topic_opts [Hash] RabbitMQ topic options. (See Bunny::Channel#topic)
64
+ # @param queue_opts [Hash] RabbitMQ queue options. (See Bunny::Channel#queue)
61
65
  # @yield [Bunny::Queue] the queue
62
- def open
63
- connect
66
+ def open(topic_opts: {}, queue_opts: {})
67
+ connect(topic_opts:, queue_opts:)
64
68
  yield queue
65
69
  ensure
66
70
  close
@@ -68,8 +72,12 @@ module Surfliner
68
72
 
69
73
  # Closes the connection.
70
74
  def close
71
- channel&.close
75
+ return unless channel
76
+ return if channel.closed?
77
+ logger.info("closing channel")
78
+ channel.close
72
79
  ensure
80
+ logger.info("closing connection")
73
81
  connection&.close
74
82
  end
75
83
 
@@ -93,6 +101,19 @@ module Surfliner
93
101
  config.port
94
102
  end
95
103
 
104
+ # @return [String] The routing key
105
+ def routing_key
106
+ config.routing_key
107
+ end
108
+
109
+ # Publishes the specified payload
110
+ # @param payload [String] the payload to publish
111
+ # @return [Bunny::Exchange] see #exchange
112
+ def publish(payload)
113
+ logger.info "Publishing to #{routing_key} with payload: #{payload}"
114
+ exchange.publish(payload, routing_key:)
115
+ end
116
+
96
117
  private
97
118
 
98
119
  def connect_on(connection, timeout = 120)
@@ -3,6 +3,6 @@ module Surfliner
3
3
  # Parent module for this gem
4
4
  module MetadataConsumer
5
5
  # The gem version
6
- VERSION = "0.1.0.pre.alpha.1"
6
+ VERSION = "0.1.0.pre.alpha.3"
7
7
  end
8
8
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: surfliner-metadata_consumer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0.pre.alpha.1
4
+ version: 0.1.0.pre.alpha.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Project Surfliner
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2025-02-12 00:00:00.000000000 Z
10
+ date: 2025-03-07 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: bunny