salesforce_streamer 2.0.0.rc1 → 2.2.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 980626b26a53a56e8fb6fd2028e538ffd667cbe938a1aa1011c4184813d2936d
4
- data.tar.gz: b6ece556e2e34186b9ad77f445c26ebf6532170e4a9f7a8d0662e309775c9427
3
+ metadata.gz: 1b4745cb1c8f38229ac4be01e746a7b865458c37e0d293f3505bfe9803cce20c
4
+ data.tar.gz: 290378a24b830fedd86290a06deaf5050fd1187c22467cadc6b1278aee19cebf
5
5
  SHA512:
6
- metadata.gz: 1920656978db1b707ba61bd90c7026988b99c9dfbb2c7489f4a8554df97f1ad9000885fa619bff884257fd5794225ba3c3ab23b3172b6753ea57ec8f76e6bb05
7
- data.tar.gz: '0099d97a9cb7774c0fe274b0ee46bb68da87dca38f6113310539248f309111341a4a3e917476e4ca686413cf8cd22e5551f6c917a774a60ffab6541f9ad04889'
6
+ metadata.gz: 228d3f363b0b0bb292e94c4776c74fd8930f616250664fb586cfafa2695fcdde07f754f850c430e87ec12b9473046d733975d4c5ac3f9d9e70fd6be0ef8baa73
7
+ data.tar.gz: '0850171e7c9762b7cf498a8c9066b21482cab7e69f30d7a72d9cc0ca7b12c90ab5ea167ae312614d6d25060558cfd7aa2a880f60e6d7eaacf8229e916e14c61b'
@@ -1,7 +1,7 @@
1
- # automatically approve PRs submitted by Dependabot
1
+ # automatically approve PRs submitted by Dependabot or Renofidev
2
2
  # this will allow Dependabot to automatically merge dependency update PRs where CI passes
3
3
  # from: https://github.com/hmarr/auto-approve-action
4
- name: Auto approve Dependabot PRs
4
+ name: Auto approve dependency upgrades PRs
5
5
 
6
6
  on:
7
7
  pull_request
@@ -11,6 +11,6 @@ jobs:
11
11
  runs-on: ubuntu-latest
12
12
  steps:
13
13
  - uses: hmarr/auto-approve-action@v2.0.0
14
- if: github.actor == 'dependabot[bot]' || github.actor == 'dependabot-preview[bot]'
14
+ if: github.actor == 'dependabot[bot]' || github.actor == 'dependabot-preview[bot]' || github.actor == 'renofidev'
15
15
  with:
16
16
  github-token: "${{ secrets.GITHUB_TOKEN }}"
@@ -0,0 +1,19 @@
1
+ name: automerge
2
+ on:
3
+ pull_request_review:
4
+ types:
5
+ - submitted
6
+ check_suite:
7
+ types:
8
+ - completed
9
+ status: {}
10
+ jobs:
11
+ automerge:
12
+ runs-on: ubuntu-latest
13
+ steps:
14
+ - name: automerge
15
+ uses: "pascalgn/automerge-action@v0.11.0"
16
+ env:
17
+ GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
18
+ MERGE_METHOD: squash
19
+ MERGE_DELETE_BRANCH: true
@@ -3,6 +3,38 @@
3
3
  Sorted so that the most recent change logs are near the top. Only significant
4
4
  changes are logged in the change log.
5
5
 
6
+ ## 2020-08-17 Scott Serok [scott@renofi.com](mailto:scott@renofi.com)
7
+
8
+ v2.1 changes the expected interface of `Configuration#replay_adapter`.
9
+
10
+ Normally this breaking change would require a major version bump, but since the
11
+ functionality today is quiet broken we can call this a major bug fix.
12
+
13
+ The `config.replay_adapter` should be an object that has an interface like Hash.
14
+ It must respond to `[]` and `[]=`. By default the adapter is an empty hash. If
15
+ you want your push topic replayId to persist between restarts, then you should
16
+ implement a class with an appropriate interface.
17
+
18
+ ```ruby
19
+ class MyReplayAdapter
20
+ def [](channel)
21
+ MyPersistence.get(channel)
22
+ end
23
+
24
+ def []=(channel, replay_id)
25
+ MyPersistence.set(channel, replay_id)
26
+ end
27
+ end
28
+ ```
29
+
30
+ This change was sparked by a misunderstanding of the
31
+ `Restforce::Concerns::Streaming::ReplayExtension` replay handlers.
32
+ SalesforceStreamer can eliminate some complexity and fix a bug by delegating the
33
+ responsibility of maintaining the current replayId to that ReplayExtension. The
34
+ object will be used on each request/response cycle to record and read the latest
35
+ replayId as long as the object assigned to `config.replay_adapter` responds to
36
+ `[]` and `[]=`.
37
+
6
38
  ## 2020-08-04 Scott Serok [scott@renofi.com](mailto:scott@renofi.com)
7
39
 
8
40
  v2.0 is released as a major simplification of this library. There are 2
@@ -61,7 +93,7 @@ To retrieve the replayId before subscribing to a PushTopic,
61
93
  configure an adapter that returns an integer.
62
94
 
63
95
  SalesforceStreamer.config.replay_adapter = proc { |topic|
64
- MyStore.fetch_replay_id(topic.name) || -1
96
+ (MyStore.fetch_replay_id(topic.name) || -1).to_i
65
97
  }
66
98
 
67
99
  This will be used to set the replayId value when subscribing to the PushTopic.
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- salesforce_streamer (2.0.0.rc1)
4
+ salesforce_streamer (2.2.0)
5
5
  dry-initializer (~> 3.0)
6
6
  faye (~> 1.4)
7
7
  restforce (>= 4.2, < 6.0)
@@ -13,16 +13,14 @@ GEM
13
13
  public_suffix (>= 2.0.2, < 5.0)
14
14
  ast (2.4.1)
15
15
  byebug (11.1.3)
16
- codecov (0.2.3)
17
- colorize
16
+ codecov (0.2.12)
18
17
  json
19
18
  simplecov
20
- colorize (0.8.1)
21
19
  cookiejar (0.3.3)
22
20
  diff-lcs (1.4.4)
23
21
  docile (1.3.2)
24
- dry-initializer (3.0.3)
25
- em-http-request (1.1.6)
22
+ dry-initializer (3.0.4)
23
+ em-http-request (1.1.7)
26
24
  addressable (>= 2.3.4)
27
25
  cookiejar (!= 0.3.1)
28
26
  em-socksify (>= 0.3)
@@ -31,8 +29,9 @@ GEM
31
29
  em-socksify (0.3.2)
32
30
  eventmachine (>= 1.0.0.beta.4)
33
31
  eventmachine (1.2.7)
34
- faraday (1.0.1)
32
+ faraday (1.1.0)
35
33
  multipart-post (>= 1.2, < 3)
34
+ ruby2_keywords
36
35
  faraday_middleware (1.0.0)
37
36
  faraday (~> 1.0)
38
37
  faye (1.4.0)
@@ -49,56 +48,59 @@ GEM
49
48
  hashie (4.1.0)
50
49
  http_parser.rb (0.6.0)
51
50
  json (2.3.1)
52
- jwt (2.2.1)
51
+ jwt (2.2.2)
53
52
  multi_json (1.15.0)
54
53
  multipart-post (2.1.1)
55
- parallel (1.19.2)
56
- parser (2.7.1.4)
54
+ parallel (1.20.0)
55
+ parser (2.7.2.0)
57
56
  ast (~> 2.4.1)
58
- public_suffix (4.0.5)
57
+ public_suffix (4.0.6)
59
58
  rack (2.2.3)
60
59
  rainbow (3.0.0)
61
60
  rake (13.0.1)
62
- regexp_parser (1.7.1)
63
- restforce (5.0.0)
61
+ regexp_parser (1.8.2)
62
+ restforce (5.0.3)
64
63
  faraday (>= 0.9.0, <= 2.0)
65
64
  faraday_middleware (>= 0.8.8, <= 2.0)
66
65
  hashie (>= 1.2.0, < 5.0)
67
66
  jwt (>= 1.5.6)
68
67
  rexml (3.2.4)
69
- rspec (3.9.0)
70
- rspec-core (~> 3.9.0)
71
- rspec-expectations (~> 3.9.0)
72
- rspec-mocks (~> 3.9.0)
73
- rspec-core (3.9.2)
74
- rspec-support (~> 3.9.3)
75
- rspec-expectations (3.9.2)
68
+ rspec (3.10.0)
69
+ rspec-core (~> 3.10.0)
70
+ rspec-expectations (~> 3.10.0)
71
+ rspec-mocks (~> 3.10.0)
72
+ rspec-core (3.10.0)
73
+ rspec-support (~> 3.10.0)
74
+ rspec-expectations (3.10.0)
76
75
  diff-lcs (>= 1.2.0, < 2.0)
77
- rspec-support (~> 3.9.0)
78
- rspec-mocks (3.9.1)
76
+ rspec-support (~> 3.10.0)
77
+ rspec-mocks (3.10.0)
79
78
  diff-lcs (>= 1.2.0, < 2.0)
80
- rspec-support (~> 3.9.0)
81
- rspec-support (3.9.3)
82
- rubocop (0.88.0)
79
+ rspec-support (~> 3.10.0)
80
+ rspec-support (3.10.0)
81
+ rubocop (1.2.0)
83
82
  parallel (~> 1.10)
84
- parser (>= 2.7.1.1)
83
+ parser (>= 2.7.1.5)
85
84
  rainbow (>= 2.2.2, < 4.0)
86
- regexp_parser (>= 1.7)
85
+ regexp_parser (>= 1.8)
87
86
  rexml
88
- rubocop-ast (>= 0.1.0, < 1.0)
87
+ rubocop-ast (>= 1.0.1)
89
88
  ruby-progressbar (~> 1.7)
90
89
  unicode-display_width (>= 1.4.0, < 2.0)
91
- rubocop-ast (0.3.0)
92
- parser (>= 2.7.1.4)
93
- rubocop-performance (1.7.1)
94
- rubocop (>= 0.82.0)
95
- rubocop-rspec (1.42.0)
90
+ rubocop-ast (1.1.1)
91
+ parser (>= 2.7.1.5)
92
+ rubocop-performance (1.8.1)
96
93
  rubocop (>= 0.87.0)
94
+ rubocop-ast (>= 0.4.0)
95
+ rubocop-rspec (2.0.0)
96
+ rubocop (~> 1.0)
97
+ rubocop-ast (>= 1.1.0)
97
98
  ruby-progressbar (1.10.1)
98
- simplecov (0.18.5)
99
+ ruby2_keywords (0.0.2)
100
+ simplecov (0.19.1)
99
101
  docile (~> 1.1)
100
102
  simplecov-html (~> 0.11)
101
- simplecov-html (0.12.2)
103
+ simplecov-html (0.12.3)
102
104
  unicode-display_width (1.7.0)
103
105
  websocket-driver (0.7.3)
104
106
  websocket-extensions (>= 0.1.0)
data/README.md CHANGED
@@ -20,33 +20,11 @@ And then execute:
20
20
 
21
21
  ## Usage
22
22
 
23
- ### Middleware
24
-
25
- You can initialize the streamer server with any number of middleware classes.
26
- When a message is received by a PushTopic subscription, the chain of middleware
27
- classes are executed before the message handler is called.
28
-
29
- ```ruby
30
- # config/initializers/streamer.rb
31
- class MySimpleMiddleware
32
- def initialize(handler)
33
- @handler = handler
34
- end
35
- def call(message)
36
- @handler.call(message)
37
- end
38
- end
39
-
40
- SalesforceStreamer.config.use_middleware MySimpleMiddleware
41
- ```
42
-
43
23
  ### Configure Push Topics
44
24
 
45
- Create a YAML file to configure your server subscriptions. The configuration
46
- for each subscription must have a nested `salesforce:` key. These settings will
47
- be synced to your Salesforce instance when the `-x` flag is set on the command
48
- line. For more information about the `replay:` and `notify_fields_for` options
49
- please see the Salesforce Streaming API reference documentation.
25
+ Create a YAML file to configure your PushTopic subscriptions. When streamer
26
+ starts up it will check for any differences between Salesforce PushTopics and
27
+ this yaml and update any differences when `config.manage_topics = true`.
50
28
 
51
29
  ```yaml
52
30
  # config/streamer.yml
@@ -71,14 +49,6 @@ production:
71
49
  <<: *DEFAULT
72
50
  ```
73
51
 
74
- It's important to note that the way push topics are managed is by the Salesforce
75
- name attribute. This should uniquely identify each push topic. It is not
76
- recommended to change the name of your push topic definitions; otherwise, the
77
- push topic manager will not find a push topic in Salesforce resulting in the
78
- creation of a brand new push topic. If the push topic manager identifies a
79
- difference in any of the other Salesforce attributes, then it will update the
80
- push topic in Salesforce before starting the streaming server.
81
-
82
52
  ### Define Message Handlers
83
53
 
84
54
  Define your handlers somewhere in your project. They must respond to either
@@ -88,14 +58,17 @@ Define your handlers somewhere in your project. They must respond to either
88
58
  # lib/account_change_handler.rb
89
59
  # Handle account changes inline
90
60
  class AccountChangeHandler
91
- def self.call(message)
92
- puts message
61
+ class << self
62
+ def call(message)
63
+ puts message
64
+ end
93
65
  end
94
66
  end
95
67
 
96
68
  # Handle account changes asynchronously
97
69
  class AccountChangeHandler
98
70
  include Sidekiq::Worker
71
+
99
72
  def perform(message)
100
73
  puts message
101
74
  end
@@ -113,13 +86,14 @@ Configure the `SalesforceStreamer` module.
113
86
  ```ruby
114
87
  # config/initializers/salesforce_streamer.rb
115
88
 
116
- SalesforceStreamer.config.logger = Logger.new(STDERR, level: 'INFO')
117
- SalesforceStreamer.config.exception_adapter = proc { |e| puts e }
118
- SalesforceStreamer.config.replay_adapter = proc { |topic|
119
- topic.id || Store.get(topic.name) || topic.replay
120
- }
121
- SalesforceStreamer.config.use_middleware AfterMessageReceived
122
- SalesforceStreamer.config.manage_topics = true
89
+ SalesforceStreamer.configure do |config|
90
+ config.logger = Logger.new(STDERR, level: 'INFO')
91
+ config.exception_adapter = proc { |e| puts e }
92
+ config.replay_adapter = MyReplayAdapter
93
+ config.use_middleware AfterMessageReceived
94
+ config.use_faye_extension ErrorLoggingExtension.new
95
+ config.manage_topics = true
96
+ end
123
97
  ```
124
98
 
125
99
  ### Launch The Streamer
@@ -158,6 +132,59 @@ By default, the executable will load the YAML based on the `RACK_ENV` environmen
158
132
  variable, or default to `:development` if not set. You can override this by
159
133
  setting the `config.environment = :integration`
160
134
 
135
+ ### Message Handling Middleware
136
+
137
+ You can initialize the streamer server with any number of middleware classes.
138
+ When a message is received by a PushTopic subscription, the chain of middleware
139
+ classes are executed before the message handler is called.
140
+
141
+ ```ruby
142
+ # config/initializers/streamer.rb
143
+ class MySimpleMiddleware
144
+ def initialize(handler)
145
+ @handler = handler
146
+ end
147
+
148
+ def call(message)
149
+ @handler.call(message)
150
+ end
151
+ end
152
+
153
+ SalesforceStreamer.config.use_middleware MySimpleMiddleware
154
+ ```
155
+
156
+ ### ReplayAdapter
157
+
158
+ The `config.replay_adapter` should be an object that has an interface like Hash.
159
+ It must respond to `[]` and `[]=`. By default the adapter is an empty hash. If
160
+ you want your push topic replayId to persist between restarts, then you should
161
+ implement a class with an appropriate interface.
162
+
163
+ ```ruby
164
+ class MyReplayAdapter
165
+ def [](channel)
166
+ Persistence.get(channel)
167
+ end
168
+
169
+ def []=(channel, replay_id)
170
+ Persistence.set(channel, replay_id)
171
+ end
172
+ end
173
+ ```
174
+
175
+ This adapter will be used directly by `Restforce::ReplayExtension`.
176
+
177
+ ### Use Faye Extension
178
+
179
+ The `config.use_faye_extension` should be given an object that responds to
180
+ `.incoming(message, callback)` or `.outgoing(message, callback)` or both. Find
181
+ out more about extensions from
182
+ [Faye](https://github.com/faye/faye/blob/master/spec/ruby/server/extensions_spec.rb)
183
+ specs.
184
+
185
+ Any configured extensions are added to the Faye client used by the Restforce
186
+ client when starting up the server.
187
+
161
188
  ## Development
162
189
 
163
190
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake rspec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
@@ -58,4 +58,8 @@ module SalesforceStreamer
58
58
  def self.config
59
59
  Configuration.instance
60
60
  end
61
+
62
+ def self.configure
63
+ yield Configuration.instance
64
+ end
61
65
  end
@@ -32,7 +32,7 @@ module SalesforceStreamer
32
32
  end
33
33
 
34
34
  o.on '-v', '--verbose LEVEL', 'Set the log level (default no logging)' do |arg|
35
- @config.logger = Logger.new(STDERR, level: arg)
35
+ @config.logger = Logger.new($stderr, level: arg)
36
36
  end
37
37
 
38
38
  o.on '-V', '--version', 'Print the version information' do
@@ -3,25 +3,30 @@ module SalesforceStreamer
3
3
  class Configuration
4
4
  attr_accessor :environment, :logger, :require_path, :config_file,
5
5
  :manage_topics, :exception_adapter, :replay_adapter
6
- attr_reader :middleware
6
+ attr_reader :middleware, :faye_extensions
7
7
 
8
8
  class << self
9
9
  attr_writer :instance
10
- end
11
10
 
12
- def self.instance
13
- @instance ||= new
11
+ def configure
12
+ yield instance
13
+ end
14
+
15
+ def instance
16
+ @instance ||= new
17
+ end
14
18
  end
15
19
 
16
20
  def initialize
17
21
  @environment = ENV['RACK_ENV'] || :development
18
22
  @logger = Logger.new(IO::NULL)
19
23
  @exception_adapter = proc { |exc| fail(exc) }
20
- @replay_adapter = proc { |topic| topic.id || topic.replay }
24
+ @replay_adapter = Hash.new { |hash, key| hash[key] = -1 }
21
25
  @manage_topics = false
22
26
  @config_file = './config/streamer.yml'
23
27
  @require_path = './config/environment'
24
28
  @middleware = []
29
+ @faye_extensions = [ReplayIdErrorExtension.new]
25
30
  end
26
31
 
27
32
  def manage_topics?
@@ -33,6 +38,11 @@ module SalesforceStreamer
33
38
  @middleware << [klass, args, block]
34
39
  end
35
40
 
41
+ # adds a Faye extension
42
+ def use_faye_extension(extension)
43
+ @faye_extensions << extension
44
+ end
45
+
36
46
  # returns a ready to use chain of middleware
37
47
  def middleware_runner(last_handler)
38
48
  @middleware.reduce(last_handler) do |next_handler, current_handler|
@@ -34,7 +34,7 @@ module SalesforceStreamer
34
34
  @handler = Object.const_get(@handler)
35
35
  true
36
36
  rescue NameError, TypeError => e
37
- message = 'handler=' + @handler.to_s + ' exception=' + e.to_s
37
+ message = "handler=#{@handler} exception=#{e}"
38
38
  raise(PushTopicHandlerMissingError, message)
39
39
  end
40
40
 
@@ -53,7 +53,7 @@ module SalesforceStreamer
53
53
  if constant.respond_to? :call
54
54
  constant
55
55
  elsif constant.respond_to? :perform_async
56
- proc { |message| handler_constant.perform_async message }
56
+ proc { |message| constant.perform_async message }
57
57
  else
58
58
  fail(UnprocessableHandlerError, constant)
59
59
  end
@@ -8,10 +8,8 @@ module SalesforceStreamer
8
8
  @client.authenticate!
9
9
  end
10
10
 
11
- def subscribe(*args)
12
- @client.subscribe(args) do
13
- yield
14
- end
11
+ def subscribe(*args, &block)
12
+ @client.subscribe(args, &block)
15
13
  end
16
14
 
17
15
  # Returns nil or an instance of Restforce::SObject
@@ -27,19 +27,19 @@ module SalesforceStreamer
27
27
  return @client if @client
28
28
  @client = Restforce.new
29
29
  @client.authenticate!
30
- @client.faye.add_extension ReplayIdErrorExtension.new
30
+ Configuration.instance.faye_extensions.each do |extension|
31
+ Log.debug %(adding Faye extension #{extension})
32
+ @client.faye.add_extension extension
33
+ end
31
34
  @client
32
35
  end
33
36
 
34
37
  def start_em
35
38
  EM.run do
36
39
  @push_topics.map do |topic|
37
- replay_id = Configuration.instance.replay_adapter.call(topic)
38
- client.subscribe topic.name, replay: replay_id.to_i do |message|
39
- replay_id = message.dig('event', 'replayId')
40
- Log.info "Message #{replay_id} received from topic #{topic.name}"
40
+ client.subscribe topic.name, replay: Configuration.instance.replay_adapter do |message|
41
+ Log.info "Message #{message.dig('event', 'replayId')} received from topic #{topic.name}"
41
42
  topic.handle message
42
- topic.id = replay_id
43
43
  end
44
44
  end
45
45
  end
@@ -1,3 +1,3 @@
1
1
  module SalesforceStreamer
2
- VERSION = '2.0.0.rc1'.freeze
2
+ VERSION = '2.2.0'.freeze
3
3
  end
@@ -14,6 +14,7 @@ Gem::Specification.new do |spec|
14
14
 
15
15
  spec.metadata['homepage_uri'] = spec.homepage
16
16
  spec.metadata['source_code_uri'] = spec.homepage
17
+ spec.metadata['documentation_uri'] = 'https://www.rubydoc.info/gems/salesforce_streamer'
17
18
 
18
19
  spec.files = Dir.chdir(File.expand_path(__dir__)) do
19
20
  `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(bin/|spec/|\.rub)}) }
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: salesforce_streamer
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0.rc1
4
+ version: 2.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Scott Serok
8
8
  - RenoFi Engineering Team
9
- autorequire:
9
+ autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2020-08-04 00:00:00.000000000 Z
12
+ date: 2020-11-11 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: dry-initializer
@@ -157,7 +157,7 @@ dependencies:
157
157
  - - ">="
158
158
  - !ruby/object:Gem::Version
159
159
  version: '0'
160
- description:
160
+ description:
161
161
  email:
162
162
  - scott@renofi.com
163
163
  - engineering@renofi.com
@@ -172,6 +172,7 @@ files:
172
172
  - ".github/ISSUE_TEMPLATE/story.md"
173
173
  - ".github/PULL_REQUEST_TEMPLATE.md"
174
174
  - ".github/workflows/auto-approve.yml"
175
+ - ".github/workflows/auto-merge.yml"
175
176
  - ".gitignore"
176
177
  - ".rspec"
177
178
  - ".travis.yml"
@@ -202,7 +203,8 @@ licenses:
202
203
  metadata:
203
204
  homepage_uri: https://github.com/renofi/salesforce_streamer
204
205
  source_code_uri: https://github.com/renofi/salesforce_streamer
205
- post_install_message:
206
+ documentation_uri: https://www.rubydoc.info/gems/salesforce_streamer
207
+ post_install_message:
206
208
  rdoc_options: []
207
209
  require_paths:
208
210
  - lib
@@ -213,12 +215,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
213
215
  version: '2.6'
214
216
  required_rubygems_version: !ruby/object:Gem::Requirement
215
217
  requirements:
216
- - - ">"
218
+ - - ">="
217
219
  - !ruby/object:Gem::Version
218
- version: 1.3.1
220
+ version: '0'
219
221
  requirements: []
220
- rubygems_version: 3.1.2
221
- signing_key:
222
+ rubygems_version: 3.1.4
223
+ signing_key:
222
224
  specification_version: 4
223
225
  summary: A wrapper around the Restforce Streaming API with a built-in PushTopic manager.
224
226
  test_files: []