em-midori 0.2.0 → 0.2.1

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 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