watercooling 0.0.2 → 0.0.3

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.
data/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Asynchronous webhook queueing with skinny daemon support.
4
4
 
5
- Inspired by @progriums Hookah and Watercoolr (http://watercoolr.nuklei.com/).
5
+ Inspired by Watercoolr (http://watercoolr.nuklei.com/) and @progrium's Hookah.
6
6
 
7
7
  # Installing
8
8
 
@@ -15,7 +15,7 @@ From source:
15
15
  rake build
16
16
  sudo rake install
17
17
 
18
- # Start
18
+ # Starting
19
19
 
20
20
  Start as a regular server:
21
21
 
@@ -25,20 +25,32 @@ Start as a daemon:
25
25
 
26
26
  watercooling start -d
27
27
 
28
- # Use
28
+ # Using
29
29
 
30
- Send out a webhook to be asynchronous queued and sent.
30
+ Required param:
31
31
 
32
- The _url param is required. All other params are optional.
32
+ * _url [webhook end destination]
33
+
34
+ Optional params:
35
+
36
+ * _callback [url for POST request on SUCCESS]
37
+ * _errback [url for POST request on FAILURE]
38
+
39
+ Example:
33
40
 
34
- → POST /dispatch { '_url':'http://www.postbin.org/1jp87ds', 'param1':'value1', etc.. }
41
+ → POST /dispatch { '_url':'http://www.postbin.org/1jp87ds', '_callback':'http://callbackaddress.com', '_errback':'http://errbackaddress.com', etc.. }
35
42
 
36
43
  # Todo
37
44
 
38
45
  * pub/sub support
46
+ * true evented support
39
47
  * web interface
40
48
  * application configuration
41
- * success and error callbacks
49
+ * <del>success and error callbacks</del>
50
+
51
+ # Helping
52
+
53
+ Help me make this a better product. Contact me at linuxsable@gmail.com.
42
54
 
43
55
  # Copyright
44
56
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.2
1
+ 0.0.3
@@ -4,6 +4,8 @@ class Webhook
4
4
  property :id, Serial
5
5
  property :queued, Boolean, :default => false
6
6
  property :url, String
7
+ property :callback, String
8
+ property :errback, String
7
9
  property :sent, Boolean, :default => false
8
10
  property :sent_at, DateTime
9
11
  property :send_error, String
@@ -4,5 +4,5 @@ require 'rest-client'
4
4
  url = "http://localhost:2003"
5
5
 
6
6
  puts "sending webhook"
7
- resp = RestClient.post(url + '/dispatch', :_url => ARGV[0], :test_param1 => 'test1', :test_param2 => 'test2')
7
+ resp = RestClient.post(url + '/dispatch', :_url => ARGV[0], :test_param1 => 'test1', :_callback => ARGV[0], :_errback => ARGV[0])
8
8
  puts resp
@@ -9,10 +9,12 @@ class WebhookQueue
9
9
  EM.add_periodic_timer(1) {
10
10
  send_current_webhooks
11
11
  }
12
+ puts "Watercoolr is cooling..."
12
13
  end
13
14
 
14
- # Loop through all pending messages and send them.
15
- # Allow a max retry of @@retries
15
+ private
16
+
17
+ # Currently this method is blocking.
16
18
  def send_current_webhooks
17
19
  queued_webhooks = Webhook.all(:queued => true, :sent => false)
18
20
  queued_webhooks.each do |webhook|
@@ -20,21 +22,54 @@ class WebhookQueue
20
22
  while trys > 0
21
23
  num_tries = 4 - trys
22
24
  begin
23
- # Grab all the webhook params and send em
24
- params = {}
25
- webhook.params.each { |param| params[param.name] = param.value }
26
- response = HTTPClient.post(webhook.url, JSON.generate(params))
25
+ send_webhook(webhook)
27
26
  webhook.update!(:sent => true, :sent_at => Time.now, :queued => false, :send_num_tries => num_tries)
27
+ callback(webhook)
28
28
  break
29
29
  rescue => e
30
30
  trys -= 1
31
- sleep 1
32
31
  if trys == 0
33
32
  # Failed to send. Take it off the queue and log error.
34
33
  webhook.update!(:sent => false, :queued => false, :send_error => e, :send_num_tries => num_tries)
34
+ errback(webhook)
35
35
  end
36
36
  end
37
37
  end
38
38
  end
39
39
  end
40
+
41
+ # Fire off the webhook
42
+ def send_webhook(webhook)
43
+ params = {}
44
+ webhook.params.each { |param| params[param.name] = param.value }
45
+ HTTPClient.post(webhook.url, params)
46
+ end
47
+
48
+ # Send a POST back to user on SUCCESS if callback url supplied
49
+ def callback(webhook)
50
+ return false if webhook.callback.nil?
51
+ operation = proc {
52
+ HTTPClient.post(webhook.callback,
53
+ :status => 'OK',
54
+ :id => webhook.id,
55
+ :sent_at => webhook.sent_at.to_time.to_i,
56
+ :send_num_tries => webhook.send_num_tries
57
+ )
58
+ }
59
+ EM.defer(operation)
60
+ end
61
+
62
+ # Send a POST back to user on ERROR if errback url supplied
63
+ def errback(webhook)
64
+ return false if webhook.errback.nil?
65
+ operation = proc {
66
+ HTTPClient.post(webhook.errback,
67
+ :status => 'FAIL',
68
+ :id => webhook.id,
69
+ :send_error => webhook.send_error,
70
+ :send_num_tries => webhook.send_num_tries
71
+ )
72
+ }
73
+ EM.defer(operation)
74
+ end
40
75
  end
data/lib/watercooling.rb CHANGED
@@ -20,8 +20,12 @@ require File.dirname(__FILE__) + '/watercooling/models/param'
20
20
  class Watercooling < Sinatra::Base
21
21
  # Database config
22
22
  configure :production, :development do
23
- db = "sqlite3:///#{Dir.pwd}/lib/watercooling.sqlite3"
24
- DataMapper.setup(:default, db)
23
+ db_path = "#{ENV['HOME']}/.watercooling"
24
+ if !File.exist?(db_path)
25
+ puts "Creating directory \"#{ENV['HOME']}/.watercooling\"."
26
+ FileUtils.mkdir(db_path)
27
+ end
28
+ DataMapper.setup(:default, 'sqlite3:///' + db_path + '/database.sqlite3')
25
29
  end
26
30
 
27
31
  configure :test do
@@ -39,7 +43,7 @@ class Watercooling < Sinatra::Base
39
43
  end
40
44
 
41
45
  configure do
42
- # Fire up the message queue
46
+ # Fire up the webhook queue
43
47
  Thread.new do
44
48
  until EM.reactor_running?
45
49
  sleep 1
@@ -57,27 +61,31 @@ class Watercooling < Sinatra::Base
57
61
  erb :index
58
62
  end
59
63
 
60
- # Accept a webhook with a special field of _url to be queued to be sent out.
64
+ # Accept a webhook with a special to be queued to be sent out
61
65
  post '/dispatch' do
62
66
  content_type :json
63
67
  response = false
64
-
68
+
65
69
  if params[:_url]
66
- if webhook = Webhook.create(:queued => true, :url => params[:_url])
67
- params.each do |key, value|
68
- unless key == '_url'
69
- response = webhook.params.create(:name => key, :value => value)
70
- end
70
+ webhook = Webhook.create(
71
+ :queued => true,
72
+ :url => params[:_url],
73
+ :callback => params[:_callback],
74
+ :errback => params[:_errback]
75
+ )
76
+
77
+ meta_params = ['_url', '_callback', '_errback']
78
+ params.each do |key, value|
79
+ unless meta_params.include?(key)
80
+ response = webhook.params.create(:name => key, :value => value)
71
81
  end
72
- else
73
- fail_reason = "Couldn't queue webhook."
74
82
  end
75
83
  else
76
84
  fail_reason = '_url post param required.'
77
85
  end
78
86
 
79
87
  if response
80
- { :status => 'OK' }.to_json
88
+ { :status => 'OK', :id => webhook.id }.to_json
81
89
  else
82
90
  { :status => 'FAIL', :reason => fail_reason }.to_json
83
91
  end
@@ -7,19 +7,34 @@ URL = 'http://localhost:2003'
7
7
  # address of your app before running the tests.
8
8
  describe "watercooling" do
9
9
  it "should add webhook" do
10
- response = RestClient.post(URL + '/dispatch', :_url => 'http://google.com', :test_param => 'test')
10
+ response = RestClient.post(URL + '/dispatch',
11
+ :_url => 'http://google.com',
12
+ :_callback => 'http://google.com',
13
+ :_errback => 'http://google.com',
14
+ :test_param => 'test'
15
+ )
11
16
  JSON.parse(response)['status'].should == 'OK'
12
17
  end
13
18
 
14
19
  it "should fail if _url is missing" do
15
- response = RestClient.post(URL + '/dispatch', :url => 'http://google.com', :test_param => 'test')
20
+ response = RestClient.post(URL + '/dispatch',
21
+ :url => 'http://google.com',
22
+ :_callback => 'http://google.com',
23
+ :_errback => 'http://google.com',
24
+ :test_param => 'test'
25
+ )
16
26
  JSON.parse(response)['status'].should == 'FAIL'
17
27
  end
18
28
 
19
29
  it "should add webhook to queue" do
20
30
  _url = 'http://asdf.com'
21
31
 
22
- RestClient.post(URL + '/dispatch', :_url => _url, :test_param => 'test')
32
+ response = RestClient.post(URL + '/dispatch',
33
+ :_url => _url,
34
+ :_callback => 'http://google.com',
35
+ :_errback => 'http://google.com',
36
+ :test_param => 'test'
37
+ )
23
38
  webhook = Webhook.first(:url => _url)
24
39
  webhook.id.should > 0
25
40
 
data/watercooling.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{watercooling}
8
- s.version = "0.0.2"
8
+ s.version = "0.0.3"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["@_ty"]
12
- s.date = %q{2010-09-01}
12
+ s.date = %q{2010-09-12}
13
13
  s.default_executable = %q{watercooling}
14
14
  s.description = %q{Asynchronous webhook queueing with skinny daemon support.}
15
15
  s.email = %q{linuxsable@gmail.com}
metadata CHANGED
@@ -1,12 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: watercooling
3
3
  version: !ruby/object:Gem::Version
4
+ hash: 25
4
5
  prerelease: false
5
6
  segments:
6
7
  - 0
7
8
  - 0
8
- - 2
9
- version: 0.0.2
9
+ - 3
10
+ version: 0.0.3
10
11
  platform: ruby
11
12
  authors:
12
13
  - "@_ty"
@@ -14,7 +15,7 @@ autorequire:
14
15
  bindir: bin
15
16
  cert_chain: []
16
17
 
17
- date: 2010-09-01 00:00:00 -07:00
18
+ date: 2010-09-12 00:00:00 -07:00
18
19
  default_executable: watercooling
19
20
  dependencies:
20
21
  - !ruby/object:Gem::Dependency
@@ -25,6 +26,7 @@ dependencies:
25
26
  requirements:
26
27
  - - ">="
27
28
  - !ruby/object:Gem::Version
29
+ hash: 13
28
30
  segments:
29
31
  - 1
30
32
  - 2
@@ -76,6 +78,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
76
78
  requirements:
77
79
  - - ">="
78
80
  - !ruby/object:Gem::Version
81
+ hash: 3
79
82
  segments:
80
83
  - 0
81
84
  version: "0"
@@ -84,6 +87,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
84
87
  requirements:
85
88
  - - ">="
86
89
  - !ruby/object:Gem::Version
90
+ hash: 3
87
91
  segments:
88
92
  - 0
89
93
  version: "0"