cloudenvoy 0.5.0 → 0.6.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.rubocop.yml +16 -20
- data/CHANGELOG.md +9 -0
- data/README.md +39 -5
- data/cloudenvoy.gemspec +2 -2
- data/examples/rails/Gemfile +1 -1
- data/examples/rails/Gemfile.lock +2 -2
- data/examples/rails/README.md +4 -0
- data/examples/rails/app/subscribers/hello_subscriber.rb +1 -1
- data/examples/rails/config/environments/production.rb +1 -1
- data/examples/rails/config/puma.rb +3 -3
- data/examples/sinatra/Gemfile +1 -1
- data/examples/sinatra/Gemfile.lock +2 -2
- data/examples/sinatra/README.md +4 -0
- data/examples/sinatra/app/subscribers/hello_subscriber.rb +1 -1
- data/examples/sinatra/app.rb +4 -4
- data/lib/cloudenvoy/backend/google_pub_sub.rb +35 -3
- data/lib/cloudenvoy/backend/memory_pub_sub.rb +25 -1
- data/lib/cloudenvoy/config.rb +1 -1
- data/lib/cloudenvoy/message.rb +2 -2
- data/lib/cloudenvoy/pub_sub_client.rb +13 -1
- data/lib/cloudenvoy/publisher.rb +39 -5
- data/lib/cloudenvoy/publisher_logger.rb +1 -1
- data/lib/cloudenvoy/version.rb +1 -1
- data/lib/cloudenvoy.rb +12 -0
- metadata +7 -13
- data/gemfiles/rails_5.2.gemfile.lock +0 -276
- data/gemfiles/rails_6.0.gemfile.lock +0 -292
- data/gemfiles/semantic_logger_3.4.gemfile.lock +0 -171
- data/gemfiles/semantic_logger_4.6.gemfile.lock +0 -171
- data/gemfiles/semantic_logger_4.7.0.gemfile.lock +0 -171
- data/gemfiles/semantic_logger_4.7.2.gemfile.lock +0 -171
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cb4f27d4f01e971d8542f5768166caa9d797ad9799372bf167ddfe5e970ecb51
|
4
|
+
data.tar.gz: 5f2ed34bde0799fc94d574203f4589ede66b90da39a4f8e9bf4b6a8b41fac483
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6a71d84e06873d76352df8ccef0ee32f95a439e62447bf90e2a57694816753337186b6f57ad9864911d8bfec270eff31b8ccd0183c36f894ce030cd1b5c6ccb8
|
7
|
+
data.tar.gz: ac0be67ec3bc95c2b9cc32745dcbd72c87fcd06cf329dbf007cde92139b8c70a712545afc7e69bb44bd61397641989e1af7f8ff41bdeb82efe5400ca84993a58
|
data/.gitignore
CHANGED
data/.rubocop.yml
CHANGED
@@ -1,14 +1,13 @@
|
|
1
1
|
require: rubocop-rspec
|
2
2
|
|
3
3
|
AllCops:
|
4
|
+
NewCops: enable
|
4
5
|
Exclude:
|
5
6
|
- 'gemfiles/**/*'
|
6
7
|
- 'vendor/**/*'
|
7
8
|
|
8
|
-
|
9
|
-
|
10
|
-
Style/BracesAroundHashParameters:
|
11
|
-
Enabled: false
|
9
|
+
Layout/LineLength:
|
10
|
+
Max: 160
|
12
11
|
|
13
12
|
Metrics/ClassLength:
|
14
13
|
Max: 150
|
@@ -17,14 +16,20 @@ Metrics/ModuleLength:
|
|
17
16
|
Max: 150
|
18
17
|
|
19
18
|
Metrics/AbcSize:
|
20
|
-
Max:
|
21
|
-
|
22
|
-
Metrics/LineLength:
|
23
|
-
Max: 120
|
19
|
+
Max: 30
|
24
20
|
|
25
21
|
Metrics/MethodLength:
|
26
22
|
Max: 20
|
27
23
|
|
24
|
+
Metrics/BlockLength:
|
25
|
+
Exclude:
|
26
|
+
- cloudenvoy.gemspec
|
27
|
+
- lib/tasks/**/*
|
28
|
+
- 'spec/**/*'
|
29
|
+
|
30
|
+
Metrics/ParameterLists:
|
31
|
+
CountKeywordArgs: false
|
32
|
+
|
28
33
|
RSpec/ExpectInHook:
|
29
34
|
Enabled: false
|
30
35
|
|
@@ -34,19 +39,10 @@ RSpec/EmptyLineAfterHook:
|
|
34
39
|
RSpec/ScatteredSetup:
|
35
40
|
Enabled: false
|
36
41
|
|
37
|
-
|
38
|
-
|
39
|
-
- cloudenvoy.gemspec
|
40
|
-
- lib/tasks/**/*
|
41
|
-
- 'spec/**/*'
|
42
|
+
RSpec/MessageSpies:
|
43
|
+
Enabled: false
|
42
44
|
|
43
45
|
Style/Documentation:
|
44
46
|
Exclude:
|
45
47
|
- 'examples/**/*'
|
46
|
-
- 'spec/**/*'
|
47
|
-
|
48
|
-
Metrics/ParameterLists:
|
49
|
-
CountKeywordArgs: false
|
50
|
-
|
51
|
-
RSpec/MessageSpies:
|
52
|
-
Enabled: false
|
48
|
+
- 'spec/**/*'
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,14 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## [v0.6.rc1](https://github.com/keypup-io/cloudenvoy/tree/v0.6.rc1) (2022-04-11)
|
4
|
+
|
5
|
+
[Full Changelog](https://github.com/keypup-io/cloudenvoy/compare/v0.5.0...v0.6.rc1)
|
6
|
+
|
7
|
+
**Improvements:**
|
8
|
+
- Pub/sub: Add `publish_all` method to publish multiple messages in one batch
|
9
|
+
- Ruby: Drop support for Ruby `2.3`
|
10
|
+
- Style: Upgrade rubocop to `0.93.0`
|
11
|
+
|
3
12
|
## [v0.5.0](https://github.com/keypup-io/cloudenvoy/tree/v0.5.0) (2022-03-11)
|
4
13
|
|
5
14
|
[Full Changelog](https://github.com/keypup-io/cloudenvoy/compare/v0.4.2...v0.5.0)
|
data/README.md
CHANGED
@@ -35,9 +35,6 @@ Add this line to your application's Gemfile:
|
|
35
35
|
|
36
36
|
```ruby
|
37
37
|
gem 'cloudenvoy'
|
38
|
-
|
39
|
-
# For Ruby 3 support, please use v0.5.rc1
|
40
|
-
gem 'cloudenvoy, '~> 0.5.rc1'
|
41
38
|
```
|
42
39
|
|
43
40
|
And then execute:
|
@@ -136,7 +133,12 @@ rails s -p 3000
|
|
136
133
|
|
137
134
|
Open a Rails console and send a message
|
138
135
|
```ruby
|
136
|
+
# One message at a time
|
139
137
|
DummyPublisher.publish('Hello pub/sub')
|
138
|
+
|
139
|
+
# Publish multiple messages in one batch
|
140
|
+
# Only available since v0.6.rc1
|
141
|
+
DummyPublisher.publish_all(['Hello pub/sub', 'Hello again!', 'Hello again and again!'])
|
140
142
|
```
|
141
143
|
|
142
144
|
Your Rails logs should display the following:
|
@@ -252,10 +254,21 @@ DummySubscriber.setup
|
|
252
254
|
## Publishing messages
|
253
255
|
|
254
256
|
### Sending messages
|
257
|
+
**Note**: The `publish_all` method is only available since `v0.6.rc1`
|
255
258
|
|
256
259
|
Cloudenvoy provides a helper method to publish arbitrary messages to any topic.
|
257
260
|
```ruby
|
261
|
+
# Publish a single message
|
258
262
|
Cloudenvoy.publish('my-topic', { 'some' => 'payload' }, { 'optional' => 'message attribute' })
|
263
|
+
|
264
|
+
# Publish multiple messages in one batch
|
265
|
+
# Only available since v0.6.rc1
|
266
|
+
Cloudenvoy.publish_all('my-topic', [
|
267
|
+
# Message 1
|
268
|
+
[{ 'some' => 'msg1 payload' }, { 'optional' => 'msg1 attribute' }],
|
269
|
+
# Message 2
|
270
|
+
[{ 'some' => 'msg2 payload' }, { 'optional' => 'msg2 attribute' }]
|
271
|
+
])
|
259
272
|
```
|
260
273
|
|
261
274
|
This helper is useful for sending basic messages however it is not the preferred way of sending messages as you will quickly clutter your application with message formatting logic over time.
|
@@ -292,8 +305,21 @@ Then in your user model you can do the following:
|
|
292
305
|
class User < ApplicationRecord
|
293
306
|
after_create :publish_user
|
294
307
|
|
308
|
+
# Example: publish multiple messages in one batch
|
309
|
+
# Only available since v0.6.rc1
|
310
|
+
#
|
311
|
+
#
|
312
|
+
# Set user status to 'active' without involving callbacks
|
313
|
+
# then manually publish the new state of users in one batch
|
314
|
+
def self.enable_all_users
|
315
|
+
User.update_all(status: 'active', updated_at: Time.current)
|
316
|
+
UserPublisher.publish_all(User.all)
|
317
|
+
end
|
318
|
+
|
295
319
|
private
|
296
320
|
|
321
|
+
# Example: publish one message at a time
|
322
|
+
#
|
297
323
|
# Publish users after they have been created
|
298
324
|
def publish_user
|
299
325
|
UserPublisher.publish(self)
|
@@ -604,9 +630,17 @@ end
|
|
604
630
|
|
605
631
|
## Development
|
606
632
|
|
607
|
-
After checking out the repo, run `bin/setup` to install dependencies.
|
633
|
+
After checking out the repo, run `bin/setup` to install dependencies.
|
634
|
+
|
635
|
+
For tests, run `rake` to run the tests. Note that Rails is not in context by default, which means Rails-specific test will not run.
|
636
|
+
For tests including Rails-specific tests, run `bundle exec appraisal rails-7.0 rake`
|
637
|
+
For all context-specific tests (incl. Rails), run the [appraisal tests](Appraisals) using `bundle exec appraisal rake`.
|
638
|
+
|
639
|
+
You can run `bin/console` for an interactive prompt that will allow you to experiment.
|
640
|
+
|
641
|
+
To install this gem onto your local machine, run `bundle exec rake install`.
|
608
642
|
|
609
|
-
To
|
643
|
+
To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
610
644
|
|
611
645
|
## Contributing
|
612
646
|
|
data/cloudenvoy.gemspec
CHANGED
@@ -12,7 +12,7 @@ Gem::Specification.new do |spec|
|
|
12
12
|
spec.description = 'Cross-application messaging using GCP Pub/Sub (alpha)'
|
13
13
|
spec.homepage = 'https://github.com/keypup-io/cloudenvoy'
|
14
14
|
spec.license = 'MIT'
|
15
|
-
spec.required_ruby_version = Gem::Requirement.new('>= 2.
|
15
|
+
spec.required_ruby_version = Gem::Requirement.new('>= 2.4.0')
|
16
16
|
|
17
17
|
spec.metadata['homepage_uri'] = spec.homepage
|
18
18
|
spec.metadata['source_code_uri'] = 'https://github.com/keypup-io/cloudenvoy'
|
@@ -35,7 +35,7 @@ Gem::Specification.new do |spec|
|
|
35
35
|
spec.add_development_dependency 'appraisal'
|
36
36
|
spec.add_development_dependency 'rake', '>= 12.3.3'
|
37
37
|
spec.add_development_dependency 'rspec', '~> 3.0'
|
38
|
-
spec.add_development_dependency 'rubocop', '0.
|
38
|
+
spec.add_development_dependency 'rubocop', '0.93.0'
|
39
39
|
spec.add_development_dependency 'rubocop-rspec', '1.37.0'
|
40
40
|
spec.add_development_dependency 'semantic_logger'
|
41
41
|
spec.add_development_dependency 'timecop'
|
data/examples/rails/Gemfile
CHANGED
data/examples/rails/Gemfile.lock
CHANGED
@@ -160,7 +160,7 @@ GEM
|
|
160
160
|
racc (~> 1.4)
|
161
161
|
os (1.1.4)
|
162
162
|
public_suffix (4.0.6)
|
163
|
-
puma (5.6.
|
163
|
+
puma (5.6.4)
|
164
164
|
nio4r (~> 2.0)
|
165
165
|
racc (1.6.0)
|
166
166
|
rack (2.2.3)
|
@@ -222,7 +222,7 @@ PLATFORMS
|
|
222
222
|
|
223
223
|
DEPENDENCIES
|
224
224
|
cloudenvoy!
|
225
|
-
puma (~> 5.6.
|
225
|
+
puma (~> 5.6.4)
|
226
226
|
rails (~> 6.0.2)
|
227
227
|
sqlite3
|
228
228
|
|
data/examples/rails/README.md
CHANGED
@@ -12,6 +12,10 @@
|
|
12
12
|
HelloPublisher.publish('Some message')
|
13
13
|
```
|
14
14
|
7. Tail the logs to see how message get processed by `HelloSubscriber`
|
15
|
+
8. Try sending multiple messages at once:
|
16
|
+
```ruby
|
17
|
+
HelloPublisher.publish_all(['message1', 'message2', 'message3'])
|
18
|
+
```
|
15
19
|
|
16
20
|
## Run using GCP Pub/Sub
|
17
21
|
|
@@ -11,6 +11,6 @@ class HelloSubscriber
|
|
11
11
|
# @param [Cloudenvoy::Message] message The message to process.
|
12
12
|
#
|
13
13
|
def process(message)
|
14
|
-
logger.info("Received message #{message.payload
|
14
|
+
logger.info("Received message #{message.payload['content']}")
|
15
15
|
end
|
16
16
|
end
|
@@ -83,7 +83,7 @@ Rails.application.configure do
|
|
83
83
|
# config.logger = ActiveSupport::TaggedLogging.new(Syslog::Logger.new 'app-name')
|
84
84
|
|
85
85
|
if ENV['RAILS_LOG_TO_STDOUT'].present?
|
86
|
-
logger = ActiveSupport::Logger.new(
|
86
|
+
logger = ActiveSupport::Logger.new($stdout)
|
87
87
|
logger.formatter = config.log_formatter
|
88
88
|
config.logger = ActiveSupport::TaggedLogging.new(logger)
|
89
89
|
end
|
@@ -6,17 +6,17 @@
|
|
6
6
|
# the maximum value specified for Puma. Default is set to 5 threads for minimum
|
7
7
|
# and maximum; this matches the default thread size of Active Record.
|
8
8
|
#
|
9
|
-
max_threads_count = ENV.fetch('RAILS_MAX_THREADS'
|
9
|
+
max_threads_count = ENV.fetch('RAILS_MAX_THREADS', 5)
|
10
10
|
min_threads_count = ENV.fetch('RAILS_MIN_THREADS') { max_threads_count }
|
11
11
|
threads min_threads_count, max_threads_count
|
12
12
|
|
13
13
|
# Specifies the `port` that Puma will listen on to receive requests; default is 3000.
|
14
14
|
#
|
15
|
-
port ENV.fetch('PORT'
|
15
|
+
port ENV.fetch('PORT', 3000)
|
16
16
|
|
17
17
|
# Specifies the `environment` that Puma will run in.
|
18
18
|
#
|
19
|
-
environment ENV.fetch('RAILS_ENV'
|
19
|
+
environment ENV.fetch('RAILS_ENV', 'development')
|
20
20
|
|
21
21
|
# Specifies the number of `workers` to boot in clustered mode.
|
22
22
|
# Workers are forked web server processes. If using threads and workers together
|
data/examples/sinatra/Gemfile
CHANGED
@@ -99,7 +99,7 @@ GEM
|
|
99
99
|
nio4r (2.5.8)
|
100
100
|
os (1.1.4)
|
101
101
|
public_suffix (4.0.6)
|
102
|
-
puma (5.6.
|
102
|
+
puma (5.6.4)
|
103
103
|
nio4r (~> 2.0)
|
104
104
|
rack (2.2.3)
|
105
105
|
rack-protection (2.2.0)
|
@@ -128,7 +128,7 @@ PLATFORMS
|
|
128
128
|
|
129
129
|
DEPENDENCIES
|
130
130
|
cloudenvoy!
|
131
|
-
puma (~> 5.6.
|
131
|
+
puma (~> 5.6.4)
|
132
132
|
rake
|
133
133
|
sinatra
|
134
134
|
|
data/examples/sinatra/README.md
CHANGED
@@ -17,6 +17,10 @@ Cloudenvoy.setup_subscribers
|
|
17
17
|
HelloPublisher.publish('Some message')
|
18
18
|
```
|
19
19
|
8. Tail the logs to see how message get processed by `HelloSubscriber`
|
20
|
+
9. Try sending multiple messages at once:
|
21
|
+
```ruby
|
22
|
+
HelloPublisher.publish_all(['message1', 'message2', 'message3'])
|
23
|
+
```
|
20
24
|
|
21
25
|
## Run using GCP Pub/Sub
|
22
26
|
|
@@ -11,6 +11,6 @@ class HelloSubscriber
|
|
11
11
|
# @param [Cloudenvoy::Message] message The message to process.
|
12
12
|
#
|
13
13
|
def process(message)
|
14
|
-
logger.info("Received message #{message.payload
|
14
|
+
logger.info("Received message #{message.payload['content']}")
|
15
15
|
end
|
16
16
|
end
|
data/examples/sinatra/app.rb
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
# Force logging to be realtime
|
4
|
-
|
4
|
+
$stdout.sync = true
|
5
5
|
|
6
6
|
# Require project files
|
7
7
|
require 'sinatra'
|
8
|
-
Dir.glob('./config/initializers/*.rb').each { |file| require file }
|
9
|
-
Dir.glob('./app/publishers/*.rb').each { |file| require file }
|
10
|
-
Dir.glob('./app/subscribers/*.rb').each { |file| require file }
|
8
|
+
Dir.glob('./config/initializers/*.rb').sort.each { |file| require file }
|
9
|
+
Dir.glob('./app/publishers/*.rb').sort.each { |file| require file }
|
10
|
+
Dir.glob('./app/subscribers/*.rb').sort.each { |file| require file }
|
11
11
|
|
12
12
|
#---------------------------------------------------
|
13
13
|
# Routes
|
@@ -54,7 +54,7 @@ module Cloudenvoy
|
|
54
54
|
# @param [Hash, String] payload The message content.
|
55
55
|
# @param [Hash] metadata The message attributes.
|
56
56
|
#
|
57
|
-
# @return [Cloudenvoy::Message] The
|
57
|
+
# @return [Cloudenvoy::Message] The published message.
|
58
58
|
#
|
59
59
|
def publish(topic, payload, metadata = {})
|
60
60
|
# Retrieve the topic
|
@@ -72,6 +72,38 @@ module Cloudenvoy
|
|
72
72
|
)
|
73
73
|
end
|
74
74
|
|
75
|
+
#
|
76
|
+
# Publish multiple messages to a topic.
|
77
|
+
#
|
78
|
+
# @param [String] topic The name of the topic
|
79
|
+
# @param [Array<Array<[Hash, String]>>] msg_args A list of message [payload, metadata].
|
80
|
+
#
|
81
|
+
# @return [Array<Cloudenvoy::Message>] The published messages.
|
82
|
+
#
|
83
|
+
def publish_all(topic, msg_args)
|
84
|
+
# Retrieve the topic
|
85
|
+
ps_topic = backend.topic(topic, skip_lookup: true)
|
86
|
+
|
87
|
+
# Publish the message
|
88
|
+
ps_msgs = ps_topic.publish do |batch|
|
89
|
+
msg_args.each do |(payload, metadata)|
|
90
|
+
batch.publish(payload.to_json, metadata.to_h)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
# Return the formatted messages
|
95
|
+
ps_msgs.each_with_index.map do |ps_msg, index|
|
96
|
+
payload, metadata = msg_args[index]
|
97
|
+
|
98
|
+
Message.new(
|
99
|
+
id: ps_msg.message_id,
|
100
|
+
payload: payload,
|
101
|
+
metadata: metadata,
|
102
|
+
topic: topic
|
103
|
+
)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
75
107
|
#
|
76
108
|
# Create or update a subscription for a specific topic.
|
77
109
|
#
|
@@ -134,8 +166,8 @@ module Cloudenvoy
|
|
134
166
|
def upsert_topic(topic)
|
135
167
|
ps_topic = begin
|
136
168
|
backend.create_topic(topic)
|
137
|
-
|
138
|
-
|
169
|
+
rescue Google::Cloud::AlreadyExistsError
|
170
|
+
backend.topic(topic)
|
139
171
|
end
|
140
172
|
|
141
173
|
# Return formatted subscription
|
@@ -47,7 +47,7 @@ module Cloudenvoy
|
|
47
47
|
# @param [Hash, String] payload The message content.
|
48
48
|
# @param [Hash] attrs The message attributes.
|
49
49
|
#
|
50
|
-
# @return [Cloudenvoy::Message] The
|
50
|
+
# @return [Cloudenvoy::Message] The published message.
|
51
51
|
#
|
52
52
|
def publish(topic, payload, metadata = {})
|
53
53
|
msg = Message.new(
|
@@ -61,6 +61,30 @@ module Cloudenvoy
|
|
61
61
|
msg
|
62
62
|
end
|
63
63
|
|
64
|
+
#
|
65
|
+
# Publish multiple messages to a topic.
|
66
|
+
#
|
67
|
+
# @param [String] topic The name of the topic
|
68
|
+
# @param [Array<Array<[Hash, String]>>] msg_args A list of message [payload, metadata].
|
69
|
+
#
|
70
|
+
# @return [Array<Cloudenvoy::Message>] The published messages.
|
71
|
+
#
|
72
|
+
def publish_all(topic, msg_args)
|
73
|
+
# Build the messages
|
74
|
+
msgs = msg_args.map do |(payload, metadata)|
|
75
|
+
Message.new(
|
76
|
+
id: SecureRandom.uuid,
|
77
|
+
payload: payload,
|
78
|
+
metadata: metadata,
|
79
|
+
topic: topic
|
80
|
+
)
|
81
|
+
end
|
82
|
+
|
83
|
+
# Push all the messages and return them
|
84
|
+
queue(topic).push(*msgs)
|
85
|
+
msgs
|
86
|
+
end
|
87
|
+
|
64
88
|
#
|
65
89
|
# Create or update a subscription for a specific topic.
|
66
90
|
#
|
data/lib/cloudenvoy/config.rb
CHANGED
data/lib/cloudenvoy/message.rb
CHANGED
@@ -30,12 +30,24 @@ module Cloudenvoy
|
|
30
30
|
# @param [Hash, String] payload The message content.
|
31
31
|
# @param [Hash] attrs The message attributes.
|
32
32
|
#
|
33
|
-
# @return [Cloudenvoy::Message] The
|
33
|
+
# @return [Cloudenvoy::Message] The published message.
|
34
34
|
#
|
35
35
|
def self.publish(topic, payload, attrs = {})
|
36
36
|
backend.publish(topic, payload, attrs)
|
37
37
|
end
|
38
38
|
|
39
|
+
#
|
40
|
+
# Publish multiple messages to a topic.
|
41
|
+
#
|
42
|
+
# @param [String] topic The name of the topic
|
43
|
+
# @param [Array<Array<[Hash, String]>>] msg_args A list of message [payload, metadata].
|
44
|
+
#
|
45
|
+
# @return [Array<Cloudenvoy::Message>] The published messages.
|
46
|
+
#
|
47
|
+
def self.publish_all(topic, msg_args)
|
48
|
+
backend.publish_all(topic, msg_args)
|
49
|
+
end
|
50
|
+
|
39
51
|
#
|
40
52
|
# Create or update a subscription for a specific topic.
|
41
53
|
#
|
data/lib/cloudenvoy/publisher.rb
CHANGED
@@ -89,6 +89,40 @@ module Cloudenvoy
|
|
89
89
|
|
90
90
|
PubSubClient.upsert_topic(default_topic)
|
91
91
|
end
|
92
|
+
|
93
|
+
#
|
94
|
+
# Publish all messages in one batch.
|
95
|
+
#
|
96
|
+
# @param [Array<Any>] The list of publisher arguments.
|
97
|
+
#
|
98
|
+
# @return [Array<Cloudenvoy::Message>] The published messages.
|
99
|
+
#
|
100
|
+
def publish_all(arg_list)
|
101
|
+
# Build the list of publishers
|
102
|
+
publishers = arg_list.map { |e| new(msg_args: [e].flatten(1)) }
|
103
|
+
|
104
|
+
# Batches are topic specific. We must send one batch of messages per topic.
|
105
|
+
publishers.group_by { |e| e.topic(*e.msg_args) }.map do |topic, topic_publishers|
|
106
|
+
# Chain publish calls. The very last call (when the chain becomes empty)
|
107
|
+
# is the actual batch publishing of messages to pub/sub
|
108
|
+
chain = topic_publishers.dup
|
109
|
+
traverse_chain = lambda do
|
110
|
+
if chain.empty?
|
111
|
+
# Send the messages in one batch and retrospectively attach them
|
112
|
+
# to each publisher
|
113
|
+
arg_list = topic_publishers.map { |e| [e.payload(*e.msg_args), e.metadata(*e.msg_args)] }
|
114
|
+
PubSubClient.publish_all(topic, arg_list).each_with_index do |msg, pub_index|
|
115
|
+
topic_publishers[pub_index].message = msg
|
116
|
+
end
|
117
|
+
else
|
118
|
+
# Defer message publishing to the next element
|
119
|
+
# in the chain until the chain is empty
|
120
|
+
chain.shift.publish(&traverse_chain)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
traverse_chain.call
|
124
|
+
end.flatten
|
125
|
+
end
|
92
126
|
end
|
93
127
|
|
94
128
|
#
|
@@ -155,9 +189,9 @@ module Cloudenvoy
|
|
155
189
|
#
|
156
190
|
# @return [Cloudenvoy::Message] The created message.
|
157
191
|
#
|
158
|
-
def publish
|
192
|
+
def publish(&block)
|
159
193
|
# Format and publish message
|
160
|
-
resp = execute_middleware_chain
|
194
|
+
resp = execute_middleware_chain(&block)
|
161
195
|
|
162
196
|
# Log job completion and return result
|
163
197
|
logger.info("Published message in #{publishing_duration}s") { { duration: publishing_duration } }
|
@@ -191,14 +225,14 @@ module Cloudenvoy
|
|
191
225
|
#
|
192
226
|
# Execute the subscriber process method through the middleware chain.
|
193
227
|
#
|
194
|
-
# @return [
|
228
|
+
# @return [Cloudenvoy::Message] The published message.
|
195
229
|
#
|
196
|
-
def execute_middleware_chain
|
230
|
+
def execute_middleware_chain(&block)
|
197
231
|
self.publishing_started_at = Time.now
|
198
232
|
|
199
233
|
Cloudenvoy.config.publisher_middleware.invoke(self) do
|
200
234
|
begin
|
201
|
-
publish_message
|
235
|
+
block_given? ? block.call : publish_message
|
202
236
|
rescue StandardError => e
|
203
237
|
logger.error([e, e.backtrace.join("\n")].join("\n"))
|
204
238
|
try(:on_error, e)
|
@@ -9,7 +9,7 @@ module Cloudenvoy
|
|
9
9
|
# @return [Proc] The context processor proc.
|
10
10
|
#
|
11
11
|
def self.default_context_processor
|
12
|
-
@default_context_processor ||= ->(loggable) { loggable.message
|
12
|
+
@default_context_processor ||= ->(loggable) { loggable.message.to_h&.slice(:id, :metadata, :topic) || {} }
|
13
13
|
end
|
14
14
|
|
15
15
|
#
|
data/lib/cloudenvoy/version.rb
CHANGED
data/lib/cloudenvoy.rb
CHANGED
@@ -63,6 +63,18 @@ module Cloudenvoy
|
|
63
63
|
PubSubClient.publish(topic, payload, attrs)
|
64
64
|
end
|
65
65
|
|
66
|
+
#
|
67
|
+
# Publish multiple messages to a topic. Shorthand method to Cloudenvoy::PubSubClient#publish_all.
|
68
|
+
#
|
69
|
+
# @param [String] topic The name of the topic
|
70
|
+
# @param [Array<Array<[Hash, String]>>] msg_args A list of message [payload, metadata].
|
71
|
+
#
|
72
|
+
# @return [Array<Cloudenvoy::Message>] The published messages.
|
73
|
+
#
|
74
|
+
def self.publish_all(topic, msg_args)
|
75
|
+
PubSubClient.publish_all(topic, msg_args)
|
76
|
+
end
|
77
|
+
|
66
78
|
#
|
67
79
|
# Return the list of registered publishers.
|
68
80
|
#
|