pushpop 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1 @@
1
+ .env
data/.travis.yml ADDED
@@ -0,0 +1,8 @@
1
+ language: ruby
2
+ bundler_args: --without development
3
+
4
+ rvm:
5
+ - 2.1.1
6
+
7
+ script:
8
+ - bundle exec rake spec
data/Gemfile ADDED
@@ -0,0 +1,13 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'clockwork'
4
+ gem 'keen'
5
+ gem 'twilio-ruby'
6
+ gem 'mail'
7
+ gem 'foreman'
8
+
9
+ group :development, :test do
10
+ gem 'rake'
11
+ gem 'rspec'
12
+ gem 'webmock'
13
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,72 @@
1
+ GEM
2
+ remote: https://rubygems.org/
3
+ specs:
4
+ activesupport (4.1.0)
5
+ i18n (~> 0.6, >= 0.6.9)
6
+ json (~> 1.7, >= 1.7.7)
7
+ minitest (~> 5.1)
8
+ thread_safe (~> 0.1)
9
+ tzinfo (~> 1.1)
10
+ addressable (2.3.6)
11
+ builder (3.2.2)
12
+ clockwork (0.7.4)
13
+ activesupport
14
+ tzinfo
15
+ crack (0.4.2)
16
+ safe_yaml (~> 1.0.0)
17
+ diff-lcs (1.2.5)
18
+ dotenv (0.7.0)
19
+ foreman (0.67.0)
20
+ dotenv (~> 0.7.0)
21
+ thor (~> 0.17.0)
22
+ i18n (0.6.9)
23
+ json (1.8.1)
24
+ jwt (0.1.11)
25
+ multi_json (>= 1.5)
26
+ keen (0.8.1)
27
+ addressable (~> 2.3.5)
28
+ multi_json (~> 1.3)
29
+ mail (2.5.4)
30
+ mime-types (~> 1.16)
31
+ treetop (~> 1.4.8)
32
+ mime-types (1.25.1)
33
+ minitest (5.3.3)
34
+ multi_json (1.9.2)
35
+ polyglot (0.3.4)
36
+ rake (10.3.1)
37
+ rspec (2.14.1)
38
+ rspec-core (~> 2.14.0)
39
+ rspec-expectations (~> 2.14.0)
40
+ rspec-mocks (~> 2.14.0)
41
+ rspec-core (2.14.8)
42
+ rspec-expectations (2.14.5)
43
+ diff-lcs (>= 1.1.3, < 2.0)
44
+ rspec-mocks (2.14.6)
45
+ safe_yaml (1.0.2)
46
+ thor (0.17.0)
47
+ thread_safe (0.3.3)
48
+ treetop (1.4.15)
49
+ polyglot
50
+ polyglot (>= 0.3.1)
51
+ twilio-ruby (3.11.5)
52
+ builder (>= 2.1.2)
53
+ jwt (>= 0.1.2)
54
+ multi_json (>= 1.3.0)
55
+ tzinfo (1.1.0)
56
+ thread_safe (~> 0.1)
57
+ webmock (1.17.4)
58
+ addressable (>= 2.2.7)
59
+ crack (>= 0.3.2)
60
+
61
+ PLATFORMS
62
+ ruby
63
+
64
+ DEPENDENCIES
65
+ clockwork
66
+ foreman
67
+ keen
68
+ mail
69
+ rake
70
+ rspec
71
+ twilio-ruby
72
+ webmock
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ Author Josh Dzielak
2
+ Copyright (c) 2014 Keen Labs
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining
5
+ a copy of this software and associated documentation files (the
6
+ "Software"), to deal in the Software without restriction, including
7
+ without limitation the rights to use, copy, modify, merge, publish,
8
+ distribute, sublicense, and/or sell copies of the Software, and to
9
+ permit persons to whom the Software is furnished to do so, subject to
10
+ the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Procfile ADDED
@@ -0,0 +1 @@
1
+ worker: bundle exec rake jobs:run
data/README.md ADDED
@@ -0,0 +1,582 @@
1
+ # Pushpop
2
+ [![Build Status](https://travis-ci.org/keenlabs/pushpop.svg)](https://travis-ci.org/keenlabs/pushpop)
3
+
4
+ ### Automatic delivery of regular reports and alerts
5
+
6
+ <hr>
7
+ <img src="http://f.cl.ly/items/1I421w263a10340a0u2q/Screen%20Shot%202014-04-16%20at%204.35.47%20PM.png" width="45%" alt="Pingpong Daily Response Time Report">
8
+ &nbsp;&nbsp;&nbsp;
9
+ <img src="http://f.cl.ly/items/3F3X2s2d2A1I1o0V3p1n/image.png" width="45%" alt="There were 5402 Pageviews today!">
10
+ <hr>
11
+
12
+ ## Overview
13
+
14
+ Pushpop is a simple but powerful Ruby app that sends notifications based on events captured with Keen IO.
15
+
16
+ #### Ways to use Pushpop
17
+
18
+ **Regular reports**
19
+
20
+ + Send a sales report to your inbox every day at noon
21
+ + Send analytics reports to your customers every week
22
+
23
+ **Alerts**
24
+
25
+ + Send an SMS if the performance of your signup funnel dramatically changes
26
+ + Send an email when your site has been busier than usual in the last hour
27
+
28
+ #### An example Pushpop job
29
+
30
+ Here's a simple Pushpop job that uses [Twilio](https://twilio.com/) to send an SMS containing the number of daily pageviews each night at midnight:
31
+
32
+ ``` ruby
33
+ require 'pushpop'
34
+
35
+ job do
36
+
37
+ every 24.hours, at: '00:00'
38
+
39
+ keen do
40
+ event_collection 'pageviews'
41
+ analysis_type 'count'
42
+ timeframe 'last_24_hours'
43
+ end
44
+
45
+ twilio do |response|
46
+ to '+18005555555'
47
+ body "There were #{response} pageviews today!"
48
+ end
49
+
50
+ end
51
+ ```
52
+
53
+ Pushpop syntax is short and sweet, but because anything Ruby can be used it's also quite powerful.
54
+
55
+ ### Where to next?
56
+
57
+ Excited to try out Pushpop with your data? Here's a few options to choose from:
58
+
59
+ #### Quickstart
60
+
61
+ Setup Pushpop locally. It takes 10 minutes to get that first shiny report in your inbox, and even less if you already have a Keen IO, Sendgrid or Twilio account.
62
+
63
+ **[Go to the Quickstart](#quickstart)**
64
+
65
+ #### Deploy a Pushpop Instance
66
+
67
+ Ready to deploy the Pushpop job you wrote locally and start getting regular reports? Detailed instructions for Heroku are provided, as well as the basics for other platforms.
68
+
69
+ **[Go to the Deploy Guide](#deploy-guide)**
70
+
71
+ #### Need help?
72
+
73
+ Don't have a hacker at hand? The friendly folks at Keen IO are happy to help you get a Pushpop instance running.
74
+
75
+ **Email [team@keen.io](mailto:team@keen.io?subject=I want a Pushpop!)** with the subject "I want a Pushpop!"
76
+
77
+ ## Quickstart
78
+
79
+ The goal of the Quickstart is to get a Pushpop instance running locally. This should take less than 10 minutes.
80
+
81
+ #### Prerequisites
82
+
83
+ + A working Ruby installation (1.9+)
84
+ + A [Keen IO](https://keen.io) account and project and associated API keys
85
+ + A [Sendgrid](https://sendgrid.com) and/or [Twilio](https://twilio.com) account and associated API keys
86
+
87
+ #### Steps
88
+
89
+ **Clone this repository**
90
+
91
+ ``` shell
92
+ $ git clone git@github.com:keenlabs/pushpop.git
93
+ ```
94
+
95
+ Enter the pushpop directory and install dependencies.
96
+
97
+ ``` shell
98
+ $ cd pushpop
99
+ $ gem install bundler
100
+ $ bundle install
101
+ ```
102
+
103
+ **Test an example job**
104
+
105
+ There is an example job in [jobs/example_job.rb](jobs/example_job.rb). All it does is print some output to the console. Run this job via a rake task to make sure your configuration is setup properly.
106
+
107
+ ``` shell
108
+ $ foreman run rake jobs:run_once[jobs/example_job.rb]
109
+ ```
110
+
111
+ You should see the following output (followed by a logging statement):
112
+
113
+ ``` html
114
+ Hey Pushpop, let's do a math!
115
+ <pre>The number 30!</pre>
116
+ ```
117
+
118
+ **Specify your API credentials**
119
+
120
+ Now it's time to write a job that connects to APIs and does something real. For that we'll need to specify API keys. We'll use [foreman](https://github.com/ddollar/foreman) to tell Pushpop about these API keys. When you use foreman to run a process, it adds variables from a local `.env` file to the process environment. It's very handy for keeping secure API keys out of your code (`.env` files are gitignored by Pushpop).
121
+
122
+ Create a `.env` file in the project directory and add the API configuration properties and keys that you have. Here's what an example file looks like with settings from all three services:
123
+
124
+ ```
125
+ KEEN_PROJECT_ID=*********
126
+ KEEN_READ_KEY=*********
127
+ SENDGRID_DOMAIN=*********
128
+ SENDGRID_PASSWORD=*********
129
+ SENDGRID_USERNAME=*********
130
+ TWILIO_AUTH_TOKEN=*********
131
+ TWILIO_FROM=*********
132
+ TWILIO_SID=*********
133
+ ```
134
+
135
+ **Write your first job**
136
+
137
+ Let's write a job that performs a count of one of your Keen IO collections and sends an email (or SMS) with the result. We'll set it to run every 24 hours.
138
+
139
+ Create a file in the `jobs` folder called `first_job.rb` and paste in the following example:
140
+
141
+ ``` ruby
142
+ job do
143
+
144
+ # how frequently do we want this job to run?
145
+ every 24.hours
146
+
147
+ # what keen io query should be performed?
148
+ keen do
149
+ event_collection '<my-keen-collection-name>'
150
+ analysis_type 'count'
151
+ timeframe 'last_24_hours'
152
+ end
153
+
154
+ # use this block to send an email
155
+ sendgrid do |_, step_responses|
156
+ to '<my-to-email-address>'
157
+ from '<my-from-email-address>'
158
+ subject "There were #{step_responses['keen']} events in the last 24 hours!"
159
+ body 'Blowing up!'
160
+ end
161
+
162
+ # use this block to send an sms
163
+ twilio do |_, step_responses|
164
+ to '<to-phone-number>'
165
+ body "There were #{step_responses['keen']} events in the last 24 hours!"
166
+ end
167
+ end
168
+ ```
169
+
170
+ Now modify the example to use your specific information. You'll want to specify a `to` and a `from` address if you're using Sendgrid, and a `to` phone number if you're using Twilio. Everything you need to change is marked with `<>`. You'll also want to remove either Sendgrid or Twilio blocks you're not using them.
171
+
172
+ Save the file and test this job using the same `jobs:run_once` rake task that we used before.
173
+
174
+ ``` shell
175
+ $ foreman run rake jobs:run_once[jobs/first_job.rb]
176
+ ```
177
+
178
+ The output of each step will be logged to the console, and if everything worked you'll receive an email or a text message within a few seconds!
179
+
180
+ **Next steps**
181
+
182
+ + Write and test more jobs. See the [Pushpop API Documentation](#pushpop-api-documentation) below for more examples of what you can do.
183
+ + Continue on to the deploy guide to deploy a Pushpop instance and start getting regular reports and alerts.
184
+
185
+ ## Deploy Guide
186
+
187
+ ##### Heroku
188
+
189
+ These instructions are for Heroku, but should be relevant to most environments.
190
+
191
+ **Prerequisites**
192
+
193
+ You'll need a Heroku account, and the [Heroku toolbelt](https://toolbelt.heroku.com/) installed.
194
+
195
+ **Create a new Heroku app**
196
+
197
+ Make sure you're inside the Pushpop directory.
198
+
199
+ ``` shell
200
+ $ heroku create
201
+ ```
202
+
203
+ **Commit changes**
204
+
205
+ If you created a new job from the Quickstart guide, you'll want to commit that code before deploying.
206
+
207
+ ``` shell
208
+ $ git commit -am 'Created my first Pushpop job'
209
+ ```
210
+
211
+ **Set Heroku config variables**
212
+
213
+ The easiest way to do this is with the [heroku-config](https://github.com/ddollar/heroku-config) plugin. This step assumes you have created a `.env` file containing your keys as demonstrated in the Quickstart guide.
214
+
215
+ ``` shell
216
+ $ heroku plugins:install git://github.com/ddollar/heroku-config.git
217
+ $ heroku config:push
218
+ ```
219
+
220
+ **Deploy code to Heroku**
221
+
222
+ Now that your code is commited and config variables pushed we can begin a deploy.
223
+
224
+ ``` shell
225
+ $ git push heroku master
226
+ ```
227
+
228
+ **Tail logs to confirm it's working**
229
+
230
+ To see that jobs are running and that there are no errors, tail the logs on Heroku.
231
+
232
+ ``` shell
233
+ $ heroku logs --tail
234
+ ```
235
+
236
+ Note that if you have jobs that are set to run at specific times of day you might not see output for a while.
237
+
238
+ Also note - by default this will run all jobs in the `jobs` folder. You might want to delete the `example_job.rb` file in
239
+ a separate commit once you've got the hang of things.
240
+
241
+ ##### Other environments
242
+
243
+ Pushpop is run entirely by one long-running Ruby process. Anywhere you can run this process in a monitored fashion you can run a Pushpop instance. Here's the command:
244
+
245
+ ``` shell
246
+ $ foreman run rake jobs:run
247
+ ```
248
+
249
+ If you don't want to use foreman and prefer to set the environment variables yourself then all you need is this:
250
+
251
+ ``` shell
252
+ $ bundle exec rake jobs:run
253
+ ```
254
+
255
+ ## Rake Tasks
256
+
257
+ All `jobs:*` rake tasks optionally take a single filename as a parameter. The file is meant to contain one or more Pushpop jobs. If no filename is specified, all jobs in the jobs folder are considered.
258
+
259
+ Specifying a specific file looks like this:
260
+
261
+ ``` shell
262
+ $ foreman run rake jobs:run[jobs/just_this_job.rb]
263
+ ```
264
+
265
+ Here's a list of the available rake tasks:
266
+
267
+ + `jobs:describe` - Print out the names of jobs in the jobs folder.
268
+ + `jobs:run_once` - Run each job once, right now.
269
+ + `jobs:run` - Run jobs as scheduled in a long-running process. This is the task used when you deploy.
270
+ + `spec` - Run the specs.
271
+
272
+ ## Pushpop API Documentation
273
+
274
+ Steps and jobs are the heart of the Pushpop workflow. Ruby jobs files contain one or more jobs, and each job consists of one or more steps.
275
+
276
+ #### Jobs
277
+
278
+ Jobs have the following attributes:
279
+
280
+ + `name`: (optional) something that describe the job, useful in logs
281
+ + `every_duration`: the frequency at which to run the job
282
+ + `every_options` (optional): options related to when the job runs
283
+ + `steps`: the ordered list of steps to run
284
+
285
+ These attributes are easily specified using the DSL's block syntax. Here's an example:
286
+
287
+ ``` ruby
288
+ job 'print job' do
289
+ every 5.minutes
290
+ step do
291
+ puts "5 minutes later..."
292
+ end
293
+ end
294
+ ```
295
+
296
+ Inside of a `job` configuration block, steps are added by using the `step` method. They can also be
297
+ added by using a method registered by a plugin, like `keen` or `twilio`. For more information, see [Plugin Documentation](#plugin-documentation).
298
+
299
+ The frequency of the job is set via the `every` method. This is basically a passthrough to Clockwork.
300
+ Here are some cool things you can do with regard to scheduling:
301
+
302
+ ``` ruby
303
+ every 5.seconds
304
+ every 24.hours, at: '12:00'
305
+ every 24.hours, at: ['00:00', '12:00']
306
+ every 24.hours, at: '**:05'
307
+ every 24.hours, at: '00:00', tz: 'UTC'
308
+ every 5.seconds, at: '10:**'
309
+ every 1.week, at: 'Monday 12:30'
310
+ ```
311
+
312
+ See the full set of options on the [Clockwork README](https://github.com/tomykaira/clockwork#event-parameters).
313
+
314
+ ##### Job workflow
315
+
316
+ When a job kicks off, steps are run serially in the order they are specified. Each step is invoked with 2
317
+ arguments - the response of the step immediately preceding it, and a map of all responses so far.
318
+ The map is keyed by step name, which defaults to a plugin name if a plugin was used but a step name not specified.
319
+
320
+ Here's an example that shows how the response chain works:
321
+
322
+ ``` ruby
323
+ job do
324
+ every 5.minutes
325
+ step 'one' do
326
+ 1
327
+ end
328
+ step 'two' do |response|
329
+ 5 + response
330
+ end
331
+ step 'add previous steps' do |response, step_responses|
332
+ puts response # prints 5
333
+ puts step_responses['one'] + step_responses['two'] # prints 6
334
+ end
335
+ end
336
+ ```
337
+
338
+ If a `step` returns false, subsequent steps **are not run**. Here's a simple example that illustrates this:
339
+
340
+ ``` ruby
341
+ job 'lame job' do
342
+ every 5.minutes
343
+ step 'one' do
344
+ false
345
+ end
346
+ step 'two' do
347
+ # never called!
348
+ end
349
+ end
350
+ ```
351
+
352
+ This behavior is designed to make *conditional* alerting easy. Here's an example of a job that only sends an alert
353
+ for certain query responses:
354
+
355
+ ``` ruby
356
+ job do
357
+
358
+ every 1.minute
359
+
360
+ keen do
361
+ event_collection 'errors'
362
+ analysis_type 'count'
363
+ timeframe 'last_1_minute'
364
+ end
365
+
366
+ step 'notify only if there are errors' do |response|
367
+ response > 0
368
+ end
369
+
370
+ twilio do |step_responses|
371
+ to '+18005555555'
372
+ body "There were #{step_responses['keen']} errors in the last minute!"
373
+ end
374
+ end
375
+ ```
376
+
377
+ In this example, the `twilio` step will only be ran if the `keen` step returned a count greater than 0.
378
+
379
+ #### Steps
380
+
381
+ Steps have the following attributes:
382
+
383
+ + `name`: (optional) something that describes the step. Useful in logs, and is the key in the `step_responses` hash. Defaults to plugin name if a plugin is used
384
+ + `plugin`: (optional) if the step is backed by a plugin, it's the name of the plugin
385
+ + `block`: A block that runs to configure the step (when a plugin is used) or run it
386
+
387
+ Steps can be pure Ruby code or leverage a plugin DSL. Plugins are just fancy abstractions for creating steps.
388
+
389
+ Steps have built-in support for ERB templating. This is useful for generating more complex emails and reports.
390
+
391
+ Here's an example that uses a template:
392
+
393
+ ``` ruby
394
+ sendgrid do |response, step_responses|
395
+ to 'josh+pushpop@keen.io'
396
+ from 'pushpopapp+123@keen.io'
397
+ subject 'Pingpong Daily Response Time Report'
398
+ body template 'pingpong_report.html.erb', response, step_responses
399
+ preview false
400
+ end
401
+ ```
402
+
403
+ `template` is a function that renders a template in context of the step responses and returns a string.
404
+ The first argument is a template file name, located in the `templates` directory by default.
405
+ The second and third arguments are the `response` and `step_responses` respectively.
406
+ An optional fourth parameter can be used to change the path templates are looked up in.
407
+
408
+ Here's a very simple template:
409
+
410
+ ``` erb
411
+ <h1>Daily Report</h1>
412
+ <p>We got <%= response %> new users today!</p>
413
+ ```
414
+
415
+ ## Recipes
416
+
417
+ The community-driven [pushpop-recipes](https://github.com/keenlabs/pushpop-recipes) repository contains jobs and templates
418
+ for doing common things with Pushpop. Check it out for some inspiration!
419
+
420
+ ## Plugin Documentation
421
+
422
+ Plugins are located at `lib/plugins`. They are loaded automatically.
423
+
424
+ ##### Keen
425
+
426
+ The `keen` plugin gives you a DSL to specify Keen query parameters. When it runs, it
427
+ passes those parameters to the [keen gem](https://github.com/keenlabs/keen-gem), which
428
+ in turn runs the query against the Keen IO API.
429
+
430
+ Here's an example that shows most of the options you can specify:
431
+
432
+ ``` ruby
433
+ job 'daily average response time by check for successful requests in april' do
434
+
435
+ keen do
436
+ event_collection 'checks'
437
+ analysis_type 'average'
438
+ target_property 'request.duration'
439
+ group_by 'check.name'
440
+ interval 'daily'
441
+ timeframe ({ start: '2014-04-01T00:00Z' })
442
+ filters [{ property_name: "response.successful",
443
+ operator: "eq",
444
+ property_value: true }]
445
+ end
446
+
447
+ end
448
+ ```
449
+
450
+ The `keen` plugin requires that the following environment variables are set: `KEEN_PROJECT_ID` and `KEEN_READ_KEY`.
451
+
452
+ A `steps` method is also supported for [funnels](https://keen.io/docs/data-analysis/funnels/),
453
+ as well as `analyses` for doing a [multi-analysis](https://keen.io/docs/data-analysis/multi-analysis/).
454
+
455
+ ##### Sendgrid
456
+
457
+ The `sendgrid` plugin gives you a DSL to specify email parameters like subject and body.
458
+
459
+ Here's an example:
460
+
461
+ ``` ruby
462
+ job 'send an email' do
463
+
464
+ sendgrid do
465
+ to 'josh+pushpop@keen.io'
466
+ from 'pushpopapp+123@keen.io'
467
+ subject 'Is your inbox lonely?'
468
+ body 'This email was intentionally left blank.'
469
+ preview false
470
+ end
471
+
472
+ end
473
+ ```
474
+
475
+ The `sendgrid` plugin requires that the following environment variables are set: `SENDGRID_DOMAIN`, `SENDGRID_USERNAME`, and `SENDGRID_PASSWORD`.
476
+
477
+ The `preview` directive is optional and defaults to false. If you set it to true, the email contents will print out
478
+ to the console, but the email will not be sent.
479
+
480
+ The `body` method can take a string, or it can take the same parameters as `template`,
481
+ in which case it will render a template to create the body. For example:
482
+
483
+ ``` ruby
484
+ body 'pingpong_report.html.erb', response, step_responses
485
+ ```
486
+
487
+ ##### Twilio
488
+
489
+ The `twilio` plugin provides DSL to specify SMS recipient information as well as the text itself.
490
+
491
+ Here's an example:
492
+
493
+ ``` ruby
494
+ job 'send a text' do
495
+
496
+ twilio do
497
+ to '18005555555'
498
+ body 'Breathe in through the nose, out through the mouth.'
499
+ end
500
+
501
+ end
502
+ ```
503
+
504
+ The `twilio` plugin requires that the following environment variables are set: `TWILIO_AUTH_TOKEN`, `TWILIO_SID`, and `TWILIO_FROM`.
505
+
506
+ ## Creating plugins
507
+
508
+ Plugins are just subclasses of `Pushpop::Step`. Plugins should implement a run method, and
509
+ register themselves. Here's a simple plugin that stops job execution if the input into the step is 0:
510
+
511
+ ``` ruby
512
+ module Pushpop
513
+ class BreakIfZero < Step
514
+ PLUGIN_NAME = 'break_if_zero'
515
+ def run(last_response=nil, step_responses=nil)
516
+ last_response == 0
517
+ end
518
+ end
519
+
520
+ Pushpop::Job.register_plugin(BreakIfZero::PLUGIN_NAME, BreakIfZero)
521
+ end
522
+
523
+ # now in your job you can use the break_if_zero step
524
+
525
+ job do
526
+ step do [0, 1].shuffle.first end
527
+ break_if_zero
528
+ step do puts 'made it through!' end
529
+ end
530
+ ```
531
+
532
+ ## Usage as a Ruby gem
533
+
534
+ Pushpop is also a Ruby gem, so you can add it to an existing Ruby project. Here's how to do that:
535
+
536
+ **Install the gem**
537
+
538
+ ``` ruby
539
+ # bundler
540
+ gem 'pushpop'
541
+
542
+ # not bundler
543
+ gem install 'pushpop'
544
+ ```
545
+
546
+ **Require job files and run**
547
+
548
+ Once the gem is available, you should be able to load in Pushpop job files. Once a file loads,
549
+ all of its jobs are ready to be run or scheduled.
550
+
551
+ ``` ruby
552
+ load 'some_job.rb'
553
+
554
+ # run the jobs once
555
+ Pushpop.run
556
+
557
+ # or schedule and run the jobs with clockwork
558
+ Pushpop.schedule
559
+ Clockwork.manager.run
560
+ ```
561
+
562
+ Note that `pushpop` does not declare dependencies other than `clockwork` and `keen`. If you're using
563
+ Pushpop plugins like Sendgrid or Twilio you'll need to install and require those dependencies explicitly.
564
+
565
+ ## Contributing
566
+
567
+ Issues and pull requests are welcome!
568
+
569
+ **Wishlist**
570
+
571
+ + Add plugins for more data collection and notification services
572
+ + Add a web interface that shows the job names, job results, and a countdown to the next run
573
+ + Add a web interface that lets you preview emails in the browser
574
+ + Beautiful email templates with support for typical Keen IO query responses (groups, series, etc)
575
+
576
+ **Testing**
577
+
578
+ Pushpop has a full set of specs (including plugins). Run them like this:
579
+
580
+ ``` shell
581
+ $ bundle exec rake spec
582
+ ```