xkoon 1.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: ee2734e060d87cfe173b074e2149710a13d3317c
4
+ data.tar.gz: 742b227a140dbb54c9cdbb934c36032b0e01f8c3
5
+ SHA512:
6
+ metadata.gz: a10dbd184d2cad958795d3451274fc7741ed5d4f13b2168d318ab8692adbdcafc0ae468033ec75d638f947a3b788b13670fc2592180ac0ab9a617095e4c5ca9c
7
+ data.tar.gz: 8ab2806562fdf8b3a4a3fcaf2bac368693372c0fded34a08de17860f4be3b307e3a4c5ee3d3203bd097405278f96cbee87a688816d36bc1c5c27a229d8524e93
@@ -0,0 +1,3 @@
1
+ .idea
2
+ Gemfile.lock
3
+ pkg
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source 'https://rubygems.org'
2
+ gemspec
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2017 Paul Duncan
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,217 @@
1
+ # xKoon
2
+
3
+ JSON-based Reactive Service Framework
4
+
5
+ ## Presentation
6
+
7
+ This library provides a simple framework to build network services (servers & clients) around a very simple JSON message format, using [RxIO](https://rubygems.org/gems/rxio).
8
+
9
+ ## Installation
10
+
11
+ ### Gemfile
12
+ ```ruby
13
+ gem 'xkoon'
14
+ ```
15
+
16
+ ### Terminal
17
+ ```bash
18
+ gem install -V xkoon
19
+ ```
20
+
21
+ ## Usage
22
+
23
+ Building a service endpoint (whether client or server) with xKoon requires the following:
24
+ 1. define a *Processor* module (for your business logic) providing a bunch of _process_XXX_ methods'
25
+ 2. instantiate an *XKoon::Service* or *XKoon::Client* object around your processor
26
+ 3. run it
27
+
28
+ ### The Processor
29
+
30
+ The _processor_ is at the heart of xKoon - it provides all the necessary abstractions for building simple services.
31
+
32
+ #### How to use
33
+
34
+ To build a processor, simply include *XKoon::Processor* into any module. Then, any method in your module that starts with _process__ will be made available to remote peers.
35
+
36
+ ```ruby
37
+ module ExampleProcessor
38
+ include XKoon::Processor
39
+
40
+ def process_foobar p, h, m
41
+ puts "Got a 'foobar' request: peer=#{p} handler=#{h} message=#{m}"
42
+ end
43
+ end
44
+ ```
45
+
46
+ #### Sending requests
47
+
48
+ The *send_request* method in *XKoon::Processor* allows sending requests to remote peers.
49
+
50
+ ```ruby
51
+ Processor.send_request p, h, m, :some_request_method, data: { foo: :bar }
52
+ ```
53
+
54
+ #### Sending responses
55
+
56
+ While processing a request, a response can be sent back using the *send_response* method in *XKoon::Processor*.
57
+
58
+ ```ruby
59
+ # Success
60
+ send_response p, h, m, 'Everything was processed correctly!'
61
+ ```
62
+
63
+ Errors should be sent using the *send_error* method.
64
+
65
+ ```ruby
66
+ # Failure
67
+ send_error p, h, m, 'Something went wrong :('
68
+ ```
69
+
70
+ #### Error Wrapper
71
+
72
+ An error wrapper is provided within *XKoon::Processor*, allowing for a more transparent implementation of business logic.
73
+
74
+ The *error_wrapper* method will yield any block passed to it, rescuing any exception and immediately throwing it back to the remote peer.
75
+
76
+ ```ruby
77
+ error_wrapper p, h, m do
78
+ raise "This will get thrown back to remote peer"
79
+ end
80
+ ```
81
+
82
+ #### Dealing with responses
83
+
84
+ Any response to a request will be handed to the _handle_response_ method of the processor. By default the method is empty. You may override it to implement any custom behavior.
85
+
86
+ ```ruby
87
+ module ExampleProcessor
88
+ include XKoon::Processor
89
+
90
+ def handle_response p, h, m
91
+ puts "Got a response from peer [#{p}]: #{m}"
92
+ end
93
+ end
94
+ ```
95
+
96
+ #### Client / Server Processors
97
+
98
+ The processor does not care about being the client or server. This means you can implement a single processor serving as a two-way module for both client & server.
99
+
100
+ ### Request Format
101
+
102
+ xKoon Requests contain the following information:
103
+
104
+ ```ruby
105
+ {
106
+ # Requested Method
107
+ req: :some_request_method,
108
+
109
+ # Timestamp marking the time at which the remote peer sent the request
110
+ sent: 1495623525
111
+ }
112
+ ```
113
+
114
+ ### Method Proxying (Make everything transparent)
115
+
116
+ xKoon injects a _to_proxy_ method into every Peer Hash.
117
+ This method simply creates a *Proxy* around the peer and returns it.
118
+
119
+ The proxy object serves as a remote method interface: any method called on it will be forwarded to the remote peer.
120
+
121
+ ```ruby
122
+ # Create Proxy around Peer
123
+ pxy = peer_hash.to_proxy
124
+
125
+ # Send a 'foobar' request to the remote peer
126
+ pxy.foobar hello: :world
127
+ ```
128
+
129
+ ### Response Format
130
+
131
+ xKoon Responses contain the following information:
132
+
133
+ ```ruby
134
+ {
135
+ # Success (true / false)
136
+ success: true,
137
+
138
+ # Original Request
139
+ req: { req: :some_request_method, sent: 1495623525 },
140
+
141
+ # Whatever the remote peer responded (can be any object - will be converted to JSON)
142
+ res: 'Got your message!',
143
+
144
+ # Timestamp marking the time at which the remote peer sent the response
145
+ sent: 1495623525
146
+ }
147
+ ```
148
+
149
+ ### Example
150
+
151
+ Below is a simple but complete example presenting an 'echo' service, replying back anything that was answered.
152
+
153
+ ```ruby
154
+ require 'xkoon'
155
+
156
+ # Proxy objects
157
+ PXY = {}
158
+
159
+ # Response Objects
160
+ RES = {}
161
+
162
+ # Two-Way Processor (used by both the client & server)
163
+ module EchoProcessor
164
+ include XKoon::Processor
165
+
166
+ # On Join (Attach the Proxy Objects as soon as we're online)
167
+ def self.on_join peer, handler
168
+ PXY[:server] = peer.to_proxy if peer.has_key? :serv
169
+ PXY[:client] = peer.to_proxy if peer.has_key? :client
170
+ end
171
+
172
+ # On Drop (Release the Proxy Objects whenever we lose the connection)
173
+ def self.on_drop peer, handler
174
+ PXY[:server] = nil if peer.has_key? :serv
175
+ PXY[:client] = nil if peer.has_key? :client
176
+ end
177
+
178
+ # Process 'echo' Request
179
+ def self.process_echo p, h, m
180
+ puts "Got echo request: #{m[:data]}"
181
+ send_response p, h, m, m[:data]
182
+ end
183
+
184
+ # Handle Response
185
+ def self.handle_response p, h, m
186
+ RES[:server] = m if p.has_key? :serv
187
+ RES[:client] = m if p.has_key? :client
188
+ puts "Got response from peer #{p[:peer][:name]}:#{p[:peer][:port]}: #{m[:res]}"
189
+ end
190
+ end
191
+
192
+ # Create Endpoints
193
+ srv = XKoon::Service.new EchoProcessor
194
+ cli = XKoon::Client.new EchoProcessor
195
+
196
+ # Start Server & Client
197
+ srv.startup
198
+ cli.startup
199
+
200
+ # Wait for client and echo something
201
+ sleep 0.1 until PXY[:client]
202
+ PXY[:client].echo data: { str: 'hello world!' }
203
+
204
+ # Wait for Response to come back
205
+ sleep 0.1 until RES[:client]
206
+
207
+ # Drop Client and wait for drop
208
+ cli.shutdown
209
+ sleep 0.1 while PXY[:server]
210
+
211
+ # Drop Server
212
+ srv.shutdown
213
+ ```
214
+
215
+ ## License
216
+
217
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
@@ -0,0 +1,9 @@
1
+ require 'rake/testtask'
2
+ require 'bundler/gem_tasks'
3
+
4
+ Rake::TestTask.new do |t|
5
+ t.libs << 'test'
6
+ t.pattern = 'test/**/test*.rb'
7
+ end
8
+
9
+ task :default => :test
@@ -0,0 +1,15 @@
1
+ # xKoon
2
+ # by Eresse <eresse@eresse.net>
3
+
4
+ # Internal Includes
5
+ require 'xkoon/version'
6
+ require 'xkoon/service'
7
+ require 'xkoon/client'
8
+ require 'xkoon/handler'
9
+ require 'xkoon/processor'
10
+ require 'xkoon/proxy'
11
+
12
+ # xKoon Module:
13
+ # Root Module for xKoon.
14
+ module XKoon
15
+ end
@@ -0,0 +1,40 @@
1
+ # xKoon
2
+ # by Eresse <eresse@eresse.net>
3
+
4
+ # External Includes
5
+ require 'json'
6
+ require 'aromat'
7
+ require 'rxio'
8
+
9
+ # Internal Includes
10
+ require 'xkoon/handler'
11
+
12
+ # xKoon Module
13
+ module XKoon
14
+
15
+ # Client Class
16
+ class Client < RxIO::Client
17
+
18
+ # Attribute Accessors
19
+ attr_reader :processor
20
+
21
+ # Defaults
22
+ DEFAULT_ADDR = 'localhost'
23
+ DEFAULT_PORT = 23255
24
+
25
+ # Construct:
26
+ # Builds a *Client* around a given _processor_ implementation, set to connect to _addr_ on _port_.
27
+ # @param [Module] processor
28
+ # @param [String] addr
29
+ # @param [Fixnum] port
30
+ # @param [Hash] ssl_params
31
+ def initialize processor, addr = DEFAULT_ADDR, port = DEFAULT_PORT, ssl_params = nil
32
+
33
+ # Super
34
+ super addr, port, Handler, ssl_params
35
+
36
+ # Set Processor
37
+ @processor = processor
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,92 @@
1
+ # xKoon
2
+ # by Eresse <eresse@eresse.net>
3
+
4
+ # External Includes
5
+ require 'json'
6
+ require 'aromat'
7
+ require 'rxio'
8
+
9
+ # Internal Includes
10
+ require 'xkoon/processor'
11
+ require 'xkoon/proxy'
12
+
13
+ # xKoon Module
14
+ module XKoon
15
+
16
+ # Handler Module:
17
+ # Provides a generic two-way implementation of the xKoon Protocol.
18
+ module Handler
19
+
20
+ # Split messages on New Lines (Extend BinDelim I/O Filter & Set message delimiter to "\n")
21
+ extend RxIO::IOFilters::BinDelim
22
+ msg_delim "\n"
23
+
24
+ # Send Request:
25
+ # Sends a request to the Peer.
26
+ # @param [Hash] peer RxIO Peer (Client / Server) Hash
27
+ # @param [Symbol] req Request method
28
+ # @param [Hash] msg Message Hash
29
+ def self.send_request peer, req, msg
30
+ send_msg peer, msg.merge(req: req, sent: Time.now.to_i).to_json
31
+ end
32
+
33
+ # On Join:
34
+ # RxIO Service Interface Callback - Triggered each time a peer is connected. Forwards notifications to Processor.
35
+ # @param [Hash] peer An RxIO Peer (Client / Server) Hash
36
+ def self.on_join peer
37
+
38
+ # Acquire Local Endpoint's Processor
39
+ proc = peer[:local].processor
40
+
41
+ # Inject Proxy Generator Method into Peer
42
+ peer.define_singleton_method(:to_proxy) { Proxy.for_peer peer }
43
+
44
+ # Forward Join Notification to Processor
45
+ proc.on_join peer, self if proc.respond_to? :on_join
46
+ end
47
+
48
+ # On Drop:
49
+ # RxIO Service Interface Callback - Triggered each time a peer is dropped. Forwards notifications to Processor.
50
+ # @param [Hash] peer An RxIO Peer (Client / Server) Hash
51
+ def self.on_drop peer
52
+
53
+ # Acquire Local Endpoint's Processor
54
+ proc = peer[:local].processor
55
+
56
+ # Forward Drop Notification to Processor
57
+ proc.on_drop peer, self if proc.respond_to? :on_drop
58
+ end
59
+
60
+ # Handle Message:
61
+ # Parses incomning messages and forwards them to the processor.
62
+ # @param [Hash] peer An RxIO Peer (Client / Server) Hash
63
+ # @param [String] msg A message
64
+ def self.handle_msg peer, msg
65
+
66
+ # Process Chomped Message as JSON and Deep-Symbolize Keys
67
+ process_msg peer, JSON.parse(msg.chomp).try(:sym_keys)
68
+ end
69
+
70
+ # Process Message:
71
+ # Verifies message structure and forwards to processor.
72
+ # @param [Hash] peer An RxIO Peer (Client / Server) Hash
73
+ # @param [Hash] msg A message
74
+ def self.process_msg peer, m
75
+
76
+ # Acquire Local Endpoint's Processor
77
+ proc = peer[:local].processor
78
+
79
+ # Check Request Present in Message
80
+ raise "Missing method in request" unless m[:req].try(:to_s).try :nstr
81
+
82
+ # Handle Responses
83
+ return proc.handle_response peer, self, m if m[:req].is_a? Hash
84
+
85
+ # Check Request Valid in Message
86
+ raise "Invalid method [#{m[:req]}] in request" unless proc.respond_to? "process_#{m[:req]}".to_sym
87
+
88
+ # Forward Message to Local Endpoint's Processor
89
+ proc.send "process_#{m[:req]}".to_sym, peer, self, m
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,85 @@
1
+ # xKoon
2
+ # by Eresse <eresse@eresse.net>
3
+
4
+ # External Includes
5
+ require 'json'
6
+ require 'aromat'
7
+
8
+ # xKoon Module
9
+ module XKoon
10
+
11
+ # Generic Processor Module:
12
+ # Provides base methods for implementing xKoon Service Processors.
13
+ module Processor
14
+
15
+ # Included:
16
+ # Inject stuff when included.
17
+ def self.included base
18
+ base.extend ClassMethods
19
+ end
20
+
21
+ # Class Methods:
22
+ # These are injected into the user's processor implementation when this module is included.
23
+ module ClassMethods
24
+
25
+ # Send Request:
26
+ # Sends a request to the Peer.
27
+ # @param [Hash] p RxIO Peer (Client / Server) Hash
28
+ # @param [Module] h Handler Module
29
+ # @param [Symbol] r Request method
30
+ # @param [Hash] m Message Hash
31
+ def send_request p, h, r, m
32
+ h.send_request p, r, m
33
+ end
34
+
35
+ # Handle Response:
36
+ # Called whenever a response is sent back from the remote peer.
37
+ # @param [Hash] p RxIO Peer (Client / Server) Hash
38
+ # @param [Module] h Handler Module
39
+ # @param [Hash] m Message Hash
40
+ def handle_response p, h, m
41
+ # NoOp - Provide your implementation
42
+ end
43
+
44
+ # Wrap in Error:
45
+ # Yields the given block, rescuing exceptions and throwing them back to the peer.
46
+ # @param [Hash] p RxIO Peer (Client / Server) Hash
47
+ # @param [Module] h Handler Module
48
+ # @param [Hash] m Message Hash
49
+ # @return [Array] An two-element Array containing a boolean representing success and the block's result [failed, output]
50
+ def error_wrapper p, h, m
51
+ failed = false
52
+ out = nil
53
+ begin
54
+ out = yield
55
+ rescue Exception => e
56
+ send_error p, h, m, e
57
+ failed = true
58
+ end
59
+
60
+ [failed, out]
61
+ end
62
+
63
+ # Respond with Error:
64
+ # Sends an error message to the Peer.
65
+ # @param [Hash] p RxIO Peer (Client / Server) Hash
66
+ # @param [Module] h Handler Module
67
+ # @param [Hash] req Original request from Peer
68
+ # @param [Object] error Anything representing an error
69
+ def send_error p, h, req, error
70
+ send_response p, h, req, { error: error }, false
71
+ end
72
+
73
+ # Send Generic Response Message:
74
+ # Sends a response message to the Peer.
75
+ # @param [Hash] p RxIO Peer (Client / Server) Hash
76
+ # @param [Module] h Handler Module
77
+ # @param [Hash] req Original request from Peer
78
+ # @param [Object] res Anything representing the result of the Peer's request
79
+ # @param [Object] success Boolean indicating success for the Peer's request
80
+ def send_response p, h, req, res = {}, success = true
81
+ h.send_msg p, { success: success, req: req, res: res, sent: Time.now.to_i }.to_json
82
+ end
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,69 @@
1
+ # xKoon
2
+ # by Eresse <eresse@eresse.net>
3
+
4
+ # External Includes
5
+ require 'aromat'
6
+
7
+ # Internal Includes
8
+ require 'xkoon/handler'
9
+ require 'xkoon/processor'
10
+
11
+ # xKoon Module
12
+ module XKoon
13
+
14
+ # Proxy Module:
15
+ # Provides transparent proxying of methods to a Peer.
16
+ module Proxy
17
+
18
+ # Create Proxy for Peer:
19
+ # Creates a new *Base* proxy object around a given _peer_ and optional _handler_.
20
+ # @param [Hash] peer RxIO Peer (Client / Server) Hash
21
+ # @param [Module] handler Handler module
22
+ def self.for_peer peer, handler = XKoon::Handler
23
+ Base.new peer, handler
24
+ end
25
+
26
+ # Method Missing:
27
+ # Proxy all method calls into requests to the Service Peer.
28
+ def self.method_missing name, *args
29
+
30
+ # Ensure we have at least a peer, handler and message
31
+ raise "Missing arguments in call to [#{name}] (peer, handler, msg)" unless args.size >= 3
32
+
33
+ # Get Peer & Handler from Args
34
+ peer = args.slice! 0
35
+ handler = args.slice! 0
36
+
37
+ # Acquire Payload
38
+ msg = args.slice! 0
39
+
40
+ # Send Request
41
+ handler.send_request peer, name, msg
42
+ end
43
+
44
+ # Object Proxy Base Class:
45
+ # Inherit this class to build proxy objects, routing all method calls to the remote peer.
46
+ class Base
47
+
48
+ # Construct:
49
+ # Creates a new *Base* proxy object around a given _peer_ and optional _handler_.
50
+ # @param [Hash] peer RxIO Peer (Client / Server) Hash
51
+ # @param [Module] handler Handler module
52
+ def initialize peer, handler = XKoon::Handler
53
+ @proxy_peer = peer
54
+ @proxy_handler = handler
55
+ end
56
+
57
+ # Method Missing:
58
+ # Proxy all method calls into requests to the remote peer.
59
+ def method_missing name, *args
60
+
61
+ # Ensure we have at least a message
62
+ raise "Missing argument in call to [#{name}] (msg)" unless args.size >= 1
63
+
64
+ # Forward request through Proxy Module
65
+ Proxy.send name, @proxy_peer, @proxy_handler, *args
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,40 @@
1
+ # xKoon
2
+ # by Eresse <eresse@eresse.net>
3
+
4
+ # External Includes
5
+ require 'json'
6
+ require 'aromat'
7
+ require 'rxio'
8
+
9
+ # Internal Includes
10
+ require 'xkoon/handler'
11
+
12
+ # xKoon Module
13
+ module XKoon
14
+
15
+ # Service Class
16
+ class Service < RxIO::Service
17
+
18
+ # Attribute Accessors
19
+ attr_reader :processor
20
+
21
+ # Defaults
22
+ DEFAULT_ADDR = 'localhost'
23
+ DEFAULT_PORT = 23255
24
+
25
+ # Construct:
26
+ # Builds a *Service* around a given _processor_ implementation, set to listen for incoming connections @ _addr_ on _port_.
27
+ # @param [Module] processor
28
+ # @param [String] addr
29
+ # @param [Fixnum] port
30
+ # @param [Hash] ssl_params
31
+ def initialize processor, addr = DEFAULT_ADDR, port = DEFAULT_PORT, ssl_params = nil
32
+
33
+ # Super
34
+ super addr, port, Handler, ssl_params
35
+
36
+ # Set Processor
37
+ @processor = processor
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,9 @@
1
+ # xKoon
2
+ # by Eresse <eresse@eresse.net>
3
+
4
+ # xKoon Module
5
+ module XKoon
6
+
7
+ # Version
8
+ VERSION = '1.0.0'
9
+ end
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'xkoon/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'xkoon'
8
+ spec.version = XKoon::VERSION
9
+ spec.authors = ['Eresse']
10
+ spec.email = ['eresse@eresse.net']
11
+
12
+ spec.summary = 'JSON-based Reactive Service Framework'
13
+ spec.description = 'Provides a simple framework to build network services.'
14
+ spec.homepage = 'http://redmine.eresse.net/projects/xkoon'
15
+ spec.license = 'MIT'
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
18
+ spec.require_paths = ['lib']
19
+
20
+ spec.add_development_dependency 'bundler'
21
+ spec.add_development_dependency 'rake'
22
+ spec.add_runtime_dependency 'minitest'
23
+ spec.add_runtime_dependency 'aromat'
24
+ spec.add_runtime_dependency 'rxio'
25
+ end
metadata ADDED
@@ -0,0 +1,127 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: xkoon
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Eresse
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-05-24 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: minitest
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: aromat
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rxio
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: Provides a simple framework to build network services.
84
+ email:
85
+ - eresse@eresse.net
86
+ executables: []
87
+ extensions: []
88
+ extra_rdoc_files: []
89
+ files:
90
+ - ".gitignore"
91
+ - Gemfile
92
+ - LICENSE.txt
93
+ - README.md
94
+ - Rakefile
95
+ - lib/xkoon.rb
96
+ - lib/xkoon/client.rb
97
+ - lib/xkoon/handler.rb
98
+ - lib/xkoon/processor.rb
99
+ - lib/xkoon/proxy.rb
100
+ - lib/xkoon/service.rb
101
+ - lib/xkoon/version.rb
102
+ - xkoon.gemspec
103
+ homepage: http://redmine.eresse.net/projects/xkoon
104
+ licenses:
105
+ - MIT
106
+ metadata: {}
107
+ post_install_message:
108
+ rdoc_options: []
109
+ require_paths:
110
+ - lib
111
+ required_ruby_version: !ruby/object:Gem::Requirement
112
+ requirements:
113
+ - - ">="
114
+ - !ruby/object:Gem::Version
115
+ version: '0'
116
+ required_rubygems_version: !ruby/object:Gem::Requirement
117
+ requirements:
118
+ - - ">="
119
+ - !ruby/object:Gem::Version
120
+ version: '0'
121
+ requirements: []
122
+ rubyforge_project:
123
+ rubygems_version: 2.5.1
124
+ signing_key:
125
+ specification_version: 4
126
+ summary: JSON-based Reactive Service Framework
127
+ test_files: []