apphunkd 0.9.0

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.
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