Skip to content

Commit 98a14f2

Browse files
committed
Merge pull request #98 from pusher/batch-events
Add support for batch events
2 parents cc8223d + 7fced7f commit 98a14f2

File tree

3 files changed

+84
-15
lines changed

3 files changed

+84
-15
lines changed

README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,18 @@ An optional fourth argument may be used to send additional parameters to the API
131131
Pusher.trigger('channel', 'event', {foo: 'bar'}, {socket_id: '123.456'})
132132
```
133133

134+
#### Batches
135+
136+
It's also possible to send multiple events with a single API call (max 10
137+
events per call on multi-tenant clusters):
138+
139+
``` ruby
140+
Pusher.trigger_batch([
141+
{channel: 'channel_1', name: 'event_name', data: { foo: 'bar' }}
142+
{channel: 'channel_1', name: 'event_name', data: { hello: 'world' }}
143+
])
144+
```
145+
134146
#### Deprecated publisher API
135147

136148
Most examples and documentation will refer to the following syntax for triggering an event:

lib/pusher/client.rb

Lines changed: 41 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -269,13 +269,35 @@ def trigger(channels, event_name, data, params = {})
269269
post('/events', trigger_params(channels, event_name, data, params))
270270
end
271271

272+
# Trigger multiple events at the same time
273+
#
274+
# POST /apps/[app_id]/batch_events
275+
#
276+
# @param events [Array] List of events to publish
277+
#
278+
# @return [Hash] See Pusher API docs
279+
#
280+
# @raise [Pusher::Error] Unsuccessful response - see the error message
281+
# @raise [Pusher::HTTPError] Error raised inside http client. The original error is wrapped in error.original_error
282+
#
283+
def trigger_batch(*events)
284+
post('/batch_events', trigger_batch_params(events.flatten))
285+
end
286+
272287
# Trigger an event on one or more channels asynchronously.
273288
# For parameters see #trigger
274289
#
275290
def trigger_async(channels, event_name, data, params = {})
276291
post_async('/events', trigger_params(channels, event_name, data, params))
277292
end
278293

294+
# Trigger multiple events asynchronously.
295+
# For parameters see #trigger_batch
296+
#
297+
def trigger_batch_async(*events)
298+
post_async('/batch_events', trigger_batch_params(events.flatten))
299+
end
300+
279301
# Generate the expected response for an authentication endpoint.
280302
# See http://pusher.com/docs/authenticating_users for details.
281303
#
@@ -351,23 +373,27 @@ def trigger_params(channels, event_name, data, params)
351373
channels = Array(channels).map(&:to_s)
352374
raise Pusher::Error, "Too many channels (#{channels.length}), max 10" if channels.length > 10
353375

354-
encoded_data = case data
355-
when String
356-
data
357-
else
358-
begin
359-
MultiJson.encode(data)
360-
rescue MultiJson::DecodeError => e
361-
Pusher.logger.error("Could not convert #{data.inspect} into JSON")
362-
raise e
376+
params.merge({
377+
name: event_name,
378+
channels: channels,
379+
data: encode_data(data),
380+
})
381+
end
382+
383+
def trigger_batch_params(events)
384+
{
385+
batch: events.map do |event|
386+
event.dup.tap do |e|
387+
e[:data] = encode_data(e[:data])
388+
end
363389
end
364-
end
390+
}
391+
end
365392

366-
return params.merge({
367-
:name => event_name,
368-
:channels => channels,
369-
:data => encoded_data,
370-
})
393+
# JSON-encode the data if it's not a string
394+
def encode_data(data)
395+
return data if data.is_a? String
396+
MultiJson.encode(data)
371397
end
372398

373399
def configured?

spec/client_spec.rb

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,37 @@
274274
end
275275
end
276276

277+
describe '#trigger_batch' do
278+
before :each do
279+
@api_path = %r{/apps/20/batch_events}
280+
stub_request(:post, @api_path).to_return({
281+
:status => 200,
282+
:body => MultiJson.encode({})
283+
})
284+
end
285+
286+
it "should call correct URL" do
287+
expect(@client.trigger_batch(channel: 'mychannel', name: 'event', data: {'some' => 'data'})).
288+
to eq({})
289+
end
290+
291+
it "should convert non string data to JSON before posting" do
292+
@client.trigger_batch(
293+
{channel: 'mychannel', name: 'event', data: {'some' => 'data'}},
294+
{channel: 'mychannel', name: 'event', data: 'already encoded'},
295+
)
296+
expect(WebMock).to have_requested(:post, @api_path).with { |req|
297+
parsed = MultiJson.decode(req.body)
298+
expect(parsed).to eq(
299+
"batch" => [
300+
{ "channel" => "mychannel", "name" => "event", "data" => "{\"some\":\"data\"}"},
301+
{ "channel" => "mychannel", "name" => "event", "data" => "already encoded"}
302+
]
303+
)
304+
}
305+
end
306+
end
307+
277308
describe '#trigger_async' do
278309
before :each do
279310
@api_path = %r{/apps/20/events}

0 commit comments

Comments
 (0)