apphunkd 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (204) hide show
  1. data/.document +5 -0
  2. data/.gitignore +22 -0
  3. data/LICENSE +20 -0
  4. data/README.rdoc +18 -0
  5. data/Rakefile +78 -0
  6. data/TODO +1 -0
  7. data/VERSION +1 -0
  8. data/apphunkd.gemspec +258 -0
  9. data/bin/apphunkd +4 -0
  10. data/config/arguments.rb +12 -0
  11. data/config/boot.rb +68 -0
  12. data/config/environment.rb +23 -0
  13. data/config/environments/development.rb +2 -0
  14. data/config/environments/production.rb +2 -0
  15. data/config/environments/test.rb +2 -0
  16. data/config/post-daemonize/readme +5 -0
  17. data/config/pre-daemonize/readme +12 -0
  18. data/config/pre-daemonize/requires.rb +2 -0
  19. data/lib/apphunkd.rb +25 -0
  20. data/lib/apphunkd/api.rb +5 -0
  21. data/lib/apphunkd/api/service.rb +27 -0
  22. data/lib/apphunkd/queue.rb +96 -0
  23. data/lib/apphunkd/remote.rb +29 -0
  24. data/lib/apphunkd/remote/result.rb +15 -0
  25. data/libexec/apphunkd-daemon.rb +13 -0
  26. data/script/console +3 -0
  27. data/script/destroy +14 -0
  28. data/script/generate +14 -0
  29. data/spec/lib/apphunkd/api/service_spec.rb +47 -0
  30. data/spec/lib/apphunkd/queue_spec.rb +129 -0
  31. data/spec/lib/apphunkd/remote_spec.rb +61 -0
  32. data/spec/lib/apphunkd_spec.rb +50 -0
  33. data/spec/spec.opts +1 -0
  34. data/spec/spec_helper.rb +13 -0
  35. data/support/apphunkd.initd +47 -0
  36. data/support/apphunkd.monitrc +3 -0
  37. data/tasks/rspec.rake +21 -0
  38. data/vendor/daemon-kit/Configuration.txt +102 -0
  39. data/vendor/daemon-kit/Deployment.txt +113 -0
  40. data/vendor/daemon-kit/History.txt +97 -0
  41. data/vendor/daemon-kit/Logging.txt +92 -0
  42. data/vendor/daemon-kit/Manifest.txt +166 -0
  43. data/vendor/daemon-kit/PostInstall.txt +6 -0
  44. data/vendor/daemon-kit/README.rdoc +130 -0
  45. data/vendor/daemon-kit/Rakefile +37 -0
  46. data/vendor/daemon-kit/RuoteParticipants.txt +113 -0
  47. data/vendor/daemon-kit/TODO.txt +37 -0
  48. data/vendor/daemon-kit/app_generators/daemon_kit/USAGE +7 -0
  49. data/vendor/daemon-kit/app_generators/daemon_kit/daemon_kit_generator.rb +161 -0
  50. data/vendor/daemon-kit/app_generators/daemon_kit/templates/README +48 -0
  51. data/vendor/daemon-kit/app_generators/daemon_kit/templates/Rakefile +6 -0
  52. data/vendor/daemon-kit/app_generators/daemon_kit/templates/bin/daemon.erb +7 -0
  53. data/vendor/daemon-kit/app_generators/daemon_kit/templates/config/arguments.rb +12 -0
  54. data/vendor/daemon-kit/app_generators/daemon_kit/templates/config/boot.rb +68 -0
  55. data/vendor/daemon-kit/app_generators/daemon_kit/templates/config/environment.rb +23 -0
  56. data/vendor/daemon-kit/app_generators/daemon_kit/templates/config/environments/development.rb +2 -0
  57. data/vendor/daemon-kit/app_generators/daemon_kit/templates/config/environments/production.rb +2 -0
  58. data/vendor/daemon-kit/app_generators/daemon_kit/templates/config/environments/test.rb +2 -0
  59. data/vendor/daemon-kit/app_generators/daemon_kit/templates/config/post-daemonize/readme +5 -0
  60. data/vendor/daemon-kit/app_generators/daemon_kit/templates/config/pre-daemonize/readme +12 -0
  61. data/vendor/daemon-kit/app_generators/daemon_kit/templates/lib/daemon.rb +2 -0
  62. data/vendor/daemon-kit/app_generators/daemon_kit/templates/libexec/daemon.erb +18 -0
  63. data/vendor/daemon-kit/app_generators/daemon_kit/templates/script/console +3 -0
  64. data/vendor/daemon-kit/app_generators/daemon_kit/templates/script/destroy +14 -0
  65. data/vendor/daemon-kit/app_generators/daemon_kit/templates/script/generate +14 -0
  66. data/vendor/daemon-kit/bin/daemon_kit +18 -0
  67. data/vendor/daemon-kit/daemon_generators/amqp/USAGE +5 -0
  68. data/vendor/daemon-kit/daemon_generators/amqp/amqp_generator.rb +65 -0
  69. data/vendor/daemon-kit/daemon_generators/amqp/templates/config/amqp.yml +28 -0
  70. data/vendor/daemon-kit/daemon_generators/amqp/templates/config/initializers/amqp.rb +7 -0
  71. data/vendor/daemon-kit/daemon_generators/amqp/templates/libexec/daemon.rb +37 -0
  72. data/vendor/daemon-kit/daemon_generators/cron/USAGE +5 -0
  73. data/vendor/daemon-kit/daemon_generators/cron/cron_generator.rb +64 -0
  74. data/vendor/daemon-kit/daemon_generators/cron/templates/config/initializers/cron.rb +11 -0
  75. data/vendor/daemon-kit/daemon_generators/cron/templates/libexec/daemon.rb +43 -0
  76. data/vendor/daemon-kit/daemon_generators/cucumber/USAGE +11 -0
  77. data/vendor/daemon-kit/daemon_generators/cucumber/cucumber_generator.rb +38 -0
  78. data/vendor/daemon-kit/daemon_generators/cucumber/templates/cucumber +8 -0
  79. data/vendor/daemon-kit/daemon_generators/cucumber/templates/cucumber.rake +13 -0
  80. data/vendor/daemon-kit/daemon_generators/cucumber/templates/cucumber_environment.rb +2 -0
  81. data/vendor/daemon-kit/daemon_generators/cucumber/templates/env.rb +7 -0
  82. data/vendor/daemon-kit/daemon_generators/deploy_capistrano/deploy_capistrano_generator.rb +35 -0
  83. data/vendor/daemon-kit/daemon_generators/deploy_capistrano/templates/Capfile +10 -0
  84. data/vendor/daemon-kit/daemon_generators/deploy_capistrano/templates/USAGE +10 -0
  85. data/vendor/daemon-kit/daemon_generators/deploy_capistrano/templates/config/deploy.rb +53 -0
  86. data/vendor/daemon-kit/daemon_generators/deploy_capistrano/templates/config/deploy/production.rb +6 -0
  87. data/vendor/daemon-kit/daemon_generators/deploy_capistrano/templates/config/deploy/staging.rb +6 -0
  88. data/vendor/daemon-kit/daemon_generators/deploy_capistrano/templates/config/environments/staging.rb +0 -0
  89. data/vendor/daemon-kit/daemon_generators/jabber/USAGE +5 -0
  90. data/vendor/daemon-kit/daemon_generators/jabber/jabber_generator.rb +65 -0
  91. data/vendor/daemon-kit/daemon_generators/jabber/templates/config/initializers/jabber.rb +7 -0
  92. data/vendor/daemon-kit/daemon_generators/jabber/templates/config/jabber.yml +26 -0
  93. data/vendor/daemon-kit/daemon_generators/jabber/templates/libexec/daemon.rb +27 -0
  94. data/vendor/daemon-kit/daemon_generators/nanite_agent/USAGE +5 -0
  95. data/vendor/daemon-kit/daemon_generators/nanite_agent/nanite_agent_generator.rb +68 -0
  96. data/vendor/daemon-kit/daemon_generators/nanite_agent/templates/config/initializers/nanite_agent.rb +6 -0
  97. data/vendor/daemon-kit/daemon_generators/nanite_agent/templates/config/nanite.yml +35 -0
  98. data/vendor/daemon-kit/daemon_generators/nanite_agent/templates/lib/actors/sample.rb +11 -0
  99. data/vendor/daemon-kit/daemon_generators/nanite_agent/templates/libexec/daemon.rb +31 -0
  100. data/vendor/daemon-kit/daemon_generators/rspec/USAGE +5 -0
  101. data/vendor/daemon-kit/daemon_generators/rspec/rspec_generator.rb +55 -0
  102. data/vendor/daemon-kit/daemon_generators/rspec/templates/spec.rb +11 -0
  103. data/vendor/daemon-kit/daemon_generators/rspec/templates/spec/spec.opts +1 -0
  104. data/vendor/daemon-kit/daemon_generators/rspec/templates/spec/spec_helper.rb +21 -0
  105. data/vendor/daemon-kit/daemon_generators/rspec/templates/tasks/rspec.rake +21 -0
  106. data/vendor/daemon-kit/daemon_generators/ruote/USAGE +5 -0
  107. data/vendor/daemon-kit/daemon_generators/ruote/ruote_generator.rb +67 -0
  108. data/vendor/daemon-kit/daemon_generators/ruote/templates/config/amqp.yml +30 -0
  109. data/vendor/daemon-kit/daemon_generators/ruote/templates/config/initializers/ruote.rb +13 -0
  110. data/vendor/daemon-kit/daemon_generators/ruote/templates/config/ruote.yml +23 -0
  111. data/vendor/daemon-kit/daemon_generators/ruote/templates/lib/daemon.rb +4 -0
  112. data/vendor/daemon-kit/daemon_generators/ruote/templates/lib/sample.rb +26 -0
  113. data/vendor/daemon-kit/daemon_generators/ruote/templates/libexec/daemon.rb +33 -0
  114. data/vendor/daemon-kit/lib/daemon_kit.rb +54 -0
  115. data/vendor/daemon-kit/lib/daemon_kit/abstract_logger.rb +235 -0
  116. data/vendor/daemon-kit/lib/daemon_kit/amqp.rb +38 -0
  117. data/vendor/daemon-kit/lib/daemon_kit/application.rb +187 -0
  118. data/vendor/daemon-kit/lib/daemon_kit/arguments.rb +165 -0
  119. data/vendor/daemon-kit/lib/daemon_kit/commands/console.rb +38 -0
  120. data/vendor/daemon-kit/lib/daemon_kit/config.rb +108 -0
  121. data/vendor/daemon-kit/lib/daemon_kit/console_daemon.rb +2 -0
  122. data/vendor/daemon-kit/lib/daemon_kit/core_ext.rb +1 -0
  123. data/vendor/daemon-kit/lib/daemon_kit/core_ext/configurable.rb +96 -0
  124. data/vendor/daemon-kit/lib/daemon_kit/core_ext/string.rb +22 -0
  125. data/vendor/daemon-kit/lib/daemon_kit/cron.rb +48 -0
  126. data/vendor/daemon-kit/lib/daemon_kit/cucumber/world.rb +38 -0
  127. data/vendor/daemon-kit/lib/daemon_kit/deployment/capistrano.rb +482 -0
  128. data/vendor/daemon-kit/lib/daemon_kit/em.rb +43 -0
  129. data/vendor/daemon-kit/lib/daemon_kit/error_handlers/base.rb +32 -0
  130. data/vendor/daemon-kit/lib/daemon_kit/error_handlers/hoptoad.rb +61 -0
  131. data/vendor/daemon-kit/lib/daemon_kit/error_handlers/mail.rb +85 -0
  132. data/vendor/daemon-kit/lib/daemon_kit/exceptions.rb +8 -0
  133. data/vendor/daemon-kit/lib/daemon_kit/initializer.rb +438 -0
  134. data/vendor/daemon-kit/lib/daemon_kit/jabber.rb +170 -0
  135. data/vendor/daemon-kit/lib/daemon_kit/nanite.rb +7 -0
  136. data/vendor/daemon-kit/lib/daemon_kit/nanite/agent.rb +56 -0
  137. data/vendor/daemon-kit/lib/daemon_kit/pid_file.rb +61 -0
  138. data/vendor/daemon-kit/lib/daemon_kit/ruote_participants.rb +119 -0
  139. data/vendor/daemon-kit/lib/daemon_kit/ruote_pseudo_participant.rb +68 -0
  140. data/vendor/daemon-kit/lib/daemon_kit/ruote_workitem.rb +169 -0
  141. data/vendor/daemon-kit/lib/daemon_kit/safety.rb +85 -0
  142. data/vendor/daemon-kit/lib/daemon_kit/tasks.rb +2 -0
  143. data/vendor/daemon-kit/lib/daemon_kit/tasks/environment.rake +10 -0
  144. data/vendor/daemon-kit/lib/daemon_kit/tasks/framework.rake +120 -0
  145. data/vendor/daemon-kit/lib/daemon_kit/tasks/god.rake +62 -0
  146. data/vendor/daemon-kit/lib/daemon_kit/tasks/log.rake +8 -0
  147. data/vendor/daemon-kit/lib/daemon_kit/tasks/monit.rake +29 -0
  148. data/vendor/daemon-kit/script/console +10 -0
  149. data/vendor/daemon-kit/script/destroy +14 -0
  150. data/vendor/daemon-kit/script/generate +14 -0
  151. data/vendor/daemon-kit/script/txt2html +71 -0
  152. data/vendor/daemon-kit/spec/abstract_logger_spec.rb +126 -0
  153. data/vendor/daemon-kit/spec/argument_spec.rb +70 -0
  154. data/vendor/daemon-kit/spec/config_spec.rb +79 -0
  155. data/vendor/daemon-kit/spec/configurable_spec.rb +56 -0
  156. data/vendor/daemon-kit/spec/daemon_kit_spec.rb +7 -0
  157. data/vendor/daemon-kit/spec/error_handlers_spec.rb +23 -0
  158. data/vendor/daemon-kit/spec/fixtures/env.yml +15 -0
  159. data/vendor/daemon-kit/spec/fixtures/noenv.yml +4 -0
  160. data/vendor/daemon-kit/spec/initializer_spec.rb +26 -0
  161. data/vendor/daemon-kit/spec/spec.opts +1 -0
  162. data/vendor/daemon-kit/spec/spec_helper.rb +27 -0
  163. data/vendor/daemon-kit/tasks/rspec.rake +21 -0
  164. data/vendor/daemon-kit/templates/god/god.erb +69 -0
  165. data/vendor/daemon-kit/templates/monit/monit.erb +14 -0
  166. data/vendor/daemon-kit/test/test_amqp_generator.rb +48 -0
  167. data/vendor/daemon-kit/test/test_cron_generator.rb +45 -0
  168. data/vendor/daemon-kit/test/test_daemon-kit_generator.rb +84 -0
  169. data/vendor/daemon-kit/test/test_daemon_kit_config.rb +28 -0
  170. data/vendor/daemon-kit/test/test_deploy_capistrano_generator.rb +48 -0
  171. data/vendor/daemon-kit/test/test_generator_helper.rb +29 -0
  172. data/vendor/daemon-kit/test/test_helper.rb +7 -0
  173. data/vendor/daemon-kit/test/test_jabber_generator.rb +49 -0
  174. data/vendor/daemon-kit/test/test_nanite_agent_generator.rb +49 -0
  175. data/vendor/daemon-kit/test/test_ruote_generator.rb +45 -0
  176. data/vendor/daemon-kit/vendor/tmail-1.2.3/tmail.rb +5 -0
  177. data/vendor/daemon-kit/vendor/tmail-1.2.3/tmail/address.rb +426 -0
  178. data/vendor/daemon-kit/vendor/tmail-1.2.3/tmail/attachments.rb +46 -0
  179. data/vendor/daemon-kit/vendor/tmail-1.2.3/tmail/base64.rb +46 -0
  180. data/vendor/daemon-kit/vendor/tmail-1.2.3/tmail/compat.rb +41 -0
  181. data/vendor/daemon-kit/vendor/tmail-1.2.3/tmail/config.rb +67 -0
  182. data/vendor/daemon-kit/vendor/tmail-1.2.3/tmail/core_extensions.rb +63 -0
  183. data/vendor/daemon-kit/vendor/tmail-1.2.3/tmail/encode.rb +581 -0
  184. data/vendor/daemon-kit/vendor/tmail-1.2.3/tmail/header.rb +960 -0
  185. data/vendor/daemon-kit/vendor/tmail-1.2.3/tmail/index.rb +9 -0
  186. data/vendor/daemon-kit/vendor/tmail-1.2.3/tmail/interface.rb +1130 -0
  187. data/vendor/daemon-kit/vendor/tmail-1.2.3/tmail/loader.rb +3 -0
  188. data/vendor/daemon-kit/vendor/tmail-1.2.3/tmail/mail.rb +578 -0
  189. data/vendor/daemon-kit/vendor/tmail-1.2.3/tmail/mailbox.rb +495 -0
  190. data/vendor/daemon-kit/vendor/tmail-1.2.3/tmail/main.rb +6 -0
  191. data/vendor/daemon-kit/vendor/tmail-1.2.3/tmail/mbox.rb +3 -0
  192. data/vendor/daemon-kit/vendor/tmail-1.2.3/tmail/net.rb +248 -0
  193. data/vendor/daemon-kit/vendor/tmail-1.2.3/tmail/obsolete.rb +132 -0
  194. data/vendor/daemon-kit/vendor/tmail-1.2.3/tmail/parser.rb +1476 -0
  195. data/vendor/daemon-kit/vendor/tmail-1.2.3/tmail/port.rb +379 -0
  196. data/vendor/daemon-kit/vendor/tmail-1.2.3/tmail/quoting.rb +118 -0
  197. data/vendor/daemon-kit/vendor/tmail-1.2.3/tmail/require_arch.rb +58 -0
  198. data/vendor/daemon-kit/vendor/tmail-1.2.3/tmail/scanner.rb +49 -0
  199. data/vendor/daemon-kit/vendor/tmail-1.2.3/tmail/scanner_r.rb +261 -0
  200. data/vendor/daemon-kit/vendor/tmail-1.2.3/tmail/stringio.rb +280 -0
  201. data/vendor/daemon-kit/vendor/tmail-1.2.3/tmail/utils.rb +337 -0
  202. data/vendor/daemon-kit/vendor/tmail-1.2.3/tmail/version.rb +39 -0
  203. data/vendor/daemon-kit/vendor/tmail.rb +13 -0
  204. metadata +281 -0
@@ -0,0 +1,23 @@
1
+ # Be sure to restart your daemon when you modify this file
2
+
3
+ # Uncomment below to force your daemon into production mode
4
+ #ENV['DAEMON_ENV'] ||= 'production'
5
+
6
+ # Boot up
7
+ require File.join(File.dirname(__FILE__), 'boot')
8
+
9
+ DaemonKit::Initializer.run do |config|
10
+
11
+ # The name of the daemon as reported by process monitoring tools
12
+ config.daemon_name = 'apphunkd'
13
+
14
+ # Force the daemon to be killed after X seconds from asking it to
15
+ # config.force_kill_wait = 30
16
+
17
+ # Log backraces when a thread/daemon dies (Recommended)
18
+ # config.backtraces = true
19
+
20
+ # Configure the safety net (see DaemonKit::Safety)
21
+ # config.safety_net.handler = :mail # (or :hoptoad )
22
+ # config.safety_net.mail.host = 'localhost'
23
+ end
@@ -0,0 +1,2 @@
1
+ # This is the same context as the environment.rb file, it is only
2
+ # loaded afterwards and only in the development environment
@@ -0,0 +1,2 @@
1
+ config.pid_file = '/var/run/apphunkd.pid'
2
+ config.log_path = '/var/log/apphunkd.log'
@@ -0,0 +1,2 @@
1
+ # This is the same context as the environment.rb file, it is only
2
+ # loaded afterwards and only in the test environment
@@ -0,0 +1,5 @@
1
+ # You can place files in here to be loaded after the code is daemonized.
2
+ #
3
+ # All the files placed here will just be required into the running
4
+ # process. This is the correct place to open any IO objects, establish
5
+ # database connections, etc.
@@ -0,0 +1,12 @@
1
+ # You can place files in here to be loaded before the code is daemonized.
2
+ #
3
+ # DaemonKit looks for a file named '<config.daemon_name>.rb' and loads
4
+ # that file first, and inside a DaemonKit::Initializer block. The
5
+ # remaning files then simply required into the running process.
6
+ #
7
+ # These files are mostly useful for operations that should fail blatantly
8
+ # before daemonizing, like loading gems.
9
+ #
10
+ # Be careful not to open any form of IO in here and expecting it to be
11
+ # open inside the running daemon since all IO instances are closed when
12
+ # daemonizing (including STDIN, STDOUT & STDERR).
@@ -0,0 +1,2 @@
1
+ require 'rubygems'
2
+ require 'sinatra/base'
data/lib/apphunkd.rb ADDED
@@ -0,0 +1,25 @@
1
+ module Apphunkd
2
+
3
+ autoload :API, 'apphunkd/api'
4
+ autoload :Queue, 'apphunkd/queue'
5
+ autoload :Remote, 'apphunkd/remote'
6
+
7
+ class << self
8
+
9
+ attr_accessor :queue
10
+
11
+ def run!
12
+ initialize_queue
13
+ initialize_api_service
14
+ end
15
+
16
+ def initialize_queue
17
+ self.queue = Queue.new
18
+ self.queue.activate!
19
+ end
20
+
21
+ def initialize_api_service
22
+ API::Service.run! :port => '8212', :host => '127.0.0.1'
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,5 @@
1
+ module Apphunkd
2
+ module API
3
+ autoload :Service, 'apphunkd/api/service'
4
+ end
5
+ end
@@ -0,0 +1,27 @@
1
+ module Apphunkd
2
+ module API
3
+
4
+ class Service < Sinatra::Base
5
+ set :sessions, false
6
+ set :environment, DaemonKit.env.to_sym
7
+
8
+ post '/api/messages' do
9
+ if Apphunkd.queue.store(params)
10
+ status 201
11
+ else
12
+ status 400
13
+ end
14
+ end
15
+
16
+ not_found do
17
+ "Not found. The requested resources doesn't exist."
18
+ end
19
+
20
+ error do
21
+ 'Hoppla. Some internal stuff has crashed.'
22
+ end
23
+ end
24
+
25
+ end
26
+ end
27
+
@@ -0,0 +1,96 @@
1
+ module Apphunkd
2
+ class Queue
3
+
4
+ attr_accessor :items
5
+ attr_accessor :mutex
6
+ attr_accessor :worker
7
+
8
+ def initialize
9
+ @items = []
10
+ @mutex = Mutex.new
11
+ end
12
+
13
+ def activate!
14
+ @worker = initialize_worker
15
+ end
16
+
17
+ def store(message = {})
18
+ return false if message[:body].blank? || message[:token].blank?
19
+ message[:stored_at] = Time.now
20
+
21
+ @mutex.synchronize do
22
+ @items = @items[-9999..-1] if @items.size >= 9999
23
+ @items << message
24
+ end
25
+
26
+ @worker.wakeup
27
+ return true
28
+ end
29
+
30
+ def initialize_worker
31
+ Thread.new do
32
+ begin
33
+ loop do
34
+ unless @items.empty?
35
+ items = get_items_from_stack
36
+ items.each do |item|
37
+ result = push_item_to_remote_service(item)
38
+ if result.status == :ok
39
+ case result.response.code
40
+ when '201'
41
+ # Everything fine
42
+ when '400', '403'
43
+ log_error "Remote Service refused to store item: #{result.response.code} / #{result.response.body}. Dropped."
44
+ else
45
+ put_item_to_stack(item)
46
+ log_error "Remote Service went crazy. Put item back in queue: #{result.response.code} / #{result.response.body}"
47
+ end
48
+ else
49
+ put_item_to_stack(item)
50
+ log_error "Could not push to Remote Service: Connection Error. Put item back in queue."
51
+ end
52
+ end
53
+ end
54
+ sleep
55
+ end
56
+ rescue => e
57
+ log_error "Error: #{e}"
58
+ end
59
+ end
60
+ end
61
+
62
+
63
+ private
64
+
65
+ def get_items_from_stack
66
+ copied_items = []
67
+ @mutex.synchronize do
68
+ copied_items = @items.dup
69
+ @items.clear
70
+ end
71
+ return copied_items
72
+ end
73
+
74
+ def put_item_to_stack(item)
75
+ @mutex.synchronize { @items << item }
76
+ end
77
+
78
+ def push_item_to_remote_service(item)
79
+ url = generate_api_messages_url(item.delete('token'))
80
+ result = Apphunkd::Remote.post(url, item, 300)
81
+ end
82
+
83
+ def generate_api_messages_url(token)
84
+ path = "api/v1/#{token}/messages"
85
+ if DaemonKit.env.to_s == 'production'
86
+ "http://apphunk.com/#{path}"
87
+ else
88
+ "http://apphunk.local/#{path}"
89
+ end
90
+ end
91
+
92
+ def log_error(message)
93
+ DaemonKit.logger.info message
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,29 @@
1
+ require 'net/http'
2
+ require 'timeout'
3
+ require 'uri'
4
+
5
+ module Apphunkd
6
+ module Remote
7
+
8
+ autoload :Result, 'apphunkd/remote/result'
9
+
10
+ class << self
11
+
12
+ def post(url, payload = {}, post_timeout = 30)
13
+ begin
14
+ Timeout.timeout(post_timeout) do
15
+ uri = URI.parse(url)
16
+ result = Remote::Result.new(:response => Net::HTTP.post_form(uri, payload))
17
+ result.status = :ok
18
+ return result
19
+ end
20
+ rescue SocketError
21
+ Remote::Result.new(:status => :connection_error)
22
+ rescue Timeout::Error
23
+ Remote::Result.new(:status => :timeout)
24
+ end
25
+ end
26
+
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,15 @@
1
+ module Apphunkd
2
+ module Remote
3
+ class Result
4
+
5
+ attr_accessor :status
6
+ attr_accessor :response
7
+
8
+ def initialize(opts = {})
9
+ self.status = opts.delete(:status)
10
+ self.response = opts.delete(:response)
11
+ end
12
+
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,13 @@
1
+ # Do your post daemonization configuration here
2
+
3
+ # At minimum you need just the first line (without the block), or a lot
4
+ # of strange things might start happening...
5
+ DaemonKit::Application.running! do |config|
6
+ # Trap signals with blocks or procs
7
+ # config.trap( 'INT' ) do
8
+ # # do something clever
9
+ # end
10
+ # config.trap( 'TERM', Proc.new { puts 'Going down' } )
11
+ end
12
+
13
+ Apphunkd.run!
data/script/console ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+ require File.dirname(__FILE__) + '/../config/boot'
3
+ require 'daemon_kit/commands/console'
data/script/destroy ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
3
+
4
+ begin
5
+ require 'rubigen'
6
+ rescue LoadError
7
+ require 'rubygems'
8
+ require 'rubigen'
9
+ end
10
+ require 'rubigen/scripts/destroy'
11
+
12
+ ARGV.shift if ['--help', '-h'].include?(ARGV[0])
13
+ RubiGen::Base.use_component_sources! [:daemon, :test_unit]
14
+ RubiGen::Scripts::Destroy.new.run(ARGV)
data/script/generate ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
3
+
4
+ begin
5
+ require 'rubigen'
6
+ rescue LoadError
7
+ require 'rubygems'
8
+ require 'rubigen'
9
+ end
10
+ require 'rubigen/scripts/generate'
11
+
12
+ ARGV.shift if ['--help', '-h'].include?(ARGV[0])
13
+ RubiGen::Base.use_component_sources! [:daemon]
14
+ RubiGen::Scripts::Generate.new.run(ARGV)
@@ -0,0 +1,47 @@
1
+ require File.dirname(__FILE__) + '/../../../spec_helper.rb'
2
+ require 'rack/test'
3
+
4
+ describe Apphunkd::API::Service do
5
+ include Rack::Test::Methods
6
+
7
+ def app
8
+ Apphunkd::API::Service
9
+ end
10
+
11
+ before(:each) do
12
+ @queue = mock('Queue')
13
+ Apphunkd.queue = @queue
14
+ end
15
+
16
+ it 'should be an instance of Sinatra::Base' do
17
+ Apphunkd::API::Service.new.should be_kind_of(Sinatra::Base)
18
+ end
19
+
20
+ describe 'POST /api/messages' do
21
+ it 'should store a message in the queue' do
22
+ @queue.should_receive(:store).with("params" => 'test')
23
+ post '/api/messages', :params => 'test'
24
+ end
25
+
26
+ it 'should return status 201 on success' do
27
+ @queue.stub!(:store).and_return(true)
28
+ post '/api/messages', :params => 'test'
29
+ last_response.status.should eql(201)
30
+ end
31
+
32
+ it 'should return status 400 on failure' do
33
+ @queue.stub!(:store).and_return(false)
34
+ post '/api/messages'
35
+ last_response.status.should eql(400)
36
+ end
37
+ end
38
+
39
+ context 'error handling' do
40
+ it 'should return status 404 not found' do
41
+ post '/api/not-existing-resource'
42
+ last_response.status.should eql(404)
43
+ last_response.body.should include('Not found')
44
+ end
45
+ end
46
+ end
47
+
@@ -0,0 +1,129 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper.rb'
2
+
3
+ describe Apphunkd::Queue do
4
+ before(:each) do
5
+ @queue = Apphunkd::Queue.new
6
+ @queue.stub!(:initialize_worker).and_return('worker')
7
+ end
8
+
9
+ describe '#initialize' do
10
+ it 'should create a new Mutex' do
11
+ @queue.mutex.should be_kind_of(Mutex)
12
+ end
13
+
14
+ it 'should prepare the items list' do
15
+ @queue.items.should be_kind_of(Array)
16
+ @queue.items.count.should be(0)
17
+ end
18
+
19
+ end
20
+
21
+ describe '#activate!' do
22
+ it 'should initialize the worker' do
23
+ @queue.activate!
24
+ @queue.worker.should eql('worker')
25
+ end
26
+ end
27
+
28
+ describe '#store' do
29
+ before(:each) do
30
+ @queue.worker = mock('Worker instance')
31
+ @queue.worker.stub!(:wakeup)
32
+ end
33
+
34
+ it 'should return false if message or token is missing' do
35
+ @queue.store().should be_false
36
+ @queue.store(:token => 'test').should be_false
37
+ @queue.store(:body => 'test').should be_false
38
+ end
39
+
40
+ it 'should wrap the store stuff into a mutex' do
41
+ @queue.mutex.should_receive(:synchronize)
42
+ store_message
43
+ end
44
+
45
+ it 'should add stored_at to the message object' do
46
+ store_message
47
+ @message[:stored_at].should be_kind_of(Time)
48
+ end
49
+
50
+ it 'should add the message to the end of the items list' do
51
+ store_message
52
+ @queue.items.should include(@message)
53
+ end
54
+
55
+ it 'should remove the oldest messages from the list to ensure that there are at max 10000 messages queued' do
56
+ @queue.items = [1] * 10000
57
+ store_message
58
+ @queue.items.size.should eql(10000)
59
+ end
60
+
61
+ it 'should wakeup the worker after appending a message' do
62
+ @queue.worker.should_receive(:wakeup)
63
+ store_message
64
+ end
65
+
66
+ it 'should return true after successfully storing a message' do
67
+ store_message.should be_true
68
+ end
69
+
70
+ def store_message
71
+ @message = { :body => 'test', :token => 'test' }
72
+ @queue.store(@message)
73
+ end
74
+ end
75
+
76
+ describe '#get_items_from_stack' do
77
+ before(:each) do
78
+ @queue.items = ["i1", "i2"]
79
+ end
80
+
81
+ it 'should create a local copy from the items array' do
82
+ @queue.items.stub!(:clear)
83
+ items_copy = @queue.send(:get_items_from_stack)
84
+ items_copy.should eql(@queue.items)
85
+ items_copy.object_id.should_not be(@queue.items.object_id)
86
+ end
87
+
88
+ it 'should synchronize via mutex during copy' do
89
+ @queue.mutex.should_receive(:synchronize)
90
+ @queue.send(:get_items_from_stack)
91
+ end
92
+
93
+ it 'should clear the original items array' do
94
+ @queue.send(:get_items_from_stack)
95
+ @queue.items.should be_empty
96
+ end
97
+ end
98
+
99
+ describe '#put_item_to_stack' do
100
+ it 'should append an item to the queue stack' do
101
+ @queue.send(:put_item_to_stack, 'i3')
102
+ @queue.items.should include('i3')
103
+ end
104
+
105
+ it 'should synchronize via mutex during append' do
106
+ @queue.mutex.should_receive(:synchronize)
107
+ @queue.send(:put_item_to_stack, 'i3')
108
+ end
109
+ end
110
+
111
+ describe '#push_item_to_remote_service' do
112
+ before(:each) do
113
+ @item = { 'token' => 'secret', 'message' => 'hallo welt' }
114
+ @queue.stub!(:generate_api_messages_url).and_return('http://api.com/secret/')
115
+ Apphunkd::Remote.stub!(:post)
116
+ end
117
+
118
+ it "should generate the api url, including the item's token" do
119
+ @queue.should_receive(:generate_api_messages_url).with('secret')
120
+ @queue.send(:push_item_to_remote_service, @item)
121
+ @item.should_not include('token')
122
+ end
123
+
124
+ it "should post to the url, including the item" do
125
+ Apphunkd::Remote.should_receive(:post).with('http://api.com/secret/', { 'message' => 'hallo welt' }, 300)
126
+ @queue.send(:push_item_to_remote_service, @item)
127
+ end
128
+ end
129
+ end