em-midori 0.1.12 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4ad463d2a5c54f9995812d347d0f428752414d77
4
- data.tar.gz: 9a9ea6eb52f59bf540e7dc37d24a6581393a439d
3
+ metadata.gz: d890861f5486fd8c8ecd3dff2a3780a26af42340
4
+ data.tar.gz: 1d6ddf047c3534998eb6637cfbe387d56f1e86f2
5
5
  SHA512:
6
- metadata.gz: bf12420ff582c13a143a872462284f3232472decff29a686286d931eb5fac60371182a313e0327c41281eea5a8a673913dd59eeebf560a8ecc99a4245aeaca9b
7
- data.tar.gz: b40da8f51f4c39e5b9dd46a5944c17b0672425ffa5869a14a5880df85d0ce9bd92c19daa7433131624e4b93308ecf69d09f8c0e5afb3c0edcc3b4111957c3066
6
+ metadata.gz: 2664bb10cda5ab00f264bd91e633315ab2f05fb44218050597fc61c34890fa00bf042d3a476e24711415b9eb8d28e2a4b94f2225bb307f1f1e77c1fffde468d6
7
+ data.tar.gz: 884cce78c3c28f9014823b45d03529082d7ff4c6832be0bfaa490265a08a7a05ad2b3ed7d5447074edbb6d3e06d32a0006004116afece1b442511f417583d33e
data/.editorconfig ADDED
@@ -0,0 +1,9 @@
1
+ root = true
2
+
3
+ [*]
4
+ end_of_line = lf
5
+ insert_final_newline = true
6
+
7
+ [*.rb]
8
+ indent_style = space
9
+ indent_size = 2
@@ -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
+ }
@@ -39,6 +39,8 @@ class Midori::Connection
39
39
  def close_connection
40
40
  EventLoop.deregister @socket
41
41
  @socket.close
42
+ rescue Errno::EBADF
43
+ # Connection finished in advance
42
44
  end
43
45
 
44
46
  def close_connection_after_writing
@@ -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
- monitor = SELECTOR.register(io, interest)
15
- monitor.value = {
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 1 secs
27
- monitor.value[:timer].stop unless monitor.value[:timer].nil?
28
- monitor.value[:callback].call(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
@@ -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
- EventLoop.register(@io.to_io, interest) do
7
- EventLoop.deregister(@io.to_io)
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
- socket = IO::open(conn.socket)
40
- await(Promise.new do |resolve|
41
- EventLoop.register(socket, :w) do
42
- EventLoop.deregister(socket)
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
- EventLoop.register(socket, :r) do
53
- EventLoop.deregister(socket)
54
- resolve.call(conn.async_result)
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
- socket_object = IO.for_fd(socket)
14
- await(Promise.new do |resolve|
15
- EventLoop.register(socket_object, :w) do
16
- unless is_busy
17
- EventLoop.deregister(socket_object)
18
- send_query(sql)
19
- resolve.call
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.error "#{@request.ip} - - Reached an EOF Error".red
46
+ @logger.warn "#{@request.ip} - - Reached an EOF Error".yellow
47
47
  end
48
48
  end)
49
49
  end.call
@@ -1,5 +1,5 @@
1
1
  # Midori Module
2
2
  module Midori
3
3
  # Current Version Code
4
- VERSION = '0.1.12'.freeze
4
+ VERSION = '0.2.0'.freeze
5
5
  end
@@ -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.7
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.7 is now running on 127.0.0.1:8080
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 globally like sinatra to avoid scope pollution, which affects a lot in scaling project.
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.1.12
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-02-25 00:00:00.000000000 Z
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.4'
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.4'
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.8
140
+ rubygems_version: 2.6.10
139
141
  signing_key:
140
142
  specification_version: 4
141
143
  summary: High performance ruby web framework