falcon 0.1.3 → 0.2.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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: b07f974b67bc387f25d6de874621983091f8f314
4
+ data.tar.gz: 6ba760b987d37bf8c33073b10dd1f68105d5ed4f
5
+ SHA512:
6
+ metadata.gz: 7651153688e68b7cb2062a5af88185ff8073c3d3d03e7ee0852772a1d1e1fdf82ebcad5d7f33077cb056ba8e60130609f7007240314df360841f13c867b5ae89
7
+ data.tar.gz: f6082bee731853ad813cb10f09db5187dea1ec369dc33636e18f92c9026c3d401dfe087eb66734d874e5d1584364f201cf0235e7fb2271ba028eda89cecccd99
data/.gitignore ADDED
@@ -0,0 +1,12 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+
11
+ # rspec failure tracking
12
+ .rspec_status
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --warnings
3
+ --require spec_helper
data/.travis.yml ADDED
@@ -0,0 +1,18 @@
1
+ language: ruby
2
+ sudo: false
3
+ dist: trusty
4
+ cache: bundler
5
+ rvm:
6
+ - 2.0
7
+ - 2.1
8
+ - 2.2
9
+ - 2.3
10
+ - 2.4
11
+ - jruby-head
12
+ - ruby-head
13
+ - rbx-3
14
+ matrix:
15
+ allow_failures:
16
+ - rvm: ruby-head
17
+ - rvm: jruby-head
18
+ - rvm: rbx-3
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in async-io.gemspec
4
+ gemspec
5
+
6
+ group :test do
7
+ gem 'simplecov'
8
+ gem 'coveralls', require: false
9
+ end
data/README.md ADDED
@@ -0,0 +1,100 @@
1
+ # Falcon
2
+
3
+ A multi-process, multi-fiber Rack HTTP server built on top of [async], [async-io] and [async-http]. Each request is run within a light weight fiber and can block on up-stream requests without stalling the entire server process. Uses a multi-process model for handling blocking requests.
4
+
5
+ [![Build Status](https://secure.travis-ci.org/socketry/falcon.svg)](http://travis-ci.org/socketry/falcon)
6
+ [![Code Climate](https://codeclimate.com/github/socketry/falcon.svg)](https://codeclimate.com/github/socketry/falcon)
7
+ [![Coverage Status](https://coveralls.io/repos/socketry/falcon/badge.svg)](https://coveralls.io/r/socketry/falcon)
8
+
9
+ [async]: https://github.com/socketry/async
10
+ [async-io]: https://github.com/socketry/async-io
11
+ [async-http]: https://github.com/socketry/async-http
12
+
13
+ ## Installation
14
+
15
+ Add this line to your application's Gemfile:
16
+
17
+ ```ruby
18
+ gem 'falcon'
19
+ ```
20
+
21
+ And then execute:
22
+
23
+ $ bundle
24
+
25
+ Or install it yourself as:
26
+
27
+ $ gem install falcon
28
+
29
+ ## Usage
30
+
31
+ You can run `falcon` directly, and it will load the `config.ru` and start serving on port 8080.
32
+
33
+ ### Integration with Guard
34
+
35
+ Falcon can restart very quickly and is ideal for use with guard. In your `Guardfile`:
36
+
37
+ ```ruby
38
+
39
+ guard :falcon do
40
+ end
41
+
42
+ ```
43
+
44
+ ### Deploying with Passenger
45
+
46
+ You can run Falcon within Passenger to improve asyncronicity by using the `Falcon::Hijack` middleware. The first request from a client will be parsed by Passenger, but `rack.hijack` allows us to start parsing requests using Falcon within a separate `Async::Reactor` which reduces latency and avoids blocking IO where possible.
47
+
48
+ ```ruby
49
+
50
+ if RACK_ENV == :production
51
+ use Falcon::Hijack
52
+ end
53
+
54
+ run MyApp
55
+
56
+ ```
57
+
58
+ ## Performance
59
+
60
+ Falcon is uses an asynchronous event-driven reactor to provide non-blocking IO. It can handle an arbitrary number of in-flight requests with minimal overhead per request.
61
+
62
+ It uses one Fiber per request, which yields in the presence of blocking IO.
63
+
64
+ ### Memory Usage
65
+
66
+ Falcon uses a pre-fork model which loads the entire rack application before forking. This reduces per-process memory usage.
67
+
68
+ ### Throughput
69
+
70
+ ## Contributing
71
+
72
+ 1. Fork it
73
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
74
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
75
+ 4. Push to the branch (`git push origin my-new-feature`)
76
+ 5. Create new Pull Request
77
+
78
+ ## License
79
+
80
+ Released under the MIT license.
81
+
82
+ Copyright, 2017, by [Samuel G. D. Williams](http://www.codeotaku.com/samuel-williams).
83
+
84
+ Permission is hereby granted, free of charge, to any person obtaining a copy
85
+ of this software and associated documentation files (the "Software"), to deal
86
+ in the Software without restriction, including without limitation the rights
87
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
88
+ copies of the Software, and to permit persons to whom the Software is
89
+ furnished to do so, subject to the following conditions:
90
+
91
+ The above copyright notice and this permission notice shall be included in
92
+ all copies or substantial portions of the Software.
93
+
94
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
95
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
96
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
97
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
98
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
99
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
100
+ THE SOFTWARE.
data/Rakefile CHANGED
@@ -1,43 +1,71 @@
1
- # encoding: utf-8
2
- require 'rake'
3
- require 'rake/testtask'
4
- require 'rake/rdoctask'
5
- require File.join(File.dirname(__FILE__), 'lib', 'falcon', 'version')
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:test)
6
5
 
7
- desc 'Default: run unit tests.'
8
6
  task :default => :test
9
7
 
10
- desc 'Test the falcon plugin.'
11
- Rake::TestTask.new(:test) do |t|
12
- t.libs << 'lib'
13
- t.libs << 'test'
14
- t.pattern = 'test/**/*_test.rb'
15
- t.verbose = true
16
- end
8
+ task :server do
9
+ require 'async/reactor'
10
+ require 'async/http/server'
11
+
12
+ app = lambda do |env|
13
+ [200, {}, ["Hello World"]]
14
+ end
15
+
16
+ server = Async::HTTP::Server.new([
17
+ Async::IO::Address.tcp('127.0.0.1', 9294, reuse_port: true)
18
+ ], app)
17
19
 
18
- desc 'Generate documentation for the falcon plugin.'
19
- Rake::RDocTask.new(:rdoc) do |rdoc|
20
- rdoc.rdoc_dir = 'rdoc'
21
- rdoc.title = 'Falcon'
22
- rdoc.options << '--line-numbers' << '--inline-source'
23
- rdoc.rdoc_files.include('README.rdoc')
24
- rdoc.rdoc_files.include('lib/**/*.rb')
20
+ Async::Reactor.run do
21
+ server.run
22
+ end
25
23
  end
26
24
 
27
- begin
28
- require 'jeweler'
29
- Jeweler::Tasks.new do |s|
30
- s.name = "falcon"
31
- s.version = Falcon::VERSION.dup
32
- s.summary = "Background video encoding"
33
- s.description = "Background video encoding via resque"
34
- s.email = "galeta.igor@gmail.com"
35
- s.homepage = "https://github.com/galetahub/falcon"
36
- s.authors = ["Igor Galeta", "Pavlo Galeta"]
37
- s.files = FileList["[A-Z]*", "{app,config,lib}/**/*"] - %w(Gemfile Gemfile.lock)
38
- end
39
-
40
- Jeweler::GemcutterTasks.new
41
- rescue LoadError
42
- puts "Jeweler not available. Install it with: gem install jeweler"
25
+ task :client do
26
+ require 'async/reactor'
27
+ require 'async/http/client'
28
+
29
+ client = Async::HTTP::Client.new([
30
+ Async::IO::Address.tcp('127.0.0.1', 9294, reuse_port: true)
31
+ ])
32
+
33
+ Async::Reactor.run do
34
+ response = client.get("/")
35
+
36
+ puts response.inspect
37
+ end
43
38
  end
39
+
40
+ task :wrk do
41
+ require 'async/reactor'
42
+ require 'async/http/server'
43
+
44
+ app = lambda do |env|
45
+ [200, {}, ["Hello World"]]
46
+ end
47
+
48
+ server = Async::HTTP::Server.new([
49
+ Async::IO::Address.tcp('127.0.0.1', 9294, reuse_port: true)
50
+ ], app)
51
+
52
+ process_count = Etc.nprocessors
53
+
54
+ pids = process_count.times.collect do
55
+ fork do
56
+ Async::Reactor.run do
57
+ server.run
58
+ end
59
+ end
60
+ end
61
+
62
+ url = "http://127.0.0.1:9294/"
63
+
64
+ connections = process_count
65
+ system("wrk", "-c", connections.to_s, "-d", "2", "-t", connections.to_s, url)
66
+
67
+ pids.each do |pid|
68
+ Process.kill(:KILL, pid)
69
+ Process.wait pid
70
+ end
71
+ end
data/bin/falcon ADDED
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Copyright, 2017, by Samuel G. D. Williams. <http://www.codeotaku.com>
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the "Software"), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in
13
+ # all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ # THE SOFTWARE.
22
+
23
+ require_relative '../lib/falcon'
24
+
25
+ begin
26
+ Falcon::Command.parse(ARGV).invoke
27
+ rescue Interrupt
28
+ end
data/falcon.gemspec ADDED
@@ -0,0 +1,31 @@
1
+ # coding: utf-8
2
+ require_relative 'lib/falcon/version'
3
+
4
+ Gem::Specification.new do |spec|
5
+ spec.name = "falcon"
6
+ spec.version = Falcon::VERSION
7
+ spec.authors = ["Samuel Williams"]
8
+ spec.email = ["samuel.williams@oriontransfer.co.nz"]
9
+
10
+ spec.summary = ""
11
+ spec.homepage = "https://github.com/socketry/falcon"
12
+
13
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
14
+ f.match(%r{^(test|spec|features)/})
15
+ end
16
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ spec.require_paths = ["lib"]
18
+
19
+ spec.add_dependency("async-http", "~> 0.2")
20
+ spec.add_dependency("async-container", "~> 0.1")
21
+
22
+ spec.add_dependency("rack", ">= 1.0")
23
+
24
+ spec.add_dependency('samovar', "~> 1.3")
25
+
26
+ spec.add_development_dependency "async-rspec", "~> 1.1"
27
+
28
+ spec.add_development_dependency "bundler", "~> 1.3"
29
+ spec.add_development_dependency "rspec", "~> 3.6"
30
+ spec.add_development_dependency "rake"
31
+ end
data/lib/falcon.rb CHANGED
@@ -1,58 +1,21 @@
1
- module Falcon
2
- autoload :Profile, 'falcon/profile'
3
- autoload :Base, 'falcon/base'
4
- autoload :Encoder, 'falcon/encoder'
5
- autoload :Media, 'falcon/media'
6
-
7
- CONTENT_TYPES = [
8
- 'application/x-mp4',
9
- 'video/mpeg',
10
- 'video/quicktime',
11
- 'video/x-la-asf',
12
- 'video/x-ms-asf',
13
- 'video/x-msvideo',
14
- 'video/x-sgi-movie',
15
- 'video/x-flv',
16
- 'flv-application/octet-stream',
17
- 'application/octet-stream',
18
- 'video/3gpp',
19
- 'video/3gpp2',
20
- 'video/3gpp-tt',
21
- 'video/BMPEG',
22
- 'video/BT656',
23
- 'video/CelB',
24
- 'video/DV',
25
- 'video/H261',
26
- 'video/H263',
27
- 'video/H263-1998',
28
- 'video/H263-2000',
29
- 'video/H264',
30
- 'video/JPEG',
31
- 'video/MJ2',
32
- 'video/MP1S',
33
- 'video/MP2P',
34
- 'video/MP2T',
35
- 'video/mp4',
36
- 'video/MP4V-ES',
37
- 'video/MPV',
38
- 'video/mpeg4',
39
- 'video/mpeg4-generic',
40
- 'video/nv',
41
- 'video/parityfec',
42
- 'video/pointer',
43
- 'video/raw',
44
- 'video/rtx',
45
- 'video/x-matroska',
46
- 'video/x-ms-wmv',
47
- 'video/divxplus',
48
- 'video/avi',
49
- 'video/divx',
50
- 'video/vnd.objectvideo' ]
51
-
52
- def self.table_name_prefix
53
- 'falcon_'
54
- end
55
- end
1
+ # Copyright, 2017, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
56
20
 
57
- require 'falcon/profiles'
58
- require 'falcon/engine'
21
+ require_relative "falcon/command"
@@ -0,0 +1,86 @@
1
+ # Copyright, 2017, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
21
+ require_relative 'server'
22
+
23
+ require 'async/container'
24
+
25
+ require 'samovar'
26
+ require 'etc'
27
+
28
+ require 'rack/builder'
29
+ require 'rack/server'
30
+
31
+ module Falcon
32
+ module Command
33
+ def self.parse(*args)
34
+ Top.parse(*args)
35
+ end
36
+
37
+ class Serve < Samovar::Command
38
+ self.description = "Run an HTTP server."
39
+
40
+ options do
41
+ option '-c/--config <path>', "Rackup configuration file to load", default: 'config.ru'
42
+ option '-n/--concurrency <count>', "Number of processes to start", default: Etc.nprocessors, type: Integer
43
+
44
+ option '-b/--bind <address>', "Bind to the given hostname/address", default: "tcp://localhost:9292"
45
+ end
46
+
47
+ def run
48
+ app, options = Rack::Builder.parse_file(@options[:config])
49
+
50
+ Async::Container.new(concurrency: @options[:concurrency]) do
51
+ server = Falcon::Server.new(app, [
52
+ Async::IO::Address.parse(@options[:bind], reuse_port: true)
53
+ ])
54
+
55
+ server.run
56
+ end
57
+ end
58
+
59
+ def invoke
60
+ run
61
+
62
+ sleep
63
+ end
64
+ end
65
+
66
+ class Top < Samovar::Command
67
+ self.description = "An asynchronous HTTP client/server toolset."
68
+
69
+ nested '<command>',
70
+ 'serve' => Serve
71
+ # 'get' => Get
72
+ # 'post' => Post
73
+ # 'head' => Head,
74
+ # 'put' => Put,
75
+ # 'delete' => Delete
76
+
77
+ def invoke(program_name: File.basename($0))
78
+ if @command
79
+ @command.invoke
80
+ else
81
+ print_usage(program_name)
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end