cloudenvoy 0.4.2 → 0.6.rc1

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.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/lint_rubocop.yml +20 -0
  3. data/.github/workflows/{test.yml → test_ruby_2.5_2.6.yml} +8 -13
  4. data/.github/workflows/test_ruby_2.7.yml +36 -0
  5. data/.github/workflows/test_ruby_3.x.yml +35 -0
  6. data/.gitignore +1 -0
  7. data/.rubocop.yml +17 -16
  8. data/Appraisals +24 -4
  9. data/CHANGELOG.md +18 -0
  10. data/README.md +39 -2
  11. data/cloudenvoy.gemspec +2 -6
  12. data/examples/rails/.ruby-version +1 -1
  13. data/examples/rails/Gemfile +4 -1
  14. data/examples/rails/Gemfile.lock +92 -85
  15. data/examples/rails/README.md +5 -1
  16. data/examples/rails/app/subscribers/hello_subscriber.rb +1 -1
  17. data/examples/rails/config/environments/production.rb +1 -1
  18. data/examples/rails/config/puma.rb +3 -3
  19. data/examples/sinatra/Gemfile +4 -1
  20. data/examples/sinatra/Gemfile.lock +40 -28
  21. data/examples/sinatra/README.md +4 -0
  22. data/examples/sinatra/app/subscribers/hello_subscriber.rb +1 -1
  23. data/examples/sinatra/app.rb +4 -4
  24. data/gemfiles/.bundle/config +2 -0
  25. data/gemfiles/rails_5.2.gemfile +1 -0
  26. data/gemfiles/rails_6.0.gemfile +1 -0
  27. data/gemfiles/rails_6.1.gemfile +8 -0
  28. data/gemfiles/rails_7.0.gemfile +8 -0
  29. data/gemfiles/semantic_logger_3.4.gemfile +1 -0
  30. data/gemfiles/semantic_logger_4.6.gemfile +1 -0
  31. data/gemfiles/semantic_logger_4.7.0.gemfile +1 -0
  32. data/gemfiles/semantic_logger_4.7.2.gemfile +1 -0
  33. data/lib/cloudenvoy/backend/google_pub_sub.rb +37 -5
  34. data/lib/cloudenvoy/backend/memory_pub_sub.rb +25 -1
  35. data/lib/cloudenvoy/config.rb +1 -1
  36. data/lib/cloudenvoy/message.rb +2 -2
  37. data/lib/cloudenvoy/pub_sub_client.rb +13 -1
  38. data/lib/cloudenvoy/publisher.rb +39 -5
  39. data/lib/cloudenvoy/publisher_logger.rb +1 -1
  40. data/lib/cloudenvoy/version.rb +1 -1
  41. data/lib/cloudenvoy.rb +13 -0
  42. metadata +15 -57
  43. data/gemfiles/rails_5.2.gemfile.lock +0 -264
  44. data/gemfiles/rails_6.0.gemfile.lock +0 -280
  45. data/gemfiles/semantic_logger_3.4.gemfile.lock +0 -279
  46. data/gemfiles/semantic_logger_4.6.gemfile.lock +0 -279
  47. data/gemfiles/semantic_logger_4.7.0.gemfile.lock +0 -279
  48. data/gemfiles/semantic_logger_4.7.2.gemfile.lock +0 -279
@@ -32,7 +32,7 @@ module Cloudenvoy
32
32
  # @return [Google::Cloud::Pub] The low level client instance.
33
33
  #
34
34
  def backend
35
- @backend ||= Google::Cloud::PubSub.new({
35
+ @backend ||= Google::Cloud::PubSub.new(**{
36
36
  project_id: config.gcp_project_id,
37
37
  emulator_host: development? ? Cloudenvoy::Config::EMULATOR_HOST : nil
38
38
  }.compact)
@@ -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 created message.
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
  #
@@ -109,7 +141,7 @@ module Cloudenvoy
109
141
  ps_topic = backend.topic(topic, skip_lookup: true)
110
142
 
111
143
  # Attempt to create the subscription
112
- ps_topic.subscribe(name, sub_config)
144
+ ps_topic.subscribe(name, **sub_config)
113
145
  rescue Google::Cloud::AlreadyExistsError
114
146
  # Update endpoint on subscription
115
147
  # Topic is not updated as it is name-dependent
@@ -134,8 +166,8 @@ module Cloudenvoy
134
166
  def upsert_topic(topic)
135
167
  ps_topic = begin
136
168
  backend.create_topic(topic)
137
- rescue Google::Cloud::AlreadyExistsError
138
- backend.topic(topic)
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 created message.
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
  #
@@ -57,7 +57,7 @@ module Cloudenvoy
57
57
  # @return [Logger, any] The cloudenvoy logger.
58
58
  #
59
59
  def logger
60
- @logger ||= defined?(Rails) ? Rails.logger : ::Logger.new(STDOUT)
60
+ @logger ||= defined?(Rails) ? Rails.logger : ::Logger.new($stdout)
61
61
  end
62
62
 
63
63
  #
@@ -75,8 +75,8 @@ module Cloudenvoy
75
75
  def to_h
76
76
  {
77
77
  id: id,
78
- payload: payload&.dup,
79
- metadata: metadata&.dup,
78
+ payload: payload.dup,
79
+ metadata: metadata.dup,
80
80
  topic: topic,
81
81
  sub_uri: sub_uri
82
82
  }.compact
@@ -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 created message.
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
  #
@@ -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 [Any] The result of the perform method.
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&.to_h&.slice(:id, :metadata, :topic) || {} }
12
+ @default_context_processor ||= ->(loggable) { loggable.message.to_h&.slice(:id, :metadata, :topic) || {} }
13
13
  end
14
14
 
15
15
  #
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Cloudenvoy
4
- VERSION = '0.4.2'
4
+ VERSION = '0.6.rc1'
5
5
  end
data/lib/cloudenvoy.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'active_support/core_ext/string/inflections'
4
+ require 'active_support/core_ext/object/try'
4
5
 
5
6
  require 'cloudenvoy/version'
6
7
  require 'cloudenvoy/config'
@@ -62,6 +63,18 @@ module Cloudenvoy
62
63
  PubSubClient.publish(topic, payload, attrs)
63
64
  end
64
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
+
65
78
  #
66
79
  # Return the list of registered publishers.
67
80
  #
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cloudenvoy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.2
4
+ version: 0.6.rc1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Arnaud Lachaume
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-10-25 00:00:00.000000000 Z
11
+ date: 2022-04-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -114,14 +114,14 @@ dependencies:
114
114
  requirements:
115
115
  - - '='
116
116
  - !ruby/object:Gem::Version
117
- version: 0.76.0
117
+ version: 0.93.0
118
118
  type: :development
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
122
  - - '='
123
123
  - !ruby/object:Gem::Version
124
- version: 0.76.0
124
+ version: 0.93.0
125
125
  - !ruby/object:Gem::Dependency
126
126
  name: rubocop-rspec
127
127
  requirement: !ruby/object:Gem::Requirement
@@ -178,48 +178,6 @@ dependencies:
178
178
  - - ">="
179
179
  - !ruby/object:Gem::Version
180
180
  version: '0'
181
- - !ruby/object:Gem::Dependency
182
- name: rails
183
- requirement: !ruby/object:Gem::Requirement
184
- requirements:
185
- - - ">="
186
- - !ruby/object:Gem::Version
187
- version: '0'
188
- type: :development
189
- prerelease: false
190
- version_requirements: !ruby/object:Gem::Requirement
191
- requirements:
192
- - - ">="
193
- - !ruby/object:Gem::Version
194
- version: '0'
195
- - !ruby/object:Gem::Dependency
196
- name: rspec-rails
197
- requirement: !ruby/object:Gem::Requirement
198
- requirements:
199
- - - ">="
200
- - !ruby/object:Gem::Version
201
- version: '0'
202
- type: :development
203
- prerelease: false
204
- version_requirements: !ruby/object:Gem::Requirement
205
- requirements:
206
- - - ">="
207
- - !ruby/object:Gem::Version
208
- version: '0'
209
- - !ruby/object:Gem::Dependency
210
- name: sqlite3
211
- requirement: !ruby/object:Gem::Requirement
212
- requirements:
213
- - - ">="
214
- - !ruby/object:Gem::Version
215
- version: '0'
216
- type: :development
217
- prerelease: false
218
- version_requirements: !ruby/object:Gem::Requirement
219
- requirements:
220
- - - ">="
221
- - !ruby/object:Gem::Version
222
- version: '0'
223
181
  description: Cross-application messaging using GCP Pub/Sub (alpha)
224
182
  email:
225
183
  - arnaud.lachaume@keypup.io
@@ -227,7 +185,10 @@ executables: []
227
185
  extensions: []
228
186
  extra_rdoc_files: []
229
187
  files:
230
- - ".github/workflows/test.yml"
188
+ - ".github/workflows/lint_rubocop.yml"
189
+ - ".github/workflows/test_ruby_2.5_2.6.yml"
190
+ - ".github/workflows/test_ruby_2.7.yml"
191
+ - ".github/workflows/test_ruby_3.x.yml"
231
192
  - ".gitignore"
232
193
  - ".rspec"
233
194
  - ".rubocop.yml"
@@ -318,18 +279,15 @@ files:
318
279
  - examples/sinatra/app/subscribers/hello_subscriber.rb
319
280
  - examples/sinatra/bin/console
320
281
  - examples/sinatra/config/initializers/cloudenvoy.rb
282
+ - gemfiles/.bundle/config
321
283
  - gemfiles/rails_5.2.gemfile
322
- - gemfiles/rails_5.2.gemfile.lock
323
284
  - gemfiles/rails_6.0.gemfile
324
- - gemfiles/rails_6.0.gemfile.lock
285
+ - gemfiles/rails_6.1.gemfile
286
+ - gemfiles/rails_7.0.gemfile
325
287
  - gemfiles/semantic_logger_3.4.gemfile
326
- - gemfiles/semantic_logger_3.4.gemfile.lock
327
288
  - gemfiles/semantic_logger_4.6.gemfile
328
- - gemfiles/semantic_logger_4.6.gemfile.lock
329
289
  - gemfiles/semantic_logger_4.7.0.gemfile
330
- - gemfiles/semantic_logger_4.7.0.gemfile.lock
331
290
  - gemfiles/semantic_logger_4.7.2.gemfile
332
- - gemfiles/semantic_logger_4.7.2.gemfile.lock
333
291
  - lib/cloudenvoy.rb
334
292
  - lib/cloudenvoy/authentication_error.rb
335
293
  - lib/cloudenvoy/authenticator.rb
@@ -372,14 +330,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
372
330
  requirements:
373
331
  - - ">="
374
332
  - !ruby/object:Gem::Version
375
- version: 2.3.0
333
+ version: 2.4.0
376
334
  required_rubygems_version: !ruby/object:Gem::Requirement
377
335
  requirements:
378
- - - ">="
336
+ - - ">"
379
337
  - !ruby/object:Gem::Version
380
- version: '0'
338
+ version: 1.3.1
381
339
  requirements: []
382
- rubygems_version: 3.0.0
340
+ rubygems_version: 3.2.3
383
341
  signing_key:
384
342
  specification_version: 4
385
343
  summary: Cross-application messaging using GCP Pub/Sub (alpha)
@@ -1,264 +0,0 @@
1
- PATH
2
- remote: ..
3
- specs:
4
- cloudenvoy (0.4.1)
5
- activesupport
6
- google-cloud-pubsub (~> 2.0)
7
- jwt
8
- retriable
9
-
10
- GEM
11
- remote: https://rubygems.org/
12
- specs:
13
- actioncable (5.2.0)
14
- actionpack (= 5.2.0)
15
- nio4r (~> 2.0)
16
- websocket-driver (>= 0.6.1)
17
- actionmailer (5.2.0)
18
- actionpack (= 5.2.0)
19
- actionview (= 5.2.0)
20
- activejob (= 5.2.0)
21
- mail (~> 2.5, >= 2.5.4)
22
- rails-dom-testing (~> 2.0)
23
- actionpack (5.2.0)
24
- actionview (= 5.2.0)
25
- activesupport (= 5.2.0)
26
- rack (~> 2.0)
27
- rack-test (>= 0.6.3)
28
- rails-dom-testing (~> 2.0)
29
- rails-html-sanitizer (~> 1.0, >= 1.0.2)
30
- actionview (5.2.0)
31
- activesupport (= 5.2.0)
32
- builder (~> 3.1)
33
- erubi (~> 1.4)
34
- rails-dom-testing (~> 2.0)
35
- rails-html-sanitizer (~> 1.0, >= 1.0.3)
36
- activejob (5.2.0)
37
- activesupport (= 5.2.0)
38
- globalid (>= 0.3.6)
39
- activemodel (5.2.0)
40
- activesupport (= 5.2.0)
41
- activerecord (5.2.0)
42
- activemodel (= 5.2.0)
43
- activesupport (= 5.2.0)
44
- arel (>= 9.0)
45
- activestorage (5.2.0)
46
- actionpack (= 5.2.0)
47
- activerecord (= 5.2.0)
48
- marcel (~> 0.3.1)
49
- activesupport (5.2.0)
50
- concurrent-ruby (~> 1.0, >= 1.0.2)
51
- i18n (>= 0.7, < 2)
52
- minitest (~> 5.1)
53
- tzinfo (~> 1.1)
54
- addressable (2.7.0)
55
- public_suffix (>= 2.0.2, < 5.0)
56
- appraisal (2.4.0)
57
- bundler
58
- rake
59
- thor (>= 0.14.0)
60
- arel (9.0.0)
61
- ast (2.4.2)
62
- builder (3.2.4)
63
- concurrent-ruby (1.1.8)
64
- crack (0.4.5)
65
- rexml
66
- crass (1.0.6)
67
- diff-lcs (1.4.4)
68
- erubi (1.10.0)
69
- faraday (1.4.1)
70
- faraday-excon (~> 1.1)
71
- faraday-net_http (~> 1.0)
72
- faraday-net_http_persistent (~> 1.1)
73
- multipart-post (>= 1.2, < 3)
74
- ruby2_keywords (>= 0.0.4)
75
- faraday-excon (1.1.0)
76
- faraday-net_http (1.0.1)
77
- faraday-net_http_persistent (1.1.0)
78
- gapic-common (0.4.1)
79
- faraday (~> 1.3)
80
- google-protobuf (~> 3.15, >= 3.15.2)
81
- googleapis-common-protos (>= 1.3.11, < 2.0)
82
- googleapis-common-protos-types (>= 1.0.6, < 2.0)
83
- googleauth (~> 0.15, >= 0.15.1)
84
- grpc (~> 1.36)
85
- globalid (0.4.2)
86
- activesupport (>= 4.2.0)
87
- google-cloud-core (1.6.0)
88
- google-cloud-env (~> 1.0)
89
- google-cloud-errors (~> 1.0)
90
- google-cloud-env (1.5.0)
91
- faraday (>= 0.17.3, < 2.0)
92
- google-cloud-errors (1.1.0)
93
- google-cloud-pubsub (2.5.0)
94
- concurrent-ruby (~> 1.1)
95
- google-cloud-core (~> 1.5)
96
- google-cloud-pubsub-v1 (~> 0.0)
97
- google-cloud-pubsub-v1 (0.4.0)
98
- gapic-common (~> 0.3)
99
- google-cloud-errors (~> 1.0)
100
- grpc-google-iam-v1 (>= 0.6.10, < 2.0)
101
- google-protobuf (3.15.8)
102
- googleapis-common-protos (1.3.11)
103
- google-protobuf (~> 3.14)
104
- googleapis-common-protos-types (>= 1.0.6, < 2.0)
105
- grpc (~> 1.27)
106
- googleapis-common-protos-types (1.0.6)
107
- google-protobuf (~> 3.14)
108
- googleauth (0.16.1)
109
- faraday (>= 0.17.3, < 2.0)
110
- jwt (>= 1.4, < 3.0)
111
- memoist (~> 0.16)
112
- multi_json (~> 1.11)
113
- os (>= 0.9, < 2.0)
114
- signet (~> 0.14)
115
- grpc (1.37.0)
116
- google-protobuf (~> 3.15)
117
- googleapis-common-protos-types (~> 1.0)
118
- grpc-google-iam-v1 (0.6.11)
119
- google-protobuf (~> 3.14)
120
- googleapis-common-protos (>= 1.3.11, < 2.0)
121
- grpc (~> 1.27)
122
- hashdiff (1.0.1)
123
- i18n (1.8.10)
124
- concurrent-ruby (~> 1.0)
125
- jaro_winkler (1.5.4)
126
- jwt (2.2.2)
127
- loofah (2.9.1)
128
- crass (~> 1.0.2)
129
- nokogiri (>= 1.5.9)
130
- mail (2.7.1)
131
- mini_mime (>= 0.1.1)
132
- marcel (0.3.3)
133
- mimemagic (~> 0.3.2)
134
- memoist (0.16.2)
135
- method_source (1.0.0)
136
- mimemagic (0.3.10)
137
- nokogiri (~> 1)
138
- rake
139
- mini_mime (1.1.0)
140
- mini_portile2 (2.5.0)
141
- minitest (5.14.4)
142
- multi_json (1.15.0)
143
- multipart-post (2.1.1)
144
- nio4r (2.5.7)
145
- nokogiri (1.11.3)
146
- mini_portile2 (~> 2.5.0)
147
- racc (~> 1.4)
148
- os (1.1.1)
149
- parallel (1.20.1)
150
- parser (3.0.1.0)
151
- ast (~> 2.4.1)
152
- public_suffix (4.0.6)
153
- racc (1.5.2)
154
- rack (2.2.3)
155
- rack-test (1.1.0)
156
- rack (>= 1.0, < 3)
157
- rails (5.2.0)
158
- actioncable (= 5.2.0)
159
- actionmailer (= 5.2.0)
160
- actionpack (= 5.2.0)
161
- actionview (= 5.2.0)
162
- activejob (= 5.2.0)
163
- activemodel (= 5.2.0)
164
- activerecord (= 5.2.0)
165
- activestorage (= 5.2.0)
166
- activesupport (= 5.2.0)
167
- bundler (>= 1.3.0)
168
- railties (= 5.2.0)
169
- sprockets-rails (>= 2.0.0)
170
- rails-dom-testing (2.0.3)
171
- activesupport (>= 4.2.0)
172
- nokogiri (>= 1.6)
173
- rails-html-sanitizer (1.3.0)
174
- loofah (~> 2.3)
175
- railties (5.2.0)
176
- actionpack (= 5.2.0)
177
- activesupport (= 5.2.0)
178
- method_source
179
- rake (>= 0.8.7)
180
- thor (>= 0.18.1, < 2.0)
181
- rainbow (3.0.0)
182
- rake (13.0.3)
183
- retriable (3.1.2)
184
- rexml (3.2.5)
185
- rspec (3.10.0)
186
- rspec-core (~> 3.10.0)
187
- rspec-expectations (~> 3.10.0)
188
- rspec-mocks (~> 3.10.0)
189
- rspec-core (3.10.1)
190
- rspec-support (~> 3.10.0)
191
- rspec-expectations (3.10.1)
192
- diff-lcs (>= 1.2.0, < 2.0)
193
- rspec-support (~> 3.10.0)
194
- rspec-mocks (3.10.2)
195
- diff-lcs (>= 1.2.0, < 2.0)
196
- rspec-support (~> 3.10.0)
197
- rspec-rails (5.0.1)
198
- actionpack (>= 5.2)
199
- activesupport (>= 5.2)
200
- railties (>= 5.2)
201
- rspec-core (~> 3.10)
202
- rspec-expectations (~> 3.10)
203
- rspec-mocks (~> 3.10)
204
- rspec-support (~> 3.10)
205
- rspec-support (3.10.2)
206
- rubocop (0.76.0)
207
- jaro_winkler (~> 1.5.1)
208
- parallel (~> 1.10)
209
- parser (>= 2.6)
210
- rainbow (>= 2.2.2, < 4.0)
211
- ruby-progressbar (~> 1.7)
212
- unicode-display_width (>= 1.4.0, < 1.7)
213
- rubocop-rspec (1.37.0)
214
- rubocop (>= 0.68.1)
215
- ruby-progressbar (1.11.0)
216
- ruby2_keywords (0.0.4)
217
- semantic_logger (4.7.4)
218
- concurrent-ruby (~> 1.0)
219
- signet (0.15.0)
220
- addressable (~> 2.3)
221
- faraday (>= 0.17.3, < 2.0)
222
- jwt (>= 1.5, < 3.0)
223
- multi_json (~> 1.10)
224
- sprockets (4.0.2)
225
- concurrent-ruby (~> 1.0)
226
- rack (> 1, < 3)
227
- sprockets-rails (3.2.2)
228
- actionpack (>= 4.0)
229
- activesupport (>= 4.0)
230
- sprockets (>= 3.0.0)
231
- sqlite3 (1.4.2)
232
- thor (1.1.0)
233
- thread_safe (0.3.6)
234
- timecop (0.9.4)
235
- tzinfo (1.2.9)
236
- thread_safe (~> 0.1)
237
- unicode-display_width (1.6.1)
238
- webmock (3.12.2)
239
- addressable (>= 2.3.6)
240
- crack (>= 0.3.2)
241
- hashdiff (>= 0.4.0, < 2.0.0)
242
- websocket-driver (0.7.3)
243
- websocket-extensions (>= 0.1.0)
244
- websocket-extensions (0.1.5)
245
-
246
- PLATFORMS
247
- ruby
248
-
249
- DEPENDENCIES
250
- appraisal
251
- cloudenvoy!
252
- rails (= 5.2)
253
- rake (>= 12.3.3)
254
- rspec (~> 3.0)
255
- rspec-rails
256
- rubocop (= 0.76.0)
257
- rubocop-rspec (= 1.37.0)
258
- semantic_logger
259
- sqlite3
260
- timecop
261
- webmock
262
-
263
- BUNDLED WITH
264
- 2.2.9