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 ADDED
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
data/.gitignore ADDED
@@ -0,0 +1,21 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.swp
15
+
16
+ ## PROJECT::GENERAL
17
+ coverage
18
+ rdoc
19
+ pkg
20
+
21
+ ## PROJECT::SPECIFIC
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,2 @@
1
+ require File.dirname(__FILE__) + '/../watercooling'
2
+ Watercooling.run! :port => 2003
@@ -0,0 +1,11 @@
1
+ class Param
2
+ include DataMapper::Resource
3
+
4
+ property :id, Serial
5
+ property :name, String
6
+ property :value, Text, :lazy => false
7
+ property :created_at, DateTime
8
+ property :updated_at, DateTime
9
+
10
+ belongs_to :webhook
11
+ end
@@ -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
@@ -0,0 +1,8 @@
1
+ require 'rubygems'
2
+ require 'rest-client'
3
+
4
+ url = "http://localhost:2003"
5
+
6
+ puts "sending webhook"
7
+ resp = RestClient.post(url + '/dispatch', :_url => ARGV[0], :test_param1 => 'test1', :test_param2 => 'test2')
8
+ puts resp
@@ -0,0 +1 @@
1
+ body { font: 12px Helvetica, sans-serif; color: #333;}
@@ -0,0 +1,10 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
2
+ <html>
3
+ <head>
4
+ <title>Watercooling</title>
5
+ <link href="style.css" rel="stylesheet" type="text/css">
6
+ </head>
7
+ <body>
8
+ <h2>Watercooling</h2>
9
+ </body>
10
+ </html>
@@ -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
@@ -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
@@ -0,0 +1,9 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
+ require 'watercooling'
4
+ require 'spec'
5
+ require 'spec/autorun'
6
+
7
+ Spec::Runner.configure do |config|
8
+
9
+ end
@@ -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