em-midori 0.1.12 → 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 +4 -4
- data/.editorconfig +9 -0
- data/em-midori.sublime-project +16 -0
- data/lib/midori/connection.rb +2 -0
- data/lib/midori/core_ext/event_loop.rb +31 -7
- data/lib/midori/core_ext/promise.rb +12 -1
- data/lib/midori/extension/net.rb +3 -2
- data/lib/midori/extension/sequel/mysql2.rb +26 -15
- data/lib/midori/extension/sequel/postgres.rb +23 -15
- data/lib/midori/runner.rb +4 -0
- data/lib/midori/server.rb +1 -1
- data/lib/midori/version.rb +1 -1
- data/tutorial/essentials/installation.md +2 -2
- data/tutorial/essentials/routing.md +1 -1
- metadata +7 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d890861f5486fd8c8ecd3dff2a3780a26af42340
|
4
|
+
data.tar.gz: 1d6ddf047c3534998eb6637cfbe387d56f1e86f2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2664bb10cda5ab00f264bd91e633315ab2f05fb44218050597fc61c34890fa00bf042d3a476e24711415b9eb8d28e2a4b94f2225bb307f1f1e77c1fffde468d6
|
7
|
+
data.tar.gz: 884cce78c3c28f9014823b45d03529082d7ff4c6832be0bfaa490265a08a7a05ad2b3ed7d5447074edbb6d3e06d32a0006004116afece1b442511f417583d33e
|
data/.editorconfig
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
{
|
2
|
+
"folders":
|
3
|
+
[
|
4
|
+
{
|
5
|
+
"path": ".",
|
6
|
+
"folder_exclude_patterns": [".resources", "coverage"],
|
7
|
+
"file_exclude_patterns": ["em-midori-*.gem","*.sublime-workspace","logo.png",".DS_Store","CONTRIBUTOR_COVENANT_CODE_OF_CONDUCT.md"]
|
8
|
+
}
|
9
|
+
],
|
10
|
+
"settings":
|
11
|
+
{
|
12
|
+
"tab_size": 2,
|
13
|
+
"translate_tabs_to_spaces": true,
|
14
|
+
"trim_trailing_white_space_on_save": true
|
15
|
+
}
|
16
|
+
}
|
data/lib/midori/connection.rb
CHANGED
@@ -4,28 +4,52 @@ module EventLoop
|
|
4
4
|
class << self
|
5
5
|
SELECTOR = NIO::Selector.new
|
6
6
|
TIMERS = []
|
7
|
+
IOS = Hash.new
|
8
|
+
QUEUE = Hash.new
|
7
9
|
|
8
10
|
def add_timer(timer)
|
9
11
|
timer.start_time = Time.now.to_f + timer.time
|
10
12
|
TIMERS << timer
|
11
13
|
end
|
12
14
|
|
13
|
-
def register(io, interest=(:rw), &callback)
|
14
|
-
|
15
|
-
|
15
|
+
def register(io, interest=(:rw), timeout=nil, resolve=nil, &callback)
|
16
|
+
if QUEUE[io.to_i].nil?
|
17
|
+
QUEUE[io.to_i] = Array.new
|
18
|
+
register_raw(io, interest, timeout, resolve, callback)
|
19
|
+
else
|
20
|
+
QUEUE[io.to_i] << [io, interest, timeout, resolve, callback]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def register_raw(io, interest=(:rw), timeout=nil, resolve=nil, callback)
|
25
|
+
SELECTOR.register(io, interest)
|
26
|
+
timer = nil
|
27
|
+
unless timeout.nil?
|
28
|
+
timer = EventLoop::Timer.new(timeout) do
|
29
|
+
EventLoop.deregister(io)
|
30
|
+
resolve.call(TimeoutError) unless resolve.nil?
|
31
|
+
end
|
32
|
+
EventLoop.add_timer(timer)
|
33
|
+
end
|
34
|
+
|
35
|
+
IOS[io] = {
|
36
|
+
timer: timer ? timer : nil,
|
16
37
|
callback: callback,
|
17
38
|
}
|
18
|
-
|
19
39
|
end
|
20
40
|
|
21
41
|
def deregister(io)
|
42
|
+
fd = io.to_i
|
22
43
|
SELECTOR.deregister(io)
|
44
|
+
IOS.delete(io)
|
45
|
+
next_register = QUEUE[fd].shift
|
46
|
+
next_register.nil? ? QUEUE.delete(fd) : register_raw(*next_register)
|
23
47
|
end
|
24
48
|
|
25
49
|
def run_once
|
26
|
-
SELECTOR.select(0.2) do |monitor| # Timeout for
|
27
|
-
monitor.
|
28
|
-
monitor.
|
50
|
+
SELECTOR.select(0.2) do |monitor| # Timeout for 0.2 secs
|
51
|
+
TIMERS.delete(IOS[monitor.io][:timer]) unless IOS[monitor.io][:timer].nil?
|
52
|
+
IOS[monitor.io][:callback].call(monitor)
|
29
53
|
end
|
30
54
|
EventLoop.timer_once
|
31
55
|
end
|
@@ -45,6 +45,17 @@ module Kernel
|
|
45
45
|
# @example
|
46
46
|
# result = await SQL.query('SELECT * FROM hello')
|
47
47
|
def await(promise)
|
48
|
-
Fiber.yield promise
|
48
|
+
result = Fiber.yield promise
|
49
|
+
if result.is_a? PromiseException
|
50
|
+
raise result.payload
|
51
|
+
end
|
52
|
+
result
|
49
53
|
end
|
50
54
|
end
|
55
|
+
|
56
|
+
class PromiseException < Exception
|
57
|
+
attr_reader :payload
|
58
|
+
def initialize(payload)
|
59
|
+
@payload = payload
|
60
|
+
end
|
61
|
+
end
|
data/lib/midori/extension/net.rb
CHANGED
@@ -3,8 +3,9 @@ require 'net/protocol'
|
|
3
3
|
class Net::BufferedIO
|
4
4
|
def wait_io(interest)
|
5
5
|
await(Promise.new do |resolve|
|
6
|
-
|
7
|
-
|
6
|
+
io = @io.to_io
|
7
|
+
EventLoop.register(io, interest) do
|
8
|
+
EventLoop.deregister(io)
|
8
9
|
resolve.call(self)
|
9
10
|
end
|
10
11
|
end)
|
@@ -1,6 +1,8 @@
|
|
1
1
|
safe_require 'sequel', 'gem install sequel'
|
2
2
|
require 'sequel/adapters/mysql2'
|
3
3
|
|
4
|
+
MYSQL_SOCKETS = {}
|
5
|
+
|
4
6
|
module Sequel
|
5
7
|
module Mysql2
|
6
8
|
class Database
|
@@ -36,22 +38,31 @@ module Sequel
|
|
36
38
|
stmt.execute(*args)
|
37
39
|
# :nocov:
|
38
40
|
else
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
conn.query(sql,
|
44
|
-
database_timezone: timezone,
|
45
|
-
application_timezone: Sequel.application_timezone,
|
46
|
-
stream: stream,
|
47
|
-
async: true)
|
48
|
-
resolve.call
|
49
|
-
end
|
50
|
-
end)
|
41
|
+
if MYSQL_SOCKETS[conn.socket].nil?
|
42
|
+
MYSQL_SOCKETS[conn.socket] = IO::open(conn.socket)
|
43
|
+
end
|
44
|
+
socket = MYSQL_SOCKETS[conn.socket]
|
51
45
|
await(Promise.new do |resolve|
|
52
|
-
|
53
|
-
|
54
|
-
|
46
|
+
count = 0
|
47
|
+
EventLoop.register(socket, :rw, 2, resolve) do
|
48
|
+
if (count == 0)
|
49
|
+
# Writable
|
50
|
+
count += 1
|
51
|
+
conn.query(sql,
|
52
|
+
database_timezone: timezone,
|
53
|
+
application_timezone: Sequel.application_timezone,
|
54
|
+
stream: stream,
|
55
|
+
async: true)
|
56
|
+
else
|
57
|
+
# Readable
|
58
|
+
begin
|
59
|
+
EventLoop.deregister(socket)
|
60
|
+
resolve.call(conn.async_result)
|
61
|
+
rescue ::Mysql2::Error => e
|
62
|
+
resolve.call(PromiseException.new(e))
|
63
|
+
next
|
64
|
+
end
|
65
|
+
end
|
55
66
|
end
|
56
67
|
end)
|
57
68
|
end
|
@@ -1,6 +1,8 @@
|
|
1
1
|
safe_require 'sequel', 'gem install sequel'
|
2
2
|
require 'sequel/adapters/postgres'
|
3
3
|
|
4
|
+
POSTGRES_SOCKETS = {}
|
5
|
+
|
4
6
|
##
|
5
7
|
# Midori Extension of sequel postgres through meta programming
|
6
8
|
class Sequel::Postgres::Adapter
|
@@ -10,24 +12,30 @@ class Sequel::Postgres::Adapter
|
|
10
12
|
# @return [Array] sql query result
|
11
13
|
def execute_query(sql, args)
|
12
14
|
@db.log_connection_yield(sql, self, args) do
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
15
|
+
if POSTGRES_SOCKETS[self].nil?
|
16
|
+
POSTGRES_SOCKETS[self] = IO::open(socket)
|
17
|
+
end
|
18
|
+
socket_object = POSTGRES_SOCKETS[self]
|
19
|
+
result = await(Promise.new do |resolve|
|
20
|
+
count = 0
|
21
|
+
EventLoop.register(socket_object, :rw) do
|
22
|
+
begin
|
23
|
+
if (count == 0)
|
24
|
+
# Writable
|
25
|
+
unless is_busy
|
26
|
+
send_query(sql)
|
27
|
+
count += 1
|
28
|
+
end
|
29
|
+
else
|
30
|
+
# Readable
|
31
|
+
EventLoop.deregister(socket_object)
|
32
|
+
resolve.call(get_result)
|
33
|
+
end
|
34
|
+
rescue => e
|
35
|
+
resolve.call(PromiseException.new(e))
|
20
36
|
end
|
21
37
|
end
|
22
38
|
end)
|
23
|
-
|
24
|
-
await(Promise.new do |resolve|
|
25
|
-
consume_input
|
26
|
-
EventLoop.register(socket_object, :r) do
|
27
|
-
EventLoop.deregister(socket_object)
|
28
|
-
resolve.call(get_result)
|
29
|
-
end
|
30
|
-
end)
|
31
39
|
end
|
32
40
|
end
|
33
41
|
end
|
data/lib/midori/runner.rb
CHANGED
@@ -13,6 +13,7 @@ class Midori::Runner
|
|
13
13
|
@bind = configure.bind
|
14
14
|
@port = configure.port
|
15
15
|
@api = ((api.is_a?Midori::APIEngine) ? api : Midori::APIEngine.new(api, configure.route_type))
|
16
|
+
@before = configure.before
|
16
17
|
end
|
17
18
|
|
18
19
|
# Get Midori server whether running
|
@@ -33,6 +34,9 @@ class Midori::Runner
|
|
33
34
|
connection = Midori::Connection.new(socket)
|
34
35
|
connection.server_initialize(@api, @logger)
|
35
36
|
end
|
37
|
+
async_fiber(Fiber.new do
|
38
|
+
@before.call
|
39
|
+
end)
|
36
40
|
EventLoop.start
|
37
41
|
nil
|
38
42
|
end
|
data/lib/midori/server.rb
CHANGED
@@ -43,7 +43,7 @@ module Midori::Server
|
|
43
43
|
@logger.info "#{@request.ip} - - \"#{@request.method} #{@request.path} HTTP/#{@request.protocol.join('.')}\" #{@response.status} #{(now_time.to_f - start_time.to_f).round(6)}".green
|
44
44
|
rescue
|
45
45
|
close_connection
|
46
|
-
@logger.
|
46
|
+
@logger.warn "#{@request.ip} - - Reached an EOF Error".yellow
|
47
47
|
end
|
48
48
|
end)
|
49
49
|
end.call
|
data/lib/midori/version.rb
CHANGED
@@ -37,7 +37,7 @@ It's hard to say that if it is possible for running on other ruby implementation
|
|
37
37
|
|
38
38
|
```
|
39
39
|
$ gem install em-midori
|
40
|
-
Successfully installed em-midori-0.1.
|
40
|
+
Successfully installed em-midori-0.1.12
|
41
41
|
1 gem installed
|
42
42
|
```
|
43
43
|
|
@@ -50,7 +50,7 @@ $ ruby -r "midori" -e "class A < Midori::API;end;Midori::Runner.new(A).start"
|
|
50
50
|
If you see the following message, then everything now works fine.
|
51
51
|
|
52
52
|
```
|
53
|
-
Midori 0.1.
|
53
|
+
Midori 0.1.12 is now running on 127.0.0.1:8080
|
54
54
|
```
|
55
55
|
|
56
56
|
## Use Bundler
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
## Basic Usage
|
4
4
|
|
5
|
-
Routes should be defined inside a class inherited from `Midori::API`. Midori doesn't support defining routes
|
5
|
+
Routes should be defined inside a class inherited from `Midori::API`. Midori doesn't support defining routes globally like sinatra to avoid scope pollution, which affects a lot in scaling project.
|
6
6
|
|
7
7
|
In midori, a route is an HTTP method with a URL-matching pattern. Each route is associated with a block:
|
8
8
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: em-midori
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- HeckPsi Lab
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-05-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: nio4r
|
@@ -30,14 +30,14 @@ dependencies:
|
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '0
|
33
|
+
version: '1.0'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '0
|
40
|
+
version: '1.0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: midori_http_parser
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -59,7 +59,9 @@ executables: []
|
|
59
59
|
extensions: []
|
60
60
|
extra_rdoc_files: []
|
61
61
|
files:
|
62
|
+
- ".editorconfig"
|
62
63
|
- LICENSE
|
64
|
+
- em-midori.sublime-project
|
63
65
|
- lib/midori.rb
|
64
66
|
- lib/midori/api.rb
|
65
67
|
- lib/midori/api_engine.rb
|
@@ -135,7 +137,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
135
137
|
version: '0'
|
136
138
|
requirements: []
|
137
139
|
rubyforge_project:
|
138
|
-
rubygems_version: 2.6.
|
140
|
+
rubygems_version: 2.6.10
|
139
141
|
signing_key:
|
140
142
|
specification_version: 4
|
141
143
|
summary: High performance ruby web framework
|