xkoon 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: []