em-midori 0.2.0 → 0.2.1

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: d890861f5486fd8c8ecd3dff2a3780a26af42340
4
- data.tar.gz: 1d6ddf047c3534998eb6637cfbe387d56f1e86f2
3
+ metadata.gz: e5a62c03f0e31bd0ea7466d2ddda81f2fbdd8efd
4
+ data.tar.gz: c16d4d64ce2fd066ccd7bef0546bd07a816a7ac0
5
5
  SHA512:
6
- metadata.gz: 2664bb10cda5ab00f264bd91e633315ab2f05fb44218050597fc61c34890fa00bf042d3a476e24711415b9eb8d28e2a4b94f2225bb307f1f1e77c1fffde468d6
7
- data.tar.gz: 884cce78c3c28f9014823b45d03529082d7ff4c6832be0bfaa490265a08a7a05ad2b3ed7d5447074edbb6d3e06d32a0006004116afece1b442511f417583d33e
6
+ metadata.gz: d8c6e274f821b8f2f4f3ef746e98b1b5efe2d1774d67a55e7083271ab5fb51928e71cdb2df4f19fe2a7e5d7ac62293ce728525b87b3d76ff2ac37e4f6b95d18c
7
+ data.tar.gz: ce6a571451d2a7647872135c2546fc097fb86667b4888b5ddfe6cd54374989964bcc5530c58d8466401956ed4959bba6634bbb298b32ce63cedf88b852f63c78
data/lib/midori/api.rb CHANGED
@@ -303,6 +303,7 @@ class Midori::API
303
303
 
304
304
  # Add EVENTSOURCE method as a DSL for route definition
305
305
  # @param [String] path Accepts as part of path in route definition
306
+ # @yield what to run when route matched
306
307
  # @return [nil] nil
307
308
  # @example String as router
308
309
  # eventsource '/' do
@@ -1,8 +1,14 @@
1
+ ##
2
+ # States of a connection
1
3
  class Midori::Connection
2
4
  include Midori::Server
3
5
 
6
+ # @!attribute data
7
+ # @return [String] string buffer of data to send
4
8
  attr_accessor :data
5
9
 
10
+ # Init Connection with socket
11
+ # @param [IO] socket raw socket
6
12
  def initialize(socket)
7
13
  @registered = false
8
14
  @socket = socket
@@ -12,6 +18,8 @@ class Midori::Connection
12
18
  listen(socket)
13
19
  end
14
20
 
21
+ # Register events of connection
22
+ # @param [IO] socket raw socket
15
23
  def listen(socket)
16
24
  EventLoop.register(socket, :rw) do |monitor|
17
25
  @monitor = monitor
@@ -32,18 +40,20 @@ class Midori::Connection
32
40
  end
33
41
  end
34
42
 
43
+ # Send message to client
44
+ # @param [String] data data to send
35
45
  def send_data(data)
36
46
  @monitor.writable? ? @socket.write_nonblock(data) : @data << data
37
47
  end
38
48
 
49
+ # Close the connection
39
50
  def close_connection
40
51
  EventLoop.deregister @socket
41
52
  @socket.close
42
- rescue Errno::EBADF
43
- # Connection finished in advance
44
53
  end
45
54
 
55
+ # Close the connection after writing
46
56
  def close_connection_after_writing
47
57
  @close_flag = true
48
58
  end
49
- end
59
+ end
data/lib/midori/const.rb CHANGED
@@ -85,6 +85,7 @@ module Midori::Const
85
85
  'Connection' => 'Upgrade'
86
86
  }
87
87
 
88
+ # Array of Route Methods
88
89
  ROUTE_METHODS = %i(
89
90
  DELETE
90
91
  GET
@@ -6,6 +6,7 @@ module Configurable
6
6
  # @param [Symbol] option the name of config
7
7
  # @param [Object] value value to the name
8
8
  # @param [Boolean] read_only Generate option= method or not
9
+ # @return [nil] nil
9
10
  def set(option, value = (not_set = true), read_only = false)
10
11
  raise ArgumentError if not_set
11
12
 
@@ -22,6 +23,9 @@ module Configurable
22
23
  private
23
24
 
24
25
  # Dynamically defines a method on settings.
26
+ # @param [String] name method name
27
+ # @param [Proc] content method content
28
+ # @return [nil] nil
25
29
  def define_singleton(name, content = Proc.new)
26
30
  singleton_class.class_eval do
27
31
  undef_method(name) if method_defined? name
@@ -1,59 +1,75 @@
1
- require 'timeout'
2
-
1
+ ##
2
+ # EventLoop Module, providing main loop for events
3
3
  module EventLoop
4
4
  class << self
5
+ # Raw NIO Selector
5
6
  SELECTOR = NIO::Selector.new
7
+ # Array of active timers
6
8
  TIMERS = []
9
+ # Hash of io and its callback
7
10
  IOS = Hash.new
11
+ # IO queue
8
12
  QUEUE = Hash.new
9
13
 
14
+ # Add timer in event loop
15
+ # @param [EventLoop::Timer] timer timer to insert
16
+ # @return [nil] nil
10
17
  def add_timer(timer)
11
18
  timer.start_time = Time.now.to_f + timer.time
12
19
  TIMERS << timer
20
+ nil
13
21
  end
14
22
 
15
- def register(io, interest=(:rw), timeout=nil, resolve=nil, &callback)
23
+ # Register I/O event with queue protection
24
+ # @param [IO] io io to register
25
+ # @param [Symbol] interest :r for read only, :w for write only, and :rw for both
26
+ # @yield what to run when io callbacks
27
+ # @return [nil] nil
28
+ def register(io, interest=(:rw), &callback)
16
29
  if QUEUE[io.to_i].nil?
17
30
  QUEUE[io.to_i] = Array.new
18
- register_raw(io, interest, timeout, resolve, callback)
31
+ register_raw(io, interest, callback)
19
32
  else
20
- QUEUE[io.to_i] << [io, interest, timeout, resolve, callback]
33
+ QUEUE[io.to_i] << [io, interest, callback]
21
34
  end
35
+ nil
22
36
  end
23
37
 
24
- def register_raw(io, interest=(:rw), timeout=nil, resolve=nil, callback)
38
+ # Register I/O event directly, without any queue protection
39
+ # @param [IO] io io to register
40
+ # @param [Symbol] interest :r for read only, :w for write only, and :rw for both
41
+ # @param [Proc] callback what to run when io callbacks
42
+ # @return [nil] nil
43
+ def register_raw(io, interest=(:rw), callback)
25
44
  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,
37
- callback: callback,
38
- }
45
+ IOS[io] = { callback: callback }
46
+ nil
39
47
  end
40
48
 
49
+ # Deregister I/O event
50
+ # @param [IO] io io to deregister
51
+ # @return [nil] nil
41
52
  def deregister(io)
42
53
  fd = io.to_i
43
54
  SELECTOR.deregister(io)
44
55
  IOS.delete(io)
45
56
  next_register = QUEUE[fd].shift
46
57
  next_register.nil? ? QUEUE.delete(fd) : register_raw(*next_register)
58
+ nil
47
59
  end
48
60
 
61
+ # Run I/O selector once
62
+ # @return [nil] nil
49
63
  def run_once
50
64
  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
65
  IOS[monitor.io][:callback].call(monitor)
53
66
  end
54
67
  EventLoop.timer_once
68
+ nil
55
69
  end
56
70
 
71
+ # Run timer once
72
+ # @return [nil] nil
57
73
  def timer_once
58
74
  now_time = Time.now.to_f
59
75
  TIMERS.delete_if do |timer|
@@ -62,8 +78,11 @@ module EventLoop
62
78
  true
63
79
  end
64
80
  end
81
+ nil
65
82
  end
66
83
 
84
+ # Start the event loop
85
+ # @return [nil] nil
67
86
  def start
68
87
  return if running?
69
88
  @stop = false
@@ -73,10 +92,15 @@ module EventLoop
73
92
  @stop = nil
74
93
  end
75
94
 
95
+ # Set the stop flag
96
+ # @return [nil] nil
76
97
  def stop
77
98
  @stop = true
99
+ nil
78
100
  end
79
101
 
102
+ # Detect the stop flag
103
+ # @return [Boolean] return if eventloop is set to be stopped
80
104
  def running?
81
105
  @stop = true if @stop.nil?
82
106
  !@stop
@@ -17,6 +17,8 @@ class Promise
17
17
  end
18
18
 
19
19
  module Kernel
20
+ # Make fiber as async chain
21
+ # @param [Fiber] fiber root of async chain
20
22
  def async_fiber(fiber)
21
23
  chain = proc do |result|
22
24
  next unless result.is_a? Promise
@@ -53,9 +55,16 @@ module Kernel
53
55
  end
54
56
  end
55
57
 
58
+
59
+ ##
60
+ # Exceptions for Promises
61
+ # @!attribute [r] payload
62
+ # @return [Exception] raw execption
56
63
  class PromiseException < Exception
57
64
  attr_reader :payload
65
+ # Init PromiseException with existed Exception
66
+ # @param [Exception] payload raw execption
58
67
  def initialize(payload)
59
68
  @payload = payload
60
69
  end
61
- end
70
+ end
@@ -2,6 +2,7 @@ module Kernel
2
2
  # Raise error if Load Failed
3
3
  # @param [String] file file to Load
4
4
  # @param [String] prompt To prompt what when load error
5
+ # @return [Boolean] whether it has been required already
5
6
  def safe_require(file, prompt)
6
7
  begin
7
8
  require file
@@ -1,10 +1,22 @@
1
+ ##
2
+ # Timer Object in EventLoop
3
+ # @!attribute [r] time
4
+ # @return [Float] timeout length
5
+ # @!attribute [r] callback
6
+ # @return [Proc] proc to call when callbacks
7
+ # @!attribute start_time
8
+ # @return [Float] when timer should callbacks
1
9
  class EventLoop::Timer
2
- attr_reader :time, :start_time, :callback
10
+
11
+ attr_reader :time, :callback
3
12
  attr_accessor :start_time
4
13
 
14
+ # Init a timer with a time period and callback
15
+ # @param [Float] time timeout length
16
+ # @yield proc to call when callbacks
5
17
  def initialize(time, &callback)
6
18
  @time = time
7
19
  @callback = callback
8
20
  @start_time = Float::INFINITY
9
21
  end
10
- end
22
+ end
@@ -1,8 +1,14 @@
1
+ ##
2
+ # Midori Extension of File reading and writing
1
3
  class Midori::File
4
+ # Init File object
5
+ # @param [Array] args same args like File.new
2
6
  def initialize(*args)
3
7
  @file = File.new(*args)
4
8
  end
5
9
 
10
+ # read file
11
+ # @return [String] string readed
6
12
  def read
7
13
  await(Promise.new do |resolve|
8
14
  data = ''
@@ -17,6 +23,8 @@ class Midori::File
17
23
  end)
18
24
  end
19
25
 
26
+ # write file
27
+ # @param [String] data string to be written
20
28
  def write(data)
21
29
  await(Promise.new do |resolve|
22
30
  written = 0
@@ -30,11 +38,14 @@ class Midori::File
30
38
  end)
31
39
  end
32
40
 
41
+ # raw file object
42
+ # @return [File] file
33
43
  def raw
34
44
  @file
35
45
  end
36
46
 
47
+ # Close the file
37
48
  def close
38
49
  @file.close
39
50
  end
40
- end
51
+ end
@@ -1,15 +1,25 @@
1
+ ##
2
+ # Meta-programming hiredis for redis async extension
1
3
  module Hiredis
2
4
  require 'hiredis/connection'
3
5
  # Overwrite with ruby implementation to hook IO
4
6
  require 'hiredis/ruby/connection'
5
7
  require 'hiredis/ruby/reader'
8
+ # Redis Connection
6
9
  Connection = Ruby::Connection
10
+ # Redis Result Reader
7
11
  Reader = Ruby::Reader
8
- end
9
12
 
10
- module Hiredis
13
+ ##
14
+ # Meta-programming hiredis for redis async extension
11
15
  module Ruby
16
+ ##
17
+ # Meta-programming hiredis for redis async extension
12
18
  class Connection
19
+ # write message directly
20
+ # @param [IO] _sock raw socket
21
+ # @param [String] data generated string data
22
+ # @param [Float] _timeout operation timeout
13
23
  def _write(_sock, data, _timeout)
14
24
  await(Promise.new do |resolve|
15
25
  data.force_encoding('binary') if data.respond_to?(:force_encoding)
@@ -24,6 +34,8 @@ module Hiredis
24
34
  end)
25
35
  end
26
36
 
37
+ # read from redis socket
38
+ # @return [String] reply
27
39
  def read
28
40
  raise 'not connected' unless connected?
29
41
  await(Promise.new do |resolve|
@@ -44,4 +56,4 @@ module Hiredis
44
56
  end
45
57
  end
46
58
  end
47
- end
59
+ end
@@ -1,6 +1,10 @@
1
1
  require 'net/protocol'
2
2
 
3
+ ##
4
+ # Meta programming Net class for async HTTP and FTP connection
3
5
  class Net::BufferedIO
6
+ # Wait till io finishes
7
+ # @param [Symbol] interest
4
8
  def wait_io(interest)
5
9
  await(Promise.new do |resolve|
6
10
  io = @io.to_io
@@ -11,6 +15,7 @@ class Net::BufferedIO
11
15
  end)
12
16
  end
13
17
 
18
+ # Fill until the operation finishes
14
19
  def rbuf_fill
15
20
  loop do
16
21
  case rv = @io.read_nonblock(BUFSIZE, exception: false)
@@ -34,4 +39,4 @@ class Net::BufferedIO
34
39
  end
35
40
  end
36
41
  end
37
- end
42
+ end
@@ -1,14 +1,23 @@
1
1
  safe_require 'sequel', 'gem install sequel'
2
2
  require 'sequel/adapters/mysql2'
3
3
 
4
+ # Management of MySQL Sockets
4
5
  MYSQL_SOCKETS = {}
5
6
 
7
+ ##
8
+ # Meta-programming Sequel for async extensions
6
9
  module Sequel
10
+ # Midori Extension of sequel MySQL through meta programming
7
11
  module Mysql2
12
+ # Midori Extension of sequel MySQL through meta programming
8
13
  class Database
9
14
  # Execute the given SQL on the given connection. If the :type
10
15
  # option is :select, yield the result of the query, otherwise
11
16
  # yield the connection if a block is given.
17
+ # @param [Mysql2::Client] conn connection to database
18
+ # @param [String] sql sql query
19
+ # @param [Hash] opts optional options
20
+ # @return [Mysql2::Result] MySQL results
12
21
  def _execute(conn, sql, opts) # rubocop:disable Metrics/MethodLength, Metrics/CyclomaticComplexity
13
22
  begin
14
23
  # :nocov:
@@ -44,15 +53,15 @@ module Sequel
44
53
  socket = MYSQL_SOCKETS[conn.socket]
45
54
  await(Promise.new do |resolve|
46
55
  count = 0
47
- EventLoop.register(socket, :rw, 2, resolve) do
56
+ EventLoop.register(socket, :rw) do
48
57
  if (count == 0)
49
58
  # Writable
50
59
  count += 1
51
60
  conn.query(sql,
52
- database_timezone: timezone,
53
- application_timezone: Sequel.application_timezone,
54
- stream: stream,
55
- async: true)
61
+ database_timezone: timezone,
62
+ application_timezone: Sequel.application_timezone,
63
+ stream: stream,
64
+ async: true)
56
65
  else
57
66
  # Readable
58
67
  begin
@@ -1,6 +1,7 @@
1
1
  safe_require 'sequel', 'gem install sequel'
2
2
  require 'sequel/adapters/postgres'
3
3
 
4
+ # Management of Postgres Sockets
4
5
  POSTGRES_SOCKETS = {}
5
6
 
6
7
  ##
@@ -11,31 +12,31 @@ class Sequel::Postgres::Adapter
11
12
  # @param [Array] args args to send
12
13
  # @return [Array] sql query result
13
14
  def execute_query(sql, args)
14
- @db.log_connection_yield(sql, self, args) do
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)
15
+ @db.log_connection_yield(sql, self, args) do
16
+ if POSTGRES_SOCKETS[self].nil?
17
+ POSTGRES_SOCKETS[self] = IO::open(socket)
18
+ end
19
+ socket_object = POSTGRES_SOCKETS[self]
20
+ await(Promise.new do |resolve|
21
+ count = 0
22
+ EventLoop.register(socket_object, :rw) do
23
+ begin
24
+ if (count == 0)
25
+ # Writable
26
+ unless is_busy
27
+ send_query(sql)
28
+ count += 1
33
29
  end
34
- rescue => e
35
- resolve.call(PromiseException.new(e))
30
+ else
31
+ # Readable
32
+ EventLoop.deregister(socket_object)
33
+ resolve.call(get_result)
36
34
  end
35
+ rescue => e
36
+ resolve.call(PromiseException.new(e))
37
37
  end
38
- end)
39
- end
38
+ end
39
+ end)
40
+ end
40
41
  end
41
42
  end
@@ -1,5 +1,5 @@
1
1
  # Midori Module
2
2
  module Midori
3
3
  # Current Version Code
4
- VERSION = '0.2.0'.freeze
4
+ VERSION = '0.2.1'.freeze
5
5
  end
data/tutorial/README.md CHANGED
@@ -8,4 +8,4 @@ If you want to know how midori compares to other libraries/frameworks, checkout
8
8
 
9
9
  ## Note
10
10
 
11
- The official guide assumes intermediate level knowledge of Ruby and backend development. If you are totally new , it might not be the best idea to jump right into a framework as your first step - grasp the basics then come back! Prior experience with other frameworks like Rails helps, but is not required.
11
+ The official guide assumes intermediate level knowledge of Ruby and backend development. If you are totally new , it might not be the best idea to jump right into a framework as your first step - grasp the basics then come back! Prior experience with other frameworks like Rails helps, but is not required.
data/tutorial/SUMMARY.md CHANGED
@@ -25,4 +25,4 @@
25
25
 
26
26
  - [Comparison with Other Frameworks](meta/comparison_with_other_frameworks.md)
27
27
  - [Next Steps](meta/next_steps.md)
28
- - [Join the Midori Community](meta/join_the_midori_community.md)
28
+ - [Join the Midori Community](meta/join_the_midori_community.md)
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.2.0
4
+ version: 0.2.1
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-05-01 00:00:00.000000000 Z
11
+ date: 2017-05-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: nio4r