fibre 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.
- checksums.yaml +7 -0
- data/.gitignore +14 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +46 -0
- data/Rakefile +2 -0
- data/fibre.gemspec +29 -0
- data/lib/fibre.rb +31 -0
- data/lib/fibre/core_ext/fiber.rb +57 -0
- data/lib/fibre/fiber_pool.rb +92 -0
- data/lib/fibre/mock.rb +24 -0
- data/lib/fibre/rack/fiber_pool.rb +23 -0
- data/lib/fibre/scope.rb +49 -0
- data/lib/fibre/version.rb +3 -0
- data/spec/fibre_spec.rb +28 -0
- data/spec/spec_helper.rb +9 -0
- metadata +117 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 8fabc7b72080a5a72b9c4f02e298546228dfebca
|
4
|
+
data.tar.gz: ffb6409b8cb5e104792c007ea293ec28c20bbc5b
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 6a47d2f626884a4efcd6a589e9d255b3305432884a044239e8c08b531773299fa0e20e2d92ae4945d2a2c4b723128da94ae386f4b1baff8147e99197bc923c98
|
7
|
+
data.tar.gz: db6e15c5b1f7882db1b0212d2fb5e5b1c39a6f32513394ead72cf17670c142999ae5e0e67dff9fd0a81982337676a71cec1268d4a5079d7bafd2264911a44f3e
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 che
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
# Fibre
|
2
|
+
|
3
|
+
Fibre - fiber pool with events
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem 'fibre'
|
11
|
+
```
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install fibre
|
20
|
+
|
21
|
+
Initialize pool:
|
22
|
+
|
23
|
+
Fibre.pool_size = 10
|
24
|
+
|
25
|
+
## Usage
|
26
|
+
|
27
|
+
```ruby
|
28
|
+
Fibre.pool_size = 10
|
29
|
+
Fibre.pool.checkout do
|
30
|
+
puts "runned in fiber"
|
31
|
+
end
|
32
|
+
# some fiber raised exception
|
33
|
+
using EventObject
|
34
|
+
Fibre.pool.on :error do |e|
|
35
|
+
puts e.to_s
|
36
|
+
exit
|
37
|
+
end
|
38
|
+
```
|
39
|
+
|
40
|
+
## Contributing
|
41
|
+
|
42
|
+
1. Fork it ( https://github.com/chelovekov/fibre/fork )
|
43
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
44
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
45
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
46
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
data/fibre.gemspec
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'fibre/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "fibre"
|
8
|
+
spec.version = Fibre::VERSION
|
9
|
+
spec.authors = ["che"]
|
10
|
+
spec.email = ["max@kupibilet.ru"]
|
11
|
+
spec.summary = %q{Fibre - fiber pool, mock and scoping fibres}
|
12
|
+
#spec.description = %q{TODO: Write a longer description. Optional.}
|
13
|
+
spec.homepage = ""
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.required_ruby_version = '>= 2.1.0'
|
22
|
+
spec.required_rubygems_version = '>= 2.3.0'
|
23
|
+
|
24
|
+
spec.add_development_dependency "bundler", "~> 1.6"
|
25
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
26
|
+
spec.add_development_dependency "rspec", "~> 3.0.0"
|
27
|
+
|
28
|
+
spec.add_dependency "event_object", "~> 0.9"
|
29
|
+
end
|
data/lib/fibre.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
require "event_object"
|
2
|
+
require "fibre/version"
|
3
|
+
require "fibre/core_ext/fiber"
|
4
|
+
|
5
|
+
module Fibre
|
6
|
+
autoload :FiberPool, 'fibre/fiber_pool'
|
7
|
+
autoload :Mock, 'fibre/mock'
|
8
|
+
autoload :Scope, 'fibre/scope'
|
9
|
+
|
10
|
+
module Rack
|
11
|
+
autoload :FiberPool, 'fibre/rack/fiber_pool'
|
12
|
+
end
|
13
|
+
|
14
|
+
# Configuration module
|
15
|
+
|
16
|
+
extend self
|
17
|
+
|
18
|
+
# Fiber.root - root fiber
|
19
|
+
attr_accessor :root
|
20
|
+
self.root = Fiber.current
|
21
|
+
|
22
|
+
# Pool size can be set before pool initialized
|
23
|
+
attr_accessor :pool_size
|
24
|
+
self.pool_size = 20
|
25
|
+
|
26
|
+
# Initialize with default pool_size
|
27
|
+
attr_writer :pool
|
28
|
+
def pool
|
29
|
+
@pool ||= FiberPool.new(pool_size)
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'fiber'
|
2
|
+
|
3
|
+
#
|
4
|
+
# Fiber.sync do |fiber|
|
5
|
+
# fiber.resume response
|
6
|
+
# fiber.leave StandardError, "Something"
|
7
|
+
# end
|
8
|
+
class Fiber
|
9
|
+
|
10
|
+
def attributes
|
11
|
+
@attributes ||= {}
|
12
|
+
end
|
13
|
+
|
14
|
+
def root?
|
15
|
+
self.eql? Fibre.root
|
16
|
+
end
|
17
|
+
|
18
|
+
def [](key)
|
19
|
+
attributes[key]
|
20
|
+
end
|
21
|
+
|
22
|
+
def []=(key,value)
|
23
|
+
attributes[key] = value
|
24
|
+
end
|
25
|
+
|
26
|
+
class <<self
|
27
|
+
|
28
|
+
def scope(*a, &b)
|
29
|
+
Fiber::Scope.scope(*a, &b)
|
30
|
+
end
|
31
|
+
|
32
|
+
def sync(*a, &b)
|
33
|
+
Fiber::Scope.scope? ? Fiber::Scope.sync(*a, &b) : sync_it(*a, &b)
|
34
|
+
end
|
35
|
+
|
36
|
+
# raise exception if we catch exception
|
37
|
+
def yield!
|
38
|
+
Fiber.yield.tap do |y|
|
39
|
+
raise y if y.is_a?(Exception)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
#
|
44
|
+
# Fiber.sync do |fiber|
|
45
|
+
# fiber.resume # ...
|
46
|
+
# end
|
47
|
+
#
|
48
|
+
def sync_it
|
49
|
+
yield(Fiber.current) if block_given?
|
50
|
+
Fiber.yield!
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def leave(exception, message=nil)
|
55
|
+
resume exception.new(message)
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
#
|
2
|
+
# Fiber pool
|
3
|
+
#
|
4
|
+
# Example,
|
5
|
+
# using EventObject
|
6
|
+
# pool = Fibre::FiberPool.new(10)
|
7
|
+
# pool.checkout do
|
8
|
+
# puts "runned in fiber"
|
9
|
+
# end
|
10
|
+
#
|
11
|
+
# # some fiber raised exception
|
12
|
+
# pool.on :error do |e|
|
13
|
+
# puts e.to_s
|
14
|
+
# end
|
15
|
+
|
16
|
+
module Fibre
|
17
|
+
using EventObject
|
18
|
+
|
19
|
+
class FiberPool
|
20
|
+
events :error, :before, :after
|
21
|
+
|
22
|
+
# Initialize fibers pool
|
23
|
+
def initialize(size)
|
24
|
+
@pool = size.times.collect { ::Fiber.new(&self.method(:fiber_entry)) }
|
25
|
+
@reserved = {}
|
26
|
+
@queue = []
|
27
|
+
end
|
28
|
+
|
29
|
+
# Check-out fiber from pool
|
30
|
+
def checkout(&b)
|
31
|
+
spec = { block: b, parent: ::Fiber.current }
|
32
|
+
|
33
|
+
if @pool.empty?
|
34
|
+
raise "fiber queue overflow" if @queue.size > MAX_POOL_QUEUE_SIZE
|
35
|
+
@queue.push spec
|
36
|
+
return
|
37
|
+
end
|
38
|
+
|
39
|
+
@pool.shift.tap do |fiber|
|
40
|
+
@reserved[fiber.object_id] = fiber
|
41
|
+
fiber.resume(spec)
|
42
|
+
end
|
43
|
+
|
44
|
+
self
|
45
|
+
end
|
46
|
+
|
47
|
+
# Free pool size
|
48
|
+
def size
|
49
|
+
@pool.size
|
50
|
+
end
|
51
|
+
|
52
|
+
def reserved
|
53
|
+
@reserved
|
54
|
+
end
|
55
|
+
|
56
|
+
def queue
|
57
|
+
@queue
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
# entrypoint for all fibers
|
63
|
+
def fiber_entry(spec)
|
64
|
+
loop do
|
65
|
+
raise "wrong spec in fiber block" unless spec.is_a?(Hash)
|
66
|
+
|
67
|
+
begin
|
68
|
+
before!(spec)
|
69
|
+
spec[:block].call# *Fiber.current.args
|
70
|
+
after!(spec)
|
71
|
+
rescue Exception => e
|
72
|
+
# don't raise fiber exceptions
|
73
|
+
error!(e)
|
74
|
+
end
|
75
|
+
|
76
|
+
unless @queue.empty?
|
77
|
+
spec = @queue.shift
|
78
|
+
next
|
79
|
+
end
|
80
|
+
|
81
|
+
spec = checkin
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
# Check-in fiber to pool
|
86
|
+
def checkin
|
87
|
+
@reserved.delete ::Fiber.current.object_id
|
88
|
+
@pool.unshift ::Fiber.current
|
89
|
+
::Fiber.yield
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
data/lib/fibre/mock.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
class Fiber
|
2
|
+
class Mock
|
3
|
+
attr_reader :scope
|
4
|
+
attr_reader :result
|
5
|
+
|
6
|
+
def initialize(scope)
|
7
|
+
@scope = scope
|
8
|
+
end
|
9
|
+
|
10
|
+
def resume(result)
|
11
|
+
@result = result
|
12
|
+
@completed = true
|
13
|
+
@scope.check
|
14
|
+
end
|
15
|
+
|
16
|
+
def completed?
|
17
|
+
!!@completed
|
18
|
+
end
|
19
|
+
|
20
|
+
def leave(e, *a)
|
21
|
+
resume e.new(*a)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Fibre
|
2
|
+
module Rack
|
3
|
+
class FiberPool
|
4
|
+
def initialize(app, options={})
|
5
|
+
@app = app
|
6
|
+
yield Fibre.pool if block_given?
|
7
|
+
@rescue_exception = options[:rescue_exception] || (->(env, ex) { [500, {}, ["Internal Server Error"]] })
|
8
|
+
end
|
9
|
+
|
10
|
+
def call(env)
|
11
|
+
call_app = lambda do
|
12
|
+
result = @app.call(env)
|
13
|
+
env['async.callback'].call result
|
14
|
+
end
|
15
|
+
|
16
|
+
Fibre.pool.checkout(&call_app)
|
17
|
+
throw :async
|
18
|
+
rescue => ex
|
19
|
+
@rescue_exception[env, ex]
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/lib/fibre/scope.rb
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
class Fiber
|
2
|
+
class Scope
|
3
|
+
attr_accessor :mocks
|
4
|
+
attr_accessor :fiber
|
5
|
+
|
6
|
+
class <<self
|
7
|
+
|
8
|
+
def scope
|
9
|
+
raise "nested scopes" if Fiber.current[:scope]
|
10
|
+
Fiber.current[:scope] = self.new(Fiber.current)
|
11
|
+
res = yield
|
12
|
+
Fiber.current[:scope] = nil
|
13
|
+
Fiber.yield!
|
14
|
+
res
|
15
|
+
end
|
16
|
+
|
17
|
+
def scope?
|
18
|
+
!!Fiber.current[:scope]
|
19
|
+
end
|
20
|
+
|
21
|
+
def sync
|
22
|
+
scope = Fiber.current[:scope]
|
23
|
+
mock = Fiber::Mock.new(scope)
|
24
|
+
scope.mocks << mock
|
25
|
+
yield(mock) if block_given?
|
26
|
+
mock
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def initialize(fiber)
|
31
|
+
@fiber = fiber
|
32
|
+
@mocks = []
|
33
|
+
end
|
34
|
+
|
35
|
+
def check
|
36
|
+
fiber.resume if @mocks.all?(&:completed?)
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
module Iterator
|
41
|
+
def sync
|
42
|
+
res = Fiber.scope do
|
43
|
+
collect(&:sync)
|
44
|
+
end
|
45
|
+
res.collect(&:result)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
data/spec/fibre_spec.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
describe Fibre do
|
3
|
+
using EventObject
|
4
|
+
|
5
|
+
it "should create default pool with default size" do
|
6
|
+
expect(Fibre.pool.size).to be(20)
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should have right root fiber" do
|
10
|
+
expect(Fibre.root).to equal(Fiber.current)
|
11
|
+
expect(Fiber.current.root?).to be true
|
12
|
+
end
|
13
|
+
|
14
|
+
let(:probe) { lambda {} }
|
15
|
+
|
16
|
+
it "should checkout fiber" do
|
17
|
+
expect(probe).to receive(:call)
|
18
|
+
Fibre.pool.checkout(&probe)
|
19
|
+
end
|
20
|
+
|
21
|
+
it "rescue error in fiber" do
|
22
|
+
expect(probe).to receive(:call)
|
23
|
+
Fibre.pool.on(:error, &probe)
|
24
|
+
Fibre.pool.checkout do
|
25
|
+
raise
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,117 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: fibre
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.9.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- che
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-08-13 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.6'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.6'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 3.0.0
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 3.0.0
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: event_object
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0.9'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0.9'
|
69
|
+
description:
|
70
|
+
email:
|
71
|
+
- max@kupibilet.ru
|
72
|
+
executables: []
|
73
|
+
extensions: []
|
74
|
+
extra_rdoc_files: []
|
75
|
+
files:
|
76
|
+
- ".gitignore"
|
77
|
+
- Gemfile
|
78
|
+
- LICENSE.txt
|
79
|
+
- README.md
|
80
|
+
- Rakefile
|
81
|
+
- fibre.gemspec
|
82
|
+
- lib/fibre.rb
|
83
|
+
- lib/fibre/core_ext/fiber.rb
|
84
|
+
- lib/fibre/fiber_pool.rb
|
85
|
+
- lib/fibre/mock.rb
|
86
|
+
- lib/fibre/rack/fiber_pool.rb
|
87
|
+
- lib/fibre/scope.rb
|
88
|
+
- lib/fibre/version.rb
|
89
|
+
- spec/fibre_spec.rb
|
90
|
+
- spec/spec_helper.rb
|
91
|
+
homepage: ''
|
92
|
+
licenses:
|
93
|
+
- MIT
|
94
|
+
metadata: {}
|
95
|
+
post_install_message:
|
96
|
+
rdoc_options: []
|
97
|
+
require_paths:
|
98
|
+
- lib
|
99
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: 2.1.0
|
104
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
105
|
+
requirements:
|
106
|
+
- - ">="
|
107
|
+
- !ruby/object:Gem::Version
|
108
|
+
version: 2.3.0
|
109
|
+
requirements: []
|
110
|
+
rubyforge_project:
|
111
|
+
rubygems_version: 2.4.1
|
112
|
+
signing_key:
|
113
|
+
specification_version: 4
|
114
|
+
summary: Fibre - fiber pool, mock and scoping fibres
|
115
|
+
test_files:
|
116
|
+
- spec/fibre_spec.rb
|
117
|
+
- spec/spec_helper.rb
|