io_request 1.2.0 → 2.0.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/.gitignore +10 -8
- data/.rubocop.yml +37 -0
- data/.rubocop_todo.yml +7 -0
- data/Gemfile +13 -4
- data/README.md +31 -39
- data/Rakefile +31 -10
- data/bin/console +15 -14
- data/examples/simple_example.rb +12 -10
- data/io_request.gemspec +23 -21
- data/lib/io_request.rb +30 -8
- data/lib/io_request/authorizer.rb +42 -0
- data/lib/io_request/client.rb +171 -158
- data/lib/io_request/message.rb +67 -85
- data/lib/io_request/utility/multi_thread.rb +64 -0
- data/lib/io_request/utility/with_id.rb +60 -0
- data/lib/io_request/utility/with_prog_name.rb +14 -0
- data/lib/io_request/version.rb +3 -1
- metadata +25 -22
- data/Gemfile.lock +0 -29
- data/lib/io_request/logging.rb +0 -49
- data/lib/io_request/utility.rb +0 -104
data/lib/io_request/message.rb
CHANGED
@@ -1,112 +1,94 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module IORequest
|
2
|
-
#
|
4
|
+
# Single message. Either request or response.
|
3
5
|
class Message
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
# @return [Hash] stored data.
|
9
|
-
attr_reader :data
|
6
|
+
include Utility::WithID
|
7
|
+
# Types of messages.
|
8
|
+
TYPES = %i[request response].freeze
|
10
9
|
|
11
|
-
#
|
12
|
-
#
|
10
|
+
# Create new message.
|
13
11
|
# @param data [Hash]
|
14
|
-
# @param
|
15
|
-
#
|
16
|
-
|
17
|
-
|
12
|
+
# @param type [Symbol] one of {TYPES} member.
|
13
|
+
# @param id [Utility::ExtendedID, String, nil] only should be filled if message is received from outside.
|
14
|
+
# @param to [Utility::ExtendedID, String, nil] if message is response, it should include integer
|
15
|
+
# of original request.
|
16
|
+
def initialize(data, type: :request, id: nil, to: nil)
|
18
17
|
@data = data
|
19
|
-
|
18
|
+
@type = type
|
19
|
+
@id = id.nil? ? extended_id : Utility::ExtendedID.from(id)
|
20
|
+
@to = to.nil? ? nil : Utility::ExtendedID.from(to)
|
20
21
|
|
21
|
-
|
22
|
-
def to_s
|
23
|
-
"#{self.class.name}##{@id}: #{@data.inspect}"
|
22
|
+
check_data
|
24
23
|
end
|
25
24
|
|
26
|
-
#
|
27
|
-
def
|
28
|
-
|
25
|
+
# Check data correctness.
|
26
|
+
def check_data
|
27
|
+
raise '@data is not a hash' unless @data.is_a? Hash
|
28
|
+
raise 'incorrect @type' unless TYPES.include? @type
|
29
|
+
raise 'incorrect @id' unless @id.is_a? Utility::ExtendedID
|
30
|
+
raise '@to not specified for response' if response? && @to.nil?
|
29
31
|
end
|
30
|
-
end
|
31
|
-
|
32
|
-
# Request for server or client.
|
33
|
-
class Request < Message
|
34
|
-
# Amount of time to sleep before checking whether responded.
|
35
|
-
JOIN_SLEEP_TIME = 0.5
|
36
|
-
|
37
|
-
# @return [Integer, Response, nil] ID of response or response itself for this message.
|
38
|
-
attr_reader :response
|
39
32
|
|
40
|
-
#
|
41
|
-
|
33
|
+
# @return [Hash]
|
34
|
+
attr_reader :data
|
42
35
|
|
43
|
-
#
|
44
|
-
|
45
|
-
# @param data [Hash]
|
46
|
-
# @param response [Integer, Response, nil]
|
47
|
-
# @param id [Integer, nil]
|
48
|
-
def initialize(data, response = nil, id = nil)
|
49
|
-
@response = response
|
50
|
-
super(data, id)
|
51
|
-
end
|
36
|
+
# @return [Symbol]
|
37
|
+
attr_reader :type
|
52
38
|
|
53
|
-
# @return [
|
54
|
-
|
55
|
-
"#{super.to_s}; #{@response ? "Response ID: #{@response.to_i}" : "Not responded"}"
|
56
|
-
end
|
39
|
+
# @return [Utility::ExtendedID]
|
40
|
+
attr_reader :id
|
57
41
|
|
58
|
-
#
|
59
|
-
|
60
|
-
# @param timeout [Integer, Float, nil] timeout size or +nil+ if no timeout.
|
61
|
-
#
|
62
|
-
# @return [Integer] amount of time passed
|
63
|
-
def join(timeout = nil)
|
64
|
-
time_passed = 0
|
65
|
-
while @response.nil? && (timeout.nil? || time_passed < timeout)
|
66
|
-
time_passed += (sleep JOIN_SLEEP_TIME)
|
67
|
-
end
|
68
|
-
time_passed
|
69
|
-
end
|
42
|
+
# @return [Utility::ExtendedID]
|
43
|
+
attr_reader :to
|
70
44
|
|
71
|
-
#
|
72
|
-
def
|
73
|
-
|
45
|
+
# @return [Boolean]
|
46
|
+
def request?
|
47
|
+
@type == :request
|
74
48
|
end
|
75
49
|
|
76
|
-
#
|
77
|
-
def
|
78
|
-
|
50
|
+
# @return [Boolean]
|
51
|
+
def response?
|
52
|
+
@type == :response
|
79
53
|
end
|
80
|
-
end
|
81
54
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
# @param data [Hash]
|
90
|
-
# @param request [Integer, Request]
|
91
|
-
# @param id [Integer, nil]
|
92
|
-
def initialize(data, request, id = nil)
|
93
|
-
@request = request
|
94
|
-
super(data, id)
|
55
|
+
# @return [String]
|
56
|
+
def to_s
|
57
|
+
if request?
|
58
|
+
"Request##{@id}: #{data}"
|
59
|
+
else
|
60
|
+
"Response##{@id}: #{data} to ##{@to}"
|
61
|
+
end
|
95
62
|
end
|
96
63
|
|
97
|
-
# @return [String]
|
98
|
-
def
|
99
|
-
|
64
|
+
# @return [String] binary data to be passed over IO.
|
65
|
+
def to_binary
|
66
|
+
json_string = JSON.generate({
|
67
|
+
id: @id.to_s,
|
68
|
+
type: @type.to_s,
|
69
|
+
to: @to.to_s,
|
70
|
+
data: @data
|
71
|
+
})
|
72
|
+
[json_string.size, json_string].pack("Sa#{json_string.size}")
|
100
73
|
end
|
101
74
|
|
102
|
-
#
|
103
|
-
def
|
104
|
-
|
75
|
+
# @param io_w [:write]
|
76
|
+
def write_to(io_w)
|
77
|
+
io_w.write(to_binary)
|
105
78
|
end
|
106
79
|
|
107
|
-
#
|
108
|
-
|
109
|
-
|
80
|
+
# @param io_r [:read]
|
81
|
+
# @return [Message]
|
82
|
+
def self.read_from(io_r)
|
83
|
+
size = io_r.read(2).unpack1('S')
|
84
|
+
raise '0 size received' if size.zero?
|
85
|
+
|
86
|
+
json_string = io_r.read(size).unpack1("a#{size}")
|
87
|
+
msg = JSON.parse(json_string, symbolize_names: true)
|
88
|
+
Message.new(msg[:data],
|
89
|
+
id: msg[:id],
|
90
|
+
type: msg[:type].to_sym,
|
91
|
+
to: msg[:to])
|
110
92
|
end
|
111
93
|
end
|
112
94
|
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module IORequest
|
4
|
+
# Utility methods.
|
5
|
+
module Utility
|
6
|
+
# Adds some methods to spawn new threads and join them.
|
7
|
+
# @note This module creates instance variables with prefix +@__multi_thread__+.
|
8
|
+
module MultiThread
|
9
|
+
private
|
10
|
+
|
11
|
+
# @return [Array<Thread>] array of running threads.
|
12
|
+
def __multi_thread__threads
|
13
|
+
@__multi_thread__threads ||= []
|
14
|
+
end
|
15
|
+
alias running_threads __multi_thread__threads
|
16
|
+
|
17
|
+
# @return [Mutex] threads manipulations mutex.
|
18
|
+
def __multi_thread__mutex
|
19
|
+
@__multi_thread__mutex ||= Mutex.new
|
20
|
+
end
|
21
|
+
|
22
|
+
# Runs block with provided arguments forwarded as arguments in separate thread.
|
23
|
+
# All the inline args will be passed to block.
|
24
|
+
# @param thread_name [String] thread name.
|
25
|
+
# @return [Thread]
|
26
|
+
def in_thread(*args, name: nil)
|
27
|
+
# Synchronizing addition/deletion of new threads. That's important
|
28
|
+
__multi_thread__mutex.synchronize do
|
29
|
+
new_thread = Thread.new(*args) do |*in_args|
|
30
|
+
yield(*in_args)
|
31
|
+
ensure
|
32
|
+
__multi_thread__remove_current_thread
|
33
|
+
end
|
34
|
+
__multi_thread__threads << new_thread
|
35
|
+
new_thread.name = name if name
|
36
|
+
new_thread
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# Removes current thread from thread list.
|
41
|
+
def __multi_thread__remove_current_thread
|
42
|
+
__multi_thread__mutex.synchronize do
|
43
|
+
__multi_thread__threads.delete(Thread.current)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# For each running thread.
|
48
|
+
def each_thread(&block)
|
49
|
+
__multi_thread__threads.each(&block)
|
50
|
+
end
|
51
|
+
|
52
|
+
# Kills each thread.
|
53
|
+
def kill_threads
|
54
|
+
each_thread(&:kill)
|
55
|
+
each_thread(&:join)
|
56
|
+
end
|
57
|
+
|
58
|
+
# Joins each thread.
|
59
|
+
def join_threads
|
60
|
+
each_thread(&:join)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module IORequest
|
4
|
+
# Utility methods.
|
5
|
+
module Utility
|
6
|
+
# Extended Id of object
|
7
|
+
class ExtendedID
|
8
|
+
include Comparable
|
9
|
+
|
10
|
+
# Create new Id based on PID, thread ID and object ID.
|
11
|
+
def initialize(pid = nil, tid = nil, oid = nil)
|
12
|
+
@pid = pid || Process.pid
|
13
|
+
@tid = tid || Thread.current.object_id
|
14
|
+
@oid = oid || object_id
|
15
|
+
end
|
16
|
+
|
17
|
+
# @return [Integer] process ID.
|
18
|
+
attr_reader :pid
|
19
|
+
|
20
|
+
# @return [Integer] thread ID.
|
21
|
+
attr_reader :tid
|
22
|
+
|
23
|
+
# @return [Integer] object ID.
|
24
|
+
attr_reader :oid
|
25
|
+
|
26
|
+
# @return [String]
|
27
|
+
def to_s
|
28
|
+
"#{@pid}##{@tid}##{@oid}"
|
29
|
+
end
|
30
|
+
|
31
|
+
# Comparison operator.
|
32
|
+
def <=>(other)
|
33
|
+
if @pid == other.pid && @tid == other.tid
|
34
|
+
@oid <=> other.oid
|
35
|
+
elsif @pid == other.pid && @tid != other.tid
|
36
|
+
@tid <=> tid
|
37
|
+
else
|
38
|
+
@pid <=> other.pid
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.from(obj)
|
43
|
+
case obj
|
44
|
+
when ExtendedID then new(obj.pid, obj.tid, obj.oid)
|
45
|
+
when String then new(*obj.split('#').map(&:to_i))
|
46
|
+
else
|
47
|
+
raise 'unknown type'
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
# Adds special method to return object ID.
|
52
|
+
module WithID
|
53
|
+
# Identifies object in thread and process.
|
54
|
+
def __with_id__extended_id
|
55
|
+
@__with_id__extended_id ||= ExtendedID.new
|
56
|
+
end
|
57
|
+
alias extended_id __with_id__extended_id
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module IORequest
|
4
|
+
# Utility methods.
|
5
|
+
module Utility
|
6
|
+
# Adds special method to identify object in log files.
|
7
|
+
module WithProgName
|
8
|
+
# Identifies object and thread it runs in.
|
9
|
+
def prog_name
|
10
|
+
"#{self.class.name}##{object_id} in Thread##{Thread.current.object_id}"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
data/lib/io_request/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: io_request
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Fizvlad
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-07-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -25,75 +25,75 @@ dependencies:
|
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '2.0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: minitest
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
33
|
+
version: '5.0'
|
34
34
|
type: :development
|
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: '
|
40
|
+
version: '5.0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
42
|
+
name: rake
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
47
|
+
version: '13.0'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: '
|
54
|
+
version: '13.0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
56
|
+
name: json
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
59
|
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
61
|
+
version: '2.0'
|
62
62
|
type: :runtime
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: '
|
68
|
+
version: '2.0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
70
|
+
name: logger
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
73
|
- - "~>"
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version:
|
75
|
+
version: '1.4'
|
76
76
|
type: :runtime
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
80
|
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version:
|
82
|
+
version: '1.4'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
|
-
name:
|
84
|
+
name: timeout-extensions
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
87
|
- - "~>"
|
88
88
|
- !ruby/object:Gem::Version
|
89
|
-
version:
|
89
|
+
version: 0.1.1
|
90
90
|
type: :runtime
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
94
|
- - "~>"
|
95
95
|
- !ruby/object:Gem::Version
|
96
|
-
version:
|
96
|
+
version: 0.1.1
|
97
97
|
description:
|
98
98
|
email:
|
99
99
|
- fizvlad@mail.ru
|
@@ -102,9 +102,10 @@ extensions: []
|
|
102
102
|
extra_rdoc_files: []
|
103
103
|
files:
|
104
104
|
- ".gitignore"
|
105
|
+
- ".rubocop.yml"
|
106
|
+
- ".rubocop_todo.yml"
|
105
107
|
- ".travis.yml"
|
106
108
|
- Gemfile
|
107
|
-
- Gemfile.lock
|
108
109
|
- LICENSE.txt
|
109
110
|
- README.md
|
110
111
|
- Rakefile
|
@@ -112,10 +113,12 @@ files:
|
|
112
113
|
- examples/simple_example.rb
|
113
114
|
- io_request.gemspec
|
114
115
|
- lib/io_request.rb
|
116
|
+
- lib/io_request/authorizer.rb
|
115
117
|
- lib/io_request/client.rb
|
116
|
-
- lib/io_request/logging.rb
|
117
118
|
- lib/io_request/message.rb
|
118
|
-
- lib/io_request/utility.rb
|
119
|
+
- lib/io_request/utility/multi_thread.rb
|
120
|
+
- lib/io_request/utility/with_id.rb
|
121
|
+
- lib/io_request/utility/with_prog_name.rb
|
119
122
|
- lib/io_request/version.rb
|
120
123
|
homepage: https://github.com/fizvlad/io-request-rb
|
121
124
|
licenses:
|
@@ -132,14 +135,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
132
135
|
requirements:
|
133
136
|
- - ">="
|
134
137
|
- !ruby/object:Gem::Version
|
135
|
-
version: 2.
|
138
|
+
version: 2.6.5
|
136
139
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
137
140
|
requirements:
|
138
141
|
- - ">="
|
139
142
|
- !ruby/object:Gem::Version
|
140
143
|
version: '0'
|
141
144
|
requirements: []
|
142
|
-
rubygems_version: 3.0.
|
145
|
+
rubygems_version: 3.1.0.pre2
|
143
146
|
signing_key:
|
144
147
|
specification_version: 4
|
145
148
|
summary: Small gem to create JSON request/response type of connection over IO object
|