watercooling 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +19 -7
- data/VERSION +1 -1
- data/lib/watercooling/models/webhook.rb +2 -0
- data/lib/watercooling/postbin.rb +1 -1
- data/lib/watercooling/webhook_queue.rb +42 -7
- data/lib/watercooling.rb +21 -13
- data/spec/watercooling_spec.rb +18 -3
- data/watercooling.gemspec +2 -2
- metadata +7 -3
data/README.md
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
Asynchronous webhook queueing with skinny daemon support.
|
4
4
|
|
5
|
-
Inspired by
|
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
|
-
#
|
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
|
-
#
|
28
|
+
# Using
|
29
29
|
|
30
|
-
|
30
|
+
Required param:
|
31
31
|
|
32
|
-
|
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', '
|
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.
|
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
|
data/lib/watercooling/postbin.rb
CHANGED
@@ -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', :
|
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
|
-
|
15
|
-
|
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
|
-
|
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
|
-
|
24
|
-
|
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
|
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
|
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
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
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
|
data/spec/watercooling_spec.rb
CHANGED
@@ -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',
|
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',
|
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',
|
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.
|
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-
|
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
|
-
-
|
9
|
-
version: 0.0.
|
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-
|
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"
|