watercooling 0.0.2
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/.document +5 -0
- data/.gitignore +21 -0
- data/LICENSE +20 -0
- data/README.md +45 -0
- data/Rakefile +50 -0
- data/VERSION +1 -0
- data/bin/watercooling +14 -0
- data/lib/watercooling/config.ru +2 -0
- data/lib/watercooling/models/param.rb +11 -0
- data/lib/watercooling/models/webhook.rb +15 -0
- data/lib/watercooling/postbin.rb +8 -0
- data/lib/watercooling/public/.sass-cache/0c0382c87ab4b8085b4c92f483d8ad06e341672b/style.scssc +0 -0
- data/lib/watercooling/public/style.css +1 -0
- data/lib/watercooling/views/index.erb +10 -0
- data/lib/watercooling/webhook_queue.rb +40 -0
- data/lib/watercooling.rb +85 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +9 -0
- data/spec/watercooling_spec.rb +30 -0
- data/watercooling.gemspec +66 -0
- metadata +99 -0
data/.document
ADDED
data/.gitignore
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Tyler Van Hoomissen
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
# Watercooling
|
2
|
+
|
3
|
+
Asynchronous webhook queueing with skinny daemon support.
|
4
|
+
|
5
|
+
Inspired by @progriums Hookah and Watercoolr (http://watercoolr.nuklei.com/).
|
6
|
+
|
7
|
+
# Installing
|
8
|
+
|
9
|
+
From rubygems:
|
10
|
+
|
11
|
+
sudo gem install watercooling
|
12
|
+
|
13
|
+
From source:
|
14
|
+
|
15
|
+
rake build
|
16
|
+
sudo rake install
|
17
|
+
|
18
|
+
# Start
|
19
|
+
|
20
|
+
Start as a regular server:
|
21
|
+
|
22
|
+
watercooling start
|
23
|
+
|
24
|
+
Start as a daemon:
|
25
|
+
|
26
|
+
watercooling start -d
|
27
|
+
|
28
|
+
# Use
|
29
|
+
|
30
|
+
Send out a webhook to be asynchronous queued and sent.
|
31
|
+
|
32
|
+
The _url param is required. All other params are optional.
|
33
|
+
|
34
|
+
→ POST /dispatch { '_url':'http://www.postbin.org/1jp87ds', 'param1':'value1', etc.. }
|
35
|
+
|
36
|
+
# Todo
|
37
|
+
|
38
|
+
* pub/sub support
|
39
|
+
* web interface
|
40
|
+
* application configuration
|
41
|
+
* success and error callbacks
|
42
|
+
|
43
|
+
# Copyright
|
44
|
+
|
45
|
+
Copyright (c) 2010 @_ty. See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "watercooling"
|
8
|
+
gem.summary = %Q{Asynchrnous webhook queueing.}
|
9
|
+
gem.description = %Q{Asynchronous webhook queueing with skinny daemon support.}
|
10
|
+
gem.email = "linuxsable@gmail.com"
|
11
|
+
gem.homepage = "http://github.com/linuxsable/watercooling"
|
12
|
+
gem.authors = ["@_ty"]
|
13
|
+
gem.add_development_dependency "rspec", ">= 1.2.9"
|
14
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
15
|
+
end
|
16
|
+
Jeweler::GemcutterTasks.new
|
17
|
+
rescue LoadError
|
18
|
+
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
19
|
+
end
|
20
|
+
|
21
|
+
require 'spec/rake/spectask'
|
22
|
+
Spec::Rake::SpecTask.new(:spec) do |spec|
|
23
|
+
spec.libs << 'lib' << 'spec'
|
24
|
+
spec.spec_files = FileList['spec/**/*_spec.rb']
|
25
|
+
end
|
26
|
+
|
27
|
+
Spec::Rake::SpecTask.new(:rcov) do |spec|
|
28
|
+
spec.libs << 'lib' << 'spec'
|
29
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
30
|
+
spec.rcov = true
|
31
|
+
end
|
32
|
+
|
33
|
+
task :spec => :check_dependencies
|
34
|
+
|
35
|
+
task :default => :spec
|
36
|
+
|
37
|
+
require 'rake/rdoctask'
|
38
|
+
Rake::RDocTask.new do |rdoc|
|
39
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
40
|
+
|
41
|
+
rdoc.rdoc_dir = 'rdoc'
|
42
|
+
rdoc.title = "watercooling #{version}"
|
43
|
+
rdoc.rdoc_files.include('README*')
|
44
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
45
|
+
end
|
46
|
+
|
47
|
+
task :console do
|
48
|
+
puts "Firing up the console.."
|
49
|
+
system("irb -r #{Dir.pwd}/lib/watercooling.rb")
|
50
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.2
|
data/bin/watercooling
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# Watercoolr daemon command line interface script.
|
4
|
+
# Run <tt>watercooling -h</tt> to get more usage.
|
5
|
+
require File.dirname(__FILE__) + '/../lib/watercooling'
|
6
|
+
require 'thin'
|
7
|
+
|
8
|
+
rackup_file = "#{File.dirname(__FILE__)}/../lib/watercooling/config.ru"
|
9
|
+
|
10
|
+
argv = ARGV
|
11
|
+
argv << ["-R", rackup_file] unless ARGV.include?("-R")
|
12
|
+
argv << ["-p", "2003"] unless ARGV.include?("-p")
|
13
|
+
argv << ["-e", "production"] unless ARGV.include?("-e")
|
14
|
+
Thin::Runner.new(argv.flatten).run!
|
@@ -0,0 +1,15 @@
|
|
1
|
+
class Webhook
|
2
|
+
include DataMapper::Resource
|
3
|
+
|
4
|
+
property :id, Serial
|
5
|
+
property :queued, Boolean, :default => false
|
6
|
+
property :url, String
|
7
|
+
property :sent, Boolean, :default => false
|
8
|
+
property :sent_at, DateTime
|
9
|
+
property :send_error, String
|
10
|
+
property :send_num_tries, Integer
|
11
|
+
property :created_at, DateTime
|
12
|
+
property :updated_at, DateTime
|
13
|
+
|
14
|
+
has n, :params
|
15
|
+
end
|
Binary file
|
@@ -0,0 +1 @@
|
|
1
|
+
body { font: 12px Helvetica, sans-serif; color: #333;}
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
|
3
|
+
class WebhookQueue
|
4
|
+
include Singleton
|
5
|
+
|
6
|
+
@@retries = 3
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
EM.add_periodic_timer(1) {
|
10
|
+
send_current_webhooks
|
11
|
+
}
|
12
|
+
end
|
13
|
+
|
14
|
+
# Loop through all pending messages and send them.
|
15
|
+
# Allow a max retry of @@retries
|
16
|
+
def send_current_webhooks
|
17
|
+
queued_webhooks = Webhook.all(:queued => true, :sent => false)
|
18
|
+
queued_webhooks.each do |webhook|
|
19
|
+
trys = @@retries
|
20
|
+
while trys > 0
|
21
|
+
num_tries = 4 - trys
|
22
|
+
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))
|
27
|
+
webhook.update!(:sent => true, :sent_at => Time.now, :queued => false, :send_num_tries => num_tries)
|
28
|
+
break
|
29
|
+
rescue => e
|
30
|
+
trys -= 1
|
31
|
+
sleep 1
|
32
|
+
if trys == 0
|
33
|
+
# Failed to send. Take it off the queue and log error.
|
34
|
+
webhook.update!(:sent => false, :queued => false, :send_error => e, :send_num_tries => num_tries)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
data/lib/watercooling.rb
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'sinatra'
|
3
|
+
require 'dm-core'
|
4
|
+
require 'dm-migrations'
|
5
|
+
require 'dm-timestamps'
|
6
|
+
require 'dm-validations'
|
7
|
+
require 'json'
|
8
|
+
require 'erb'
|
9
|
+
require 'httpclient'
|
10
|
+
require 'zlib'
|
11
|
+
require 'eventmachine'
|
12
|
+
require 'logger'
|
13
|
+
|
14
|
+
# Watercooling code
|
15
|
+
require File.dirname(__FILE__) + '/watercooling'
|
16
|
+
require File.dirname(__FILE__) + '/watercooling/webhook_queue'
|
17
|
+
require File.dirname(__FILE__) + '/watercooling/models/webhook'
|
18
|
+
require File.dirname(__FILE__) + '/watercooling/models/param'
|
19
|
+
|
20
|
+
class Watercooling < Sinatra::Base
|
21
|
+
# Database config
|
22
|
+
configure :production, :development do
|
23
|
+
db = "sqlite3:///#{Dir.pwd}/lib/watercooling.sqlite3"
|
24
|
+
DataMapper.setup(:default, db)
|
25
|
+
end
|
26
|
+
|
27
|
+
configure :test do
|
28
|
+
db = "sqlite3::memory:"
|
29
|
+
DataMapper.setup(:default, db)
|
30
|
+
end
|
31
|
+
|
32
|
+
configure :production, :test, :development do
|
33
|
+
Webhook.auto_migrate! unless Webhook.storage_exists?
|
34
|
+
Param.auto_migrate! unless Param.storage_exists?
|
35
|
+
end
|
36
|
+
|
37
|
+
configure :production, :development do
|
38
|
+
DataMapper.auto_upgrade!
|
39
|
+
end
|
40
|
+
|
41
|
+
configure do
|
42
|
+
# Fire up the message queue
|
43
|
+
Thread.new do
|
44
|
+
until EM.reactor_running?
|
45
|
+
sleep 1
|
46
|
+
end
|
47
|
+
wq = WebhookQueue.instance
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# Set the views to the proper path inside the gem
|
52
|
+
set :views, File.dirname(__FILE__) + '/watercooling/views'
|
53
|
+
set :public, File.dirname(__FILE__) + '/watercooling/public'
|
54
|
+
set :bind, 'localhost'
|
55
|
+
|
56
|
+
get '/' do
|
57
|
+
erb :index
|
58
|
+
end
|
59
|
+
|
60
|
+
# Accept a webhook with a special field of _url to be queued to be sent out.
|
61
|
+
post '/dispatch' do
|
62
|
+
content_type :json
|
63
|
+
response = false
|
64
|
+
|
65
|
+
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
|
71
|
+
end
|
72
|
+
else
|
73
|
+
fail_reason = "Couldn't queue webhook."
|
74
|
+
end
|
75
|
+
else
|
76
|
+
fail_reason = '_url post param required.'
|
77
|
+
end
|
78
|
+
|
79
|
+
if response
|
80
|
+
{ :status => 'OK' }.to_json
|
81
|
+
else
|
82
|
+
{ :status => 'FAIL', :reason => fail_reason }.to_json
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
data/spec/spec.opts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
require 'rest-client'
|
3
|
+
|
4
|
+
URL = 'http://localhost:2003'
|
5
|
+
|
6
|
+
# Make sure to set the above URL to the correct
|
7
|
+
# address of your app before running the tests.
|
8
|
+
describe "watercooling" do
|
9
|
+
it "should add webhook" do
|
10
|
+
response = RestClient.post(URL + '/dispatch', :_url => 'http://google.com', :test_param => 'test')
|
11
|
+
JSON.parse(response)['status'].should == 'OK'
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should fail if _url is missing" do
|
15
|
+
response = RestClient.post(URL + '/dispatch', :url => 'http://google.com', :test_param => 'test')
|
16
|
+
JSON.parse(response)['status'].should == 'FAIL'
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should add webhook to queue" do
|
20
|
+
_url = 'http://asdf.com'
|
21
|
+
|
22
|
+
RestClient.post(URL + '/dispatch', :_url => _url, :test_param => 'test')
|
23
|
+
webhook = Webhook.first(:url => _url)
|
24
|
+
webhook.id.should > 0
|
25
|
+
|
26
|
+
test_param = webhook.params.first(:name => 'test_param', :value => 'test')
|
27
|
+
test_param.value.should == 'test'
|
28
|
+
test_param.name.should == 'test_param'
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{watercooling}
|
8
|
+
s.version = "0.0.2"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["@_ty"]
|
12
|
+
s.date = %q{2010-09-01}
|
13
|
+
s.default_executable = %q{watercooling}
|
14
|
+
s.description = %q{Asynchronous webhook queueing with skinny daemon support.}
|
15
|
+
s.email = %q{linuxsable@gmail.com}
|
16
|
+
s.executables = ["watercooling"]
|
17
|
+
s.extra_rdoc_files = [
|
18
|
+
"LICENSE",
|
19
|
+
"README.md"
|
20
|
+
]
|
21
|
+
s.files = [
|
22
|
+
".document",
|
23
|
+
".gitignore",
|
24
|
+
"LICENSE",
|
25
|
+
"README.md",
|
26
|
+
"Rakefile",
|
27
|
+
"VERSION",
|
28
|
+
"bin/watercooling",
|
29
|
+
"lib/watercooling.rb",
|
30
|
+
"lib/watercooling/config.ru",
|
31
|
+
"lib/watercooling/models/param.rb",
|
32
|
+
"lib/watercooling/models/webhook.rb",
|
33
|
+
"lib/watercooling/postbin.rb",
|
34
|
+
"lib/watercooling/public/.sass-cache/0c0382c87ab4b8085b4c92f483d8ad06e341672b/style.scssc",
|
35
|
+
"lib/watercooling/public/style.css",
|
36
|
+
"lib/watercooling/views/index.erb",
|
37
|
+
"lib/watercooling/webhook_queue.rb",
|
38
|
+
"spec/spec.opts",
|
39
|
+
"spec/spec_helper.rb",
|
40
|
+
"spec/watercooling_spec.rb",
|
41
|
+
"watercooling.gemspec"
|
42
|
+
]
|
43
|
+
s.homepage = %q{http://github.com/linuxsable/watercooling}
|
44
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
45
|
+
s.require_paths = ["lib"]
|
46
|
+
s.rubygems_version = %q{1.3.7}
|
47
|
+
s.summary = %q{Asynchrnous webhook queueing.}
|
48
|
+
s.test_files = [
|
49
|
+
"spec/spec_helper.rb",
|
50
|
+
"spec/watercooling_spec.rb"
|
51
|
+
]
|
52
|
+
|
53
|
+
if s.respond_to? :specification_version then
|
54
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
55
|
+
s.specification_version = 3
|
56
|
+
|
57
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
58
|
+
s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
|
59
|
+
else
|
60
|
+
s.add_dependency(%q<rspec>, [">= 1.2.9"])
|
61
|
+
end
|
62
|
+
else
|
63
|
+
s.add_dependency(%q<rspec>, [">= 1.2.9"])
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
metadata
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: watercooling
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 0
|
8
|
+
- 2
|
9
|
+
version: 0.0.2
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- "@_ty"
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2010-09-01 00:00:00 -07:00
|
18
|
+
default_executable: watercooling
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: rspec
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
segments:
|
29
|
+
- 1
|
30
|
+
- 2
|
31
|
+
- 9
|
32
|
+
version: 1.2.9
|
33
|
+
type: :development
|
34
|
+
version_requirements: *id001
|
35
|
+
description: Asynchronous webhook queueing with skinny daemon support.
|
36
|
+
email: linuxsable@gmail.com
|
37
|
+
executables:
|
38
|
+
- watercooling
|
39
|
+
extensions: []
|
40
|
+
|
41
|
+
extra_rdoc_files:
|
42
|
+
- LICENSE
|
43
|
+
- README.md
|
44
|
+
files:
|
45
|
+
- .document
|
46
|
+
- .gitignore
|
47
|
+
- LICENSE
|
48
|
+
- README.md
|
49
|
+
- Rakefile
|
50
|
+
- VERSION
|
51
|
+
- bin/watercooling
|
52
|
+
- lib/watercooling.rb
|
53
|
+
- lib/watercooling/config.ru
|
54
|
+
- lib/watercooling/models/param.rb
|
55
|
+
- lib/watercooling/models/webhook.rb
|
56
|
+
- lib/watercooling/postbin.rb
|
57
|
+
- lib/watercooling/public/.sass-cache/0c0382c87ab4b8085b4c92f483d8ad06e341672b/style.scssc
|
58
|
+
- lib/watercooling/public/style.css
|
59
|
+
- lib/watercooling/views/index.erb
|
60
|
+
- lib/watercooling/webhook_queue.rb
|
61
|
+
- spec/spec.opts
|
62
|
+
- spec/spec_helper.rb
|
63
|
+
- spec/watercooling_spec.rb
|
64
|
+
- watercooling.gemspec
|
65
|
+
has_rdoc: true
|
66
|
+
homepage: http://github.com/linuxsable/watercooling
|
67
|
+
licenses: []
|
68
|
+
|
69
|
+
post_install_message:
|
70
|
+
rdoc_options:
|
71
|
+
- --charset=UTF-8
|
72
|
+
require_paths:
|
73
|
+
- lib
|
74
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
75
|
+
none: false
|
76
|
+
requirements:
|
77
|
+
- - ">="
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
segments:
|
80
|
+
- 0
|
81
|
+
version: "0"
|
82
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
83
|
+
none: false
|
84
|
+
requirements:
|
85
|
+
- - ">="
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
segments:
|
88
|
+
- 0
|
89
|
+
version: "0"
|
90
|
+
requirements: []
|
91
|
+
|
92
|
+
rubyforge_project:
|
93
|
+
rubygems_version: 1.3.7
|
94
|
+
signing_key:
|
95
|
+
specification_version: 3
|
96
|
+
summary: Asynchrnous webhook queueing.
|
97
|
+
test_files:
|
98
|
+
- spec/spec_helper.rb
|
99
|
+
- spec/watercooling_spec.rb
|