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 +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"
|