thin_async 0.0.1

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 ADDED
@@ -0,0 +1,25 @@
1
+ # Thin Asynchronous Response API
2
+ A nice wrapper around Thin's obscure async callback used to send response body asynchronously.
3
+ Which means you can send the response in chunks while allowing Thin to process other requests.
4
+
5
+ Crazy delicious with em-http-request for file upload, image processing, proxying, etc.
6
+
7
+ ## _WARNING_
8
+ You should not use long blocking operations (Net::HTTP or slow shell calls) with this as it
9
+ will prevent the EventMachine event loop from running and block all other requests.
10
+
11
+ ## Usage
12
+ Inside your Rack app #call(env):
13
+
14
+ Thin::AsyncResponse.new(env) do |response|
15
+ response << "this is ... "
16
+ EM.add_timer(1) do
17
+ # This will be sent to the client 1 sec later without blocking other requests.
18
+ response << "async!"
19
+ response.done
20
+ end
21
+ end
22
+
23
+ See example/ dir for more.
24
+
25
+ (c) macournoyer
data/example/simple.ru ADDED
@@ -0,0 +1,19 @@
1
+ require File.dirname(__FILE__) + "/../lib/thin/async"
2
+
3
+ class Simple
4
+ def call(env)
5
+ response = Thin::AsyncResponse.new(env)
6
+
7
+ response << " " * 1024
8
+
9
+ response << "this is ... "
10
+ EM.add_timer(1) do
11
+ response << "async stuff!"
12
+ response.done
13
+ end
14
+
15
+ response.finish
16
+ end
17
+ end
18
+
19
+ run Simple.new
data/lib/thin/async.rb ADDED
@@ -0,0 +1,72 @@
1
+ module Thin
2
+ unless defined?(DeferrableBody)
3
+ # Based on version from James Tucker <raggi@rubyforge.org>
4
+ class DeferrableBody
5
+ include EM::Deferrable
6
+
7
+ def initialize
8
+ @queue = []
9
+ end
10
+
11
+ def call(body)
12
+ @queue << body
13
+ schedule_dequeue
14
+ end
15
+
16
+ def each(&blk)
17
+ @body_callback = blk
18
+ schedule_dequeue
19
+ end
20
+
21
+ private
22
+ def schedule_dequeue
23
+ return unless @body_callback
24
+ EM.next_tick do
25
+ next unless body = @queue.shift
26
+ body.each do |chunk|
27
+ @body_callback.call(chunk)
28
+ end
29
+ schedule_dequeue unless @queue.empty?
30
+ end
31
+ end
32
+ end
33
+ end
34
+
35
+ # Response whos body is sent asynchronously.
36
+ class AsyncResponse
37
+ include Rack::Response::Helpers
38
+
39
+ Marker = [-1, {}, []].freeze
40
+
41
+ attr_reader :headers
42
+ attr_accessor :status
43
+
44
+ def initialize(env)
45
+ @callback = env['async.callback']
46
+ @body = DeferrableBody.new
47
+ @status = 200
48
+ @headers = {}
49
+
50
+ if block_given?
51
+ yield self
52
+ finish
53
+ end
54
+ end
55
+
56
+ def write(body)
57
+ @body.call(body.respond_to?(:each) ? body : [body])
58
+ end
59
+ alias :<< :write
60
+
61
+ def done
62
+ EM.next_tick do
63
+ @body.succeed
64
+ end
65
+ end
66
+
67
+ def finish
68
+ @callback.call [@status, @headers, @body]
69
+ Marker
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,13 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = "thin_async"
3
+ s.version = "0.0.1"
4
+ s.summary = "A nice wrapper to send response body asynchronously with Thin"
5
+
6
+ s.author = "Marc-Andre Cournoyer"
7
+ s.email = "macournoyer@gmail.com"
8
+ s.files = Dir["**/*"]
9
+ s.homepage = "http://github.com/macournoyer/thin_async"
10
+ s.require_paths = ["lib"]
11
+
12
+ s.add_dependency "thin", ">= 1.2.1"
13
+ end
metadata ADDED
@@ -0,0 +1,68 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: thin_async
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Marc-Andre Cournoyer
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-12-13 00:00:00 -05:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: thin
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 1.2.1
24
+ version:
25
+ description:
26
+ email: macournoyer@gmail.com
27
+ executables: []
28
+
29
+ extensions: []
30
+
31
+ extra_rdoc_files: []
32
+
33
+ files:
34
+ - example/simple.ru
35
+ - lib/thin/async.rb
36
+ - README.md
37
+ - thin_async-0.0.1.gem
38
+ - thin_async.gemspec
39
+ has_rdoc: true
40
+ homepage: http://github.com/macournoyer/thin_async
41
+ licenses: []
42
+
43
+ post_install_message:
44
+ rdoc_options: []
45
+
46
+ require_paths:
47
+ - lib
48
+ required_ruby_version: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: "0"
53
+ version:
54
+ required_rubygems_version: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ version: "0"
59
+ version:
60
+ requirements: []
61
+
62
+ rubyforge_project:
63
+ rubygems_version: 1.3.5
64
+ signing_key:
65
+ specification_version: 3
66
+ summary: A nice wrapper to send response body asynchronously with Thin
67
+ test_files: []
68
+