plux 0.1.3 → 0.1.8

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
  SHA256:
3
- metadata.gz: 472f8a38bccdb6c63b10b4291c4cd109598e8819222c4061dd673f3491d58344
4
- data.tar.gz: 489ce27db397a3df71058642b8f3dab80ac255cf1ace82f66c12d80980de4efc
3
+ metadata.gz: ccf41ebecbdaa05e45295b9a3237cf72710d435459c4031b8d19c3ce1806165f
4
+ data.tar.gz: 61ab35e88507321b06de9c1c4e9fabcfdabfd1c7d5333bcb1cf7b1195b6a9b10
5
5
  SHA512:
6
- metadata.gz: 565721905d9e193557d56c78a323f35bd41e1650bb7592607534a6da3cf9f961d66801b2a169477f9b3b2019f06d45e1e08bcda6b146d855d5018b11ba5a6231
7
- data.tar.gz: 32d1c59b0a5b169e9ed33302d576dc3d87e42ba376d9f927f61a34d1f5b8bcdf44582fe11a547de0d62c1827158248dfb6293df8fd06cdaa5716f23bcb313741
6
+ metadata.gz: 8ddb55b3ab4d9a5544ba0ba3780d30a63decab60197cc97ea431d68d313bc6c9a0e91b17dfa9cf54f25848eee10f2ade27e5790d5f454a13bc063759811bf729
7
+ data.tar.gz: 4cda0ff1be89717a676b5622e221a227d426cbc08ede6bb86faf4bc8a0e12c525965a5eafcb29f90f345ec8f3627946ba5e2f2f0ca09d553926e1ebf80f6e186
@@ -1,7 +1,8 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- plux (0.1.3)
4
+ plux (0.1.6)
5
+ nio4r (~> 2.0)
5
6
 
6
7
  GEM
7
8
  remote: https://rubygems.org/
@@ -9,6 +10,7 @@ GEM
9
10
  coderay (1.1.2)
10
11
  method_source (0.9.2)
11
12
  minitest (5.14.1)
13
+ nio4r (2.5.4)
12
14
  pry (0.12.2)
13
15
  coderay (~> 1.1.0)
14
16
  method_source (~> 0.9.0)
data/README.md CHANGED
@@ -21,32 +21,57 @@ Or install it yourself as:
21
21
  ## Usage
22
22
 
23
23
  ```ruby
24
- # start one and only process named 'abc',
24
+ # start one and only process named 'abc', with 2 threads in it (1 thread if not specified),
25
25
  # no matter the code below is called how many times in whatever processes/threads
26
- server = Plux.worker(:abc) do
26
+ server = Plux.worker(:abc, thread: 2) do
27
27
 
28
- # prepare resources like mq/db, to handle requests
29
- def initialize
28
+ # prepare thread-safe resources like mq/db, to handle requests
29
+ def prepare
30
30
  # @db = ...
31
31
  end
32
32
 
33
33
  # threads call this method to deal with clients' message
34
- def work(msg)
34
+ def process(msg)
35
35
  # @db << parse(msg)
36
36
  end
37
37
  end
38
38
 
39
- # five threads will be started to handle these clients,
40
- # and finished once their counterparts call close
39
+ # clients connect, send msg, and close concurrently
41
40
  5.times do |n|
42
41
  Thread.new do
43
42
  client = server.connect
44
- client.puts "hello #{n}"
43
+ client.puts "hello"
44
+ client.puts "my name is #{n}"
45
45
  client.close
46
46
  end
47
47
  end
48
48
  ```
49
49
 
50
+ Also, you can boot multiple servers(processes) with same logic:
51
+
52
+ ```ruby
53
+ class AwesomeServer < Plux::Engine
54
+ # prepare thread-safe resources like mq/db, to handle requests
55
+ def prepare
56
+ # @db = ...
57
+ end
58
+
59
+ # threads call this method to deal with clients' message
60
+ def process(msg)
61
+ # @db << parse(msg)
62
+ end
63
+ end
64
+
65
+ a = AwesomeServer.new(:a)
66
+ b = AwesomeServer.new(:b)
67
+ c = AwesomeServer.new(:c, thread: 4)
68
+
69
+ a_client = a.connect
70
+ b_client = b.connect
71
+ c_client = c.connect
72
+ c_client_2 = c.connect
73
+ ```
74
+
50
75
  ## Development
51
76
 
52
77
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
@@ -4,6 +4,7 @@ require "plux/version"
4
4
  require "plux/server"
5
5
  require "plux/client"
6
6
  require "plux/parser"
7
+ require "plux/engine"
7
8
 
8
9
 
9
10
  module Plux
@@ -32,10 +33,12 @@ module Plux
32
33
  File.join(dir, "#{server_name}.so")
33
34
  end
34
35
 
35
- def worker(name, &block)
36
- Server.new(name).boot(block)
36
+ def worker(name, thread: 1, &block)
37
+ worker = Class.new(&block).new
38
+ Server.new(name, thread: thread).boot(worker)
37
39
  end
38
40
  end
39
41
 
40
42
  FileUtils.mkdir_p(self.dir)
43
+
41
44
  end
@@ -0,0 +1,21 @@
1
+ module Plux
2
+ class Engine
3
+
4
+ attr_reader :name
5
+
6
+ def initialize(name, thread: 1)
7
+ @name = name
8
+ @server = Server.new(name, thread: thread).boot(self)
9
+ end
10
+
11
+ def connect
12
+ @server.connect
13
+ end
14
+
15
+ def prepare
16
+ end
17
+
18
+ def process(msg)
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,76 @@
1
+ module Plux
2
+ class Reactor
3
+ def initialize(count, worker)
4
+ @worker = worker
5
+ @msg_q = Queue.new
6
+ @count = count
7
+
8
+ @nio = NIO::Selector.new
9
+ @newly_accepted = Queue.new
10
+ @closed = []
11
+
12
+ receive
13
+ process
14
+ end
15
+
16
+ def register(socket)
17
+ @newly_accepted << socket
18
+ @nio.wakeup
19
+ end
20
+
21
+ private
22
+
23
+ def receive
24
+ Thread.new do
25
+ loop do
26
+ @closed.size.times{ @nio.deregister(@closed.pop) }
27
+
28
+ @newly_accepted.size.times do
29
+ socket = @newly_accepted.pop
30
+ mon = @nio.register(socket, :r)
31
+ mon.value = Worker.new(socket, @msg_q)
32
+ end
33
+
34
+ @nio.select do |m|
35
+ next if m.value.process
36
+ @closed << m.io
37
+ end
38
+ end
39
+ end
40
+ end
41
+
42
+ def process
43
+ @count.times.each do
44
+ Thread.new do
45
+ loop{ @worker.process(@msg_q.deq) }
46
+ end
47
+ end
48
+ end
49
+
50
+ class Worker
51
+ def initialize(socket, q)
52
+ @parser = Parser.new
53
+ @socket = socket
54
+ @q = q
55
+ end
56
+
57
+ def process
58
+ stream = @socket.read_nonblock(Parser::STREAM_MAX_LEN, exception: false)
59
+ return true if stream == :wait_readable
60
+
61
+ msgs = @parser.decode(stream)
62
+ last_msg = msgs.pop
63
+
64
+ msgs.each{ |msg| @q << msg }
65
+ if last_msg == Parser::LAST_MSG
66
+ @socket.close
67
+ return false
68
+ end
69
+ @q << last_msg
70
+
71
+ true
72
+ end
73
+ end
74
+
75
+ end
76
+ end
@@ -1,3 +1,6 @@
1
+ require "nio"
2
+ require "plux/reactor"
3
+
1
4
  module Plux
2
5
 
3
6
  class Server
@@ -6,13 +9,14 @@ module Plux
6
9
  Active = {}
7
10
  at_exit{ Active.values.each(&:close) }
8
11
 
9
- def initialize(name)
12
+ def initialize(name, thread: )
10
13
  @name = name
14
+ @thread = thread
11
15
  end
12
16
 
13
- def boot(block)
17
+ def boot(worker)
14
18
  Plux.lock_pid_file(name) do |file|
15
- start_server_if_not_pid(file, block)
19
+ start_server_if_not_pid(file, worker)
16
20
  end
17
21
  self
18
22
  end
@@ -27,7 +31,7 @@ module Plux
27
31
 
28
32
  private
29
33
 
30
- def start_server_if_not_pid(file, block)
34
+ def start_server_if_not_pid(file, worker)
31
35
  @pid = file.read.to_i
32
36
  return unless pid == 0
33
37
 
@@ -39,11 +43,9 @@ module Plux
39
43
  child.close
40
44
  UNIXServer.open(Plux.server_file(name)) do |serv|
41
45
  parent.close
42
- worker = Class.new(&block).new
43
- loop do
44
- socket = serv.accept
45
- Worker.new(socket, worker)
46
- end
46
+ worker.prepare
47
+ reactor = Reactor.new(@thread, worker)
48
+ loop{ reactor.register(serv.accept) }
47
49
  end
48
50
  end
49
51
 
@@ -62,31 +64,6 @@ module Plux
62
64
  File.delete(Plux.send(file, name))
63
65
  end
64
66
  end
65
-
66
- class Worker
67
- def initialize(socket, worker)
68
- par = Parser.new
69
- t = Thread.new do
70
- loop do
71
- begin
72
- stream = socket.read_nonblock(Parser::STREAM_MAX_LEN)
73
- rescue IO::WaitReadable
74
- IO.select([socket])
75
- retry
76
- end
77
-
78
- msgs = par.decode(stream)
79
- last_msg = msgs.pop
80
-
81
- msgs.each{ |msg| worker.work(msg) }
82
- break if last_msg == Parser::LAST_MSG
83
- worker.work(last_msg)
84
- end
85
- socket.close
86
- end
87
- end
88
- end
89
-
90
67
  end
91
68
 
92
69
  end
@@ -1,3 +1,3 @@
1
1
  module Plux
2
- VERSION = "0.1.3"
2
+ VERSION = "0.1.8"
3
3
  end
@@ -23,4 +23,6 @@ Gem::Specification.new do |spec|
23
23
  spec.add_development_dependency "rake", "~> 10.0"
24
24
  spec.add_development_dependency "minitest", "~> 5.0"
25
25
  spec.add_development_dependency "pry"
26
+
27
+ spec.add_dependency "nio4r", "~> 2.0"
26
28
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: plux
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.1.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - ken
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-09-13 00:00:00.000000000 Z
11
+ date: 2020-10-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -66,6 +66,20 @@ dependencies:
66
66
  - - ">="
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: nio4r
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '2.0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '2.0'
69
83
  description:
70
84
  email:
71
85
  - block24block@gmail.com
@@ -85,7 +99,9 @@ files:
85
99
  - bin/setup
86
100
  - lib/plux.rb
87
101
  - lib/plux/client.rb
102
+ - lib/plux/engine.rb
88
103
  - lib/plux/parser.rb
104
+ - lib/plux/reactor.rb
89
105
  - lib/plux/server.rb
90
106
  - lib/plux/version.rb
91
107
  - plux.gemspec