plumbus 0.1.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 +7 -0
- data/.gitignore +10 -0
- data/.rspec +2 -0
- data/.travis.yml +3 -0
- data/CODE_OF_CONDUCT.md +49 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +109 -0
- data/Rakefile +6 -0
- data/bin/plumbus +50 -0
- data/docs/images/banner.png +0 -0
- data/docs/images/request_response_drivers.png +0 -0
- data/lib/plumbus.rb +12 -0
- data/lib/plumbus/driver.rb +28 -0
- data/lib/plumbus/driver_facilities.rb +17 -0
- data/lib/plumbus/helpers/remove_references.rb +30 -0
- data/lib/plumbus/helpers/trim.rb +45 -0
- data/lib/plumbus/loader.rb +44 -0
- data/lib/plumbus/port.rb +51 -0
- data/lib/plumbus/ports.rb +123 -0
- data/lib/plumbus/version.rb +3 -0
- data/plumbus.gemspec +27 -0
- metadata +135 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 5b89f274da67d1f431e10b3d41cca145b5499b0f
|
4
|
+
data.tar.gz: d46ab230187b679ad802a982992eb2ff500315bf
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b3b36c8a6264c6c03305d4f5aa56372369fac782404e7f91fda78112e118d21cab0c99c09e42a84d9e81815ba6af549071f2fb4fedff1225f960780118fe5c4d
|
7
|
+
data.tar.gz: 6ed57aac6f1582a7b9b94b23d720c638a7d9039c05d1e077115e097c835ea6437ccfedadd7f0d6d057cdd04f160df8f8c6db0a49d38173a39774e4f6a92c2bfd
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/CODE_OF_CONDUCT.md
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
# Contributor Code of Conduct
|
2
|
+
|
3
|
+
As contributors and maintainers of this project, and in the interest of
|
4
|
+
fostering an open and welcoming community, we pledge to respect all people who
|
5
|
+
contribute through reporting issues, posting feature requests, updating
|
6
|
+
documentation, submitting pull requests or patches, and other activities.
|
7
|
+
|
8
|
+
We are committed to making participation in this project a harassment-free
|
9
|
+
experience for everyone, regardless of level of experience, gender, gender
|
10
|
+
identity and expression, sexual orientation, disability, personal appearance,
|
11
|
+
body size, race, ethnicity, age, religion, or nationality.
|
12
|
+
|
13
|
+
Examples of unacceptable behavior by participants include:
|
14
|
+
|
15
|
+
* The use of sexualized language or imagery
|
16
|
+
* Personal attacks
|
17
|
+
* Trolling or insulting/derogatory comments
|
18
|
+
* Public or private harassment
|
19
|
+
* Publishing other's private information, such as physical or electronic
|
20
|
+
addresses, without explicit permission
|
21
|
+
* Other unethical or unprofessional conduct
|
22
|
+
|
23
|
+
Project maintainers have the right and responsibility to remove, edit, or
|
24
|
+
reject comments, commits, code, wiki edits, issues, and other contributions
|
25
|
+
that are not aligned to this Code of Conduct, or to ban temporarily or
|
26
|
+
permanently any contributor for other behaviors that they deem inappropriate,
|
27
|
+
threatening, offensive, or harmful.
|
28
|
+
|
29
|
+
By adopting this Code of Conduct, project maintainers commit themselves to
|
30
|
+
fairly and consistently applying these principles to every aspect of managing
|
31
|
+
this project. Project maintainers who do not follow or enforce the Code of
|
32
|
+
Conduct may be permanently removed from the project team.
|
33
|
+
|
34
|
+
This code of conduct applies both within project spaces and in public spaces
|
35
|
+
when an individual is representing the project or its community.
|
36
|
+
|
37
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
38
|
+
reported by contacting a project maintainer at seotownsend@icloud.com. All
|
39
|
+
complaints will be reviewed and investigated and will result in a response that
|
40
|
+
is deemed necessary and appropriate to the circumstances. Maintainers are
|
41
|
+
obligated to maintain confidentiality with regard to the reporter of an
|
42
|
+
incident.
|
43
|
+
|
44
|
+
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
45
|
+
version 1.3.0, available at
|
46
|
+
[http://contributor-covenant.org/version/1/3/0/][version]
|
47
|
+
|
48
|
+
[homepage]: http://contributor-covenant.org
|
49
|
+
[version]: http://contributor-covenant.org/version/1/3/0/
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2016 seo
|
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.
|
data/README.md
ADDED
@@ -0,0 +1,109 @@
|
|
1
|
+

|
2
|
+
|
3
|
+
[](http://badge.fury.io/rb/plumbus)
|
4
|
+
[](https://travis-ci.org/sotownsend/plumbus)
|
5
|
+
[](https://bitdeli.com/free "Bitdeli Badge")
|
6
|
+
[](https://github.com/sotownsend/plumbus/blob/master/LICENSE)
|
7
|
+
|
8
|
+
# What is this?
|
9
|
+
|
10
|
+
Plubus is an agnostic micro-service router.
|
11
|
+
|
12
|
+
## Features
|
13
|
+
- [x] Bring your archaic HTTP api into the micro-service age without modifying the API
|
14
|
+
- [x] *Any language, any networking or queuing library*
|
15
|
+
- [x] Distributed by design, even session information
|
16
|
+
- [x] Everything is a stream/push. Even HTTP (just a very short stream session!)
|
17
|
+
- [x] Mix & Match - Daisy-chainable
|
18
|
+
|
19
|
+
|
20
|
+
## Example scenerio
|
21
|
+
Let's take the case where you have an aging HTTP web-service API, and a new modern sock-io client.
|
22
|
+
<div style='text-align: center'>
|
23
|
+
<img width=600 src='./docs/images/request_response_drivers.png' />
|
24
|
+
</div>
|
25
|
+
|
26
|
+
In this example, we're using an HTTP driver and sockio-driver on the request side. On the response side we have an HTTP driver & a redis-queue driver. This configuration
|
27
|
+
allows us to serve all of our services located on the redis-bus & HTTP-bus to both sockio users and HTTP users!
|
28
|
+
|
29
|
+
## Routing schemes
|
30
|
+
Each request contains an action-name and session-id used for routing. Each response-driver maintains a running-list of available actions. If multiple action-paths are available,
|
31
|
+
a round-robin scheme is used to deliver messages. Responses are delivered based on the session-id back to the original source. This allows many responses, for a request that has
|
32
|
+
requested multiple actions which resulted in requests to multiple response backends, to deliver to the correct requester & know the status of the requester as signals are propogated
|
33
|
+
back to the responders in the event the request is closed. A session is deemed over if all responders hang-up.
|
34
|
+
|
35
|
+
## Streaming
|
36
|
+
All connections in plumbus are streams. HTTP, as it is stateless, is just treated as a degenerate stream that closes it's session after a response is given. One of the neat-things
|
37
|
+
about plumbus is that streams are able to hit multiple responses (by virtue of a request stream has sent multiple action requests and those were routed to seperate responses). This
|
38
|
+
provides you with load-balancing on traditionally single-server streams (like sock.io).
|
39
|
+
|
40
|
+
## Configuration
|
41
|
+
Configure is handled through a ruby file. This file contains a listing of `ports` which are just driver instances that are declared on either the request or response side.
|
42
|
+
```ruby
|
43
|
+
port(:request, 'plumbus-http') do
|
44
|
+
#Driver specific config
|
45
|
+
end
|
46
|
+
|
47
|
+
port(:request, 'plumbus-sockio') do
|
48
|
+
#Driver specific config
|
49
|
+
end
|
50
|
+
|
51
|
+
port(:response, 'plumbus-http') do
|
52
|
+
#Driver specific config
|
53
|
+
end
|
54
|
+
|
55
|
+
port(:response, 'plumbus-redis-queue') do
|
56
|
+
#Driver specific config
|
57
|
+
end
|
58
|
+
```
|
59
|
+
|
60
|
+
# Setup
|
61
|
+
```js
|
62
|
+
#Setup
|
63
|
+
gem install plumbus
|
64
|
+
```
|
65
|
+
|
66
|
+
# Usage
|
67
|
+
#### SYNOPSIS
|
68
|
+
```js
|
69
|
+
plumbus config
|
70
|
+
```
|
71
|
+
#### DESCRIPTION
|
72
|
+
config is a ruby file that declares backends & frontends (called ports).
|
73
|
+
|
74
|
+
## Requirements
|
75
|
+
|
76
|
+
- Modern **nix** (FreeBSD, Mac, or Linux)
|
77
|
+
- Ruby 2.2.1 or Higher (Very important)
|
78
|
+
|
79
|
+
## Communication
|
80
|
+
> ♥ This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
|
81
|
+
|
82
|
+
- If you **found a bug**, open an issue.
|
83
|
+
- If you **have a feature request**, open an issue.
|
84
|
+
- If you **want to contribute**, submit a pull request.
|
85
|
+
|
86
|
+
## Installation
|
87
|
+
|
88
|
+
RVM users:
|
89
|
+
Run `gem install plumbus`
|
90
|
+
|
91
|
+
System ruby installation?
|
92
|
+
Run `sudo gem install plumbus`
|
93
|
+
|
94
|
+
---
|
95
|
+
|
96
|
+
## FAQ
|
97
|
+
|
98
|
+
### When should I use plumbus?
|
99
|
+
|
100
|
+
Todo
|
101
|
+
|
102
|
+
### Creator
|
103
|
+
|
104
|
+
- [Seo Townsend](http://github.com/sotownsend) ([@seotownsend](https://twitter.com/seotownsend))
|
105
|
+
|
106
|
+
|
107
|
+
## License
|
108
|
+
|
109
|
+
plumbus is released under the MIT license. See LICENSE for details.
|
data/Rakefile
ADDED
data/bin/plumbus
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "plumbus"
|
5
|
+
require 'yaml'
|
6
|
+
require 'optparse'
|
7
|
+
|
8
|
+
parser = OptionParser.new do |opts|
|
9
|
+
opts.banner = "Usage: plumbus config"
|
10
|
+
end
|
11
|
+
parser.parse!
|
12
|
+
|
13
|
+
unless config_path = ARGV.pop
|
14
|
+
$stderr.puts parser
|
15
|
+
exit -1
|
16
|
+
end
|
17
|
+
|
18
|
+
Plumbus::Loader.load config_path
|
19
|
+
|
20
|
+
$stderr.puts <<HERE
|
21
|
+
(((
|
22
|
+
(( ((((
|
23
|
+
((((((((((((((((((
|
24
|
+
(((((((((((((
|
25
|
+
(((((((((((((
|
26
|
+
(((((((((((((
|
27
|
+
******
|
28
|
+
******
|
29
|
+
******
|
30
|
+
*******
|
31
|
+
**********
|
32
|
+
*************
|
33
|
+
******************
|
34
|
+
***************(****
|
35
|
+
*************((/((/**
|
36
|
+
*************((((((((/
|
37
|
+
*************//////(//
|
38
|
+
**********************
|
39
|
+
*********************
|
40
|
+
*******************
|
41
|
+
****************
|
42
|
+
***********
|
43
|
+
-----------------------------------------
|
44
|
+
HERE
|
45
|
+
|
46
|
+
|
47
|
+
while 100
|
48
|
+
$stderr.puts ">Ready to get Riggity Riggity Wrecked Son!"
|
49
|
+
sleep 1000
|
50
|
+
end
|
Binary file
|
Binary file
|
data/lib/plumbus.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
require "plumbus/version"
|
2
|
+
require "plumbus/driver_facilities"
|
3
|
+
require "plumbus/driver"
|
4
|
+
require "plumbus/port"
|
5
|
+
require "plumbus/ports"
|
6
|
+
require "plumbus/loader"
|
7
|
+
|
8
|
+
require "plumbus/helpers/trim"
|
9
|
+
require "plumbus/helpers/remove_references"
|
10
|
+
|
11
|
+
module Plumbus
|
12
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'active_support/inflector'
|
2
|
+
|
3
|
+
module Plumbus
|
4
|
+
module Driver
|
5
|
+
#Available drivers
|
6
|
+
@@link_table = {}
|
7
|
+
|
8
|
+
def self.load driver_name
|
9
|
+
require driver_name.to_s
|
10
|
+
|
11
|
+
return self.add_link driver_name
|
12
|
+
rescue LoadError => e
|
13
|
+
raise LoadError, "Driver named #{driver_name.inspect} failed to load. Are you sure it's installed correctly?: #{e.inspect}"
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def self.add_link name
|
19
|
+
mod = name.to_s.classify.constantize
|
20
|
+
@@link_table[name.to_sym] = mod
|
21
|
+
$stderr.puts "[Driver #{name.inspect} linked]"
|
22
|
+
|
23
|
+
return mod
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.link_table() return @@link_table end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
#Used by actual drivers
|
2
|
+
module Plumbus
|
3
|
+
module DriverFacilities
|
4
|
+
#This is imported into the Port (which is a driver) interface
|
5
|
+
def invalidate_supported_actions
|
6
|
+
Ports.refresh_port_routing_table self
|
7
|
+
end
|
8
|
+
|
9
|
+
def emit_message sid, action, payload
|
10
|
+
Ports.forward_message port:self, sid:sid, action:action, payload:payload
|
11
|
+
end
|
12
|
+
|
13
|
+
def raise_signal name, info
|
14
|
+
Ports.signal port:self, name:name, info:info
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
class Hash
|
2
|
+
def remove_references! obj
|
3
|
+
self.select{|k, v| [Array, Hash].include? v.class}.each do |k, v|
|
4
|
+
v.remove_references! obj
|
5
|
+
end
|
6
|
+
self.select{|k, v| not [Array, Hash].include? v.class}.each do |k, v|
|
7
|
+
if v == obj
|
8
|
+
self.delete(k)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
self
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class Array
|
17
|
+
def remove_references! obj
|
18
|
+
self.select{|e| [Array, Hash].include? e.class}.each do |e|
|
19
|
+
e.remove_references! obj
|
20
|
+
end
|
21
|
+
|
22
|
+
self.select{|e| not [Array, Hash].include? e.class}.each_with_index do |e, i|
|
23
|
+
if e == obj
|
24
|
+
self.delete(obj)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
self
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
class Hash
|
2
|
+
#Removes all sub-hashes & arrays that have no objects in them.
|
3
|
+
def trim!
|
4
|
+
self.each do |k, v|
|
5
|
+
if v.class == Array
|
6
|
+
|
7
|
+
v.trim!
|
8
|
+
|
9
|
+
#Blank array, dump it
|
10
|
+
if v.count == 0
|
11
|
+
self.delete k
|
12
|
+
end
|
13
|
+
elsif v.class == Hash
|
14
|
+
v.trim!
|
15
|
+
|
16
|
+
if v.keys.count == 0
|
17
|
+
self.delete k
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
return self
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
class Array
|
27
|
+
def trim!
|
28
|
+
self.each do |e|
|
29
|
+
if e.class == Hash
|
30
|
+
e.trim!
|
31
|
+
|
32
|
+
if e.keys.count == 0
|
33
|
+
self.delete e
|
34
|
+
end
|
35
|
+
elsif e.class == Array
|
36
|
+
e.trim!
|
37
|
+
if e.count == 0
|
38
|
+
self.delete(e)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
return self
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Plumbus
|
2
|
+
module Loader
|
3
|
+
def self.load path
|
4
|
+
self.unload_all
|
5
|
+
dsl = LoaderDSL.new(path)
|
6
|
+
|
7
|
+
#Load ports
|
8
|
+
dsl.ports.each do |_port|
|
9
|
+
direction = _port[:direction]
|
10
|
+
driver = _port[:driver]
|
11
|
+
config_block = _port[:config_block]
|
12
|
+
|
13
|
+
#Load driver if not already loaded
|
14
|
+
klass = Driver.load driver
|
15
|
+
|
16
|
+
#Create instance of driver module
|
17
|
+
port = Port.new(driver_module_klass: klass, direction: direction)
|
18
|
+
port.config &config_block
|
19
|
+
port.attach!
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.unload_all
|
24
|
+
Ports.detach_all
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
class LoaderDSL
|
29
|
+
attr_reader :ports
|
30
|
+
|
31
|
+
def initialize src_path
|
32
|
+
@ports = []
|
33
|
+
contents = File.read(src_path)
|
34
|
+
|
35
|
+
instance_eval contents, src_path
|
36
|
+
end
|
37
|
+
|
38
|
+
def port direction, driver, &config_block
|
39
|
+
raise ArgumentError, "The given direction #{direction.inspect} was not a valid direction. Valid directions include #{Port::SUPPORTED_DIRECTIONS.inspect}" unless Port::SUPPORTED_DIRECTIONS.include? direction
|
40
|
+
raise ArgumentError, "No config block was given for the port #{direction.inspect}, #{driver.inspect}" unless config_block
|
41
|
+
@ports << {:direction => direction, :driver => driver, :config_block => config_block}
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
data/lib/plumbus/port.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'active_support/inflector'
|
2
|
+
|
3
|
+
#Contains the class for each port
|
4
|
+
module Plumbus
|
5
|
+
class Port
|
6
|
+
SUPPORTED_DIRECTIONS = [:request, :response]
|
7
|
+
|
8
|
+
attr_reader :driver_module_klass, :direction
|
9
|
+
|
10
|
+
def initialize driver_module_klass:, direction:
|
11
|
+
@driver_module_klass = driver_module_klass
|
12
|
+
@direction = direction
|
13
|
+
|
14
|
+
#@driver = Plumbus::PortDriver.new
|
15
|
+
extend DriverFacilities
|
16
|
+
extend "#{@driver_module_klass.name}::PlumbusHandlers".constantize
|
17
|
+
end
|
18
|
+
|
19
|
+
def attach!
|
20
|
+
Ports.attach_port self
|
21
|
+
end
|
22
|
+
|
23
|
+
#def detach!
|
24
|
+
#Ports.detach_port self
|
25
|
+
#end
|
26
|
+
|
27
|
+
def opposite_direction
|
28
|
+
@direction == :request ? :response : :request
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class PortDriver
|
33
|
+
#Plumbus extended handlers
|
34
|
+
###############################################################
|
35
|
+
def config &block
|
36
|
+
end
|
37
|
+
|
38
|
+
#Forward a message to the block for a sid
|
39
|
+
def forward_message sid, action, info
|
40
|
+
end
|
41
|
+
|
42
|
+
#Forward a signal, like disconnection
|
43
|
+
def forward_signal signal, info
|
44
|
+
end
|
45
|
+
|
46
|
+
def supported_actions
|
47
|
+
return @supported_actions
|
48
|
+
end
|
49
|
+
###############################################################
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,123 @@
|
|
1
|
+
#Ports manages the actual instances of the port classes
|
2
|
+
module Plumbus
|
3
|
+
module Ports
|
4
|
+
#Instances#########################################################
|
5
|
+
#Holds instances
|
6
|
+
@@instances = []
|
7
|
+
def self.instances; @@instances end
|
8
|
+
|
9
|
+
#Attach a port
|
10
|
+
def self.attach_port port
|
11
|
+
@@instances << port
|
12
|
+
refresh_port_routing_table port
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.refresh_port_routing_table port
|
16
|
+
evict_routing_table_references port
|
17
|
+
|
18
|
+
port.supported_actions.each do |action|
|
19
|
+
action = action.to_s
|
20
|
+
@@routing_table[port.opposite_direction][action] ||= []
|
21
|
+
@@routing_table[port.opposite_direction][action] << port
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.evict_routing_table_references port
|
26
|
+
@@routing_table[port.opposite_direction].remove_references! port
|
27
|
+
@@routing_table[port.opposite_direction].trim!
|
28
|
+
end
|
29
|
+
|
30
|
+
#def self.detach_port port
|
31
|
+
#evict_routing_table_references port
|
32
|
+
#@@instances -= [port]
|
33
|
+
#Needs to support the sid_to_ports
|
34
|
+
#end
|
35
|
+
|
36
|
+
def self.detach_all
|
37
|
+
@@instances.each do |port|
|
38
|
+
evict_routing_table_references port
|
39
|
+
end
|
40
|
+
@@instances = []
|
41
|
+
@@sid_to_ports = {}
|
42
|
+
end
|
43
|
+
|
44
|
+
#Routing###########################################################
|
45
|
+
#Holds routing table which maps from
|
46
|
+
@@routing_table = {
|
47
|
+
:request => {},
|
48
|
+
:response => {},
|
49
|
+
}
|
50
|
+
|
51
|
+
#Maps a sid into one request port and potentionally many response ports
|
52
|
+
#via [request, Set<response0, response1...>]
|
53
|
+
@@sid_to_ports = {}
|
54
|
+
|
55
|
+
#This returns the *response* (destination) ports for a request originating on the
|
56
|
+
#request side. I.e. it returns a response port.
|
57
|
+
def self.response_ports_for_request(action:)
|
58
|
+
action = action.to_s
|
59
|
+
@@routing_table[:request][action] || []
|
60
|
+
end
|
61
|
+
|
62
|
+
def self.response_port_for_request(action:)
|
63
|
+
return self.response_ports_for_request(action: action).first
|
64
|
+
end
|
65
|
+
|
66
|
+
def self.request_port_for_response(sid:)
|
67
|
+
return (@@sid_to_ports[sid] || [])[0]
|
68
|
+
end
|
69
|
+
|
70
|
+
def self.signal(port:, name:, info:)
|
71
|
+
case name
|
72
|
+
when :hangup
|
73
|
+
sid = info[:sid]
|
74
|
+
if ports = @@sid_to_ports[sid]
|
75
|
+
#Get request port (0)
|
76
|
+
req_port = ports[0]
|
77
|
+
|
78
|
+
#The request side hungup
|
79
|
+
set = ports[1]
|
80
|
+
if req_port == port
|
81
|
+
set.each do |p|
|
82
|
+
p.handle_signal :hangup_notice, {:sid => sid}
|
83
|
+
end
|
84
|
+
@@sid_to_ports.delete sid
|
85
|
+
else
|
86
|
+
#Remove ourselves (response) from response set
|
87
|
+
set.delete(port)
|
88
|
+
|
89
|
+
#Signal request of termination
|
90
|
+
if set.length == 0
|
91
|
+
@@sid_to_ports.delete sid
|
92
|
+
req_port.handle_signal :hangup_notice, {:sid => sid}
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def self.forward_message(port:, sid:, action:, payload:)
|
100
|
+
if port.direction == :request
|
101
|
+
if req_port = response_port_for_request(action: action)
|
102
|
+
if ports = @@sid_to_ports[sid]
|
103
|
+
ports[1] << req_port
|
104
|
+
else
|
105
|
+
req_set = Set.new [req_port]
|
106
|
+
@@sid_to_ports[sid] = [port, req_set]
|
107
|
+
end
|
108
|
+
req_port.handle_message sid, action.to_s, payload
|
109
|
+
else
|
110
|
+
#undeliverable
|
111
|
+
port.handle_signal :undeliverable, {sid: sid}
|
112
|
+
end
|
113
|
+
elsif port.direction == :response
|
114
|
+
if res_port = request_port_for_response(sid: sid)
|
115
|
+
res_port.handle_message sid, action, payload
|
116
|
+
else
|
117
|
+
#undeliverable
|
118
|
+
port.handle_signal :undeliverable, {sid: sid}
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
data/plumbus.gemspec
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'plumbus/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "plumbus"
|
8
|
+
spec.version = Plumbus::VERSION
|
9
|
+
spec.authors = ["seo"]
|
10
|
+
spec.email = ["seotownsend@icloud.com"]
|
11
|
+
|
12
|
+
|
13
|
+
spec.summary = "Plubus is an agnostic micro-service router."
|
14
|
+
spec.homepage = "http://github.com/sotownsend/plumbus"
|
15
|
+
spec.license = "MIT"
|
16
|
+
|
17
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
18
|
+
spec.bindir = "exe"
|
19
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
20
|
+
spec.require_paths = ["lib"]
|
21
|
+
|
22
|
+
spec.add_development_dependency "bundler", "~> 1.6"
|
23
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
24
|
+
spec.add_development_dependency "rspec", "~> 3.4"
|
25
|
+
spec.add_development_dependency "pry", "~> 0.10"
|
26
|
+
spec.add_runtime_dependency "activesupport", "~> 4.2"
|
27
|
+
end
|
metadata
ADDED
@@ -0,0 +1,135 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: plumbus
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- seo
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-03-14 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: '1.6'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.6'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.4'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.4'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: pry
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0.10'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0.10'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: activesupport
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '4.2'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '4.2'
|
83
|
+
description:
|
84
|
+
email:
|
85
|
+
- seotownsend@icloud.com
|
86
|
+
executables: []
|
87
|
+
extensions: []
|
88
|
+
extra_rdoc_files: []
|
89
|
+
files:
|
90
|
+
- ".gitignore"
|
91
|
+
- ".rspec"
|
92
|
+
- ".travis.yml"
|
93
|
+
- CODE_OF_CONDUCT.md
|
94
|
+
- Gemfile
|
95
|
+
- LICENSE.txt
|
96
|
+
- README.md
|
97
|
+
- Rakefile
|
98
|
+
- bin/plumbus
|
99
|
+
- docs/images/banner.png
|
100
|
+
- docs/images/request_response_drivers.png
|
101
|
+
- lib/plumbus.rb
|
102
|
+
- lib/plumbus/driver.rb
|
103
|
+
- lib/plumbus/driver_facilities.rb
|
104
|
+
- lib/plumbus/helpers/remove_references.rb
|
105
|
+
- lib/plumbus/helpers/trim.rb
|
106
|
+
- lib/plumbus/loader.rb
|
107
|
+
- lib/plumbus/port.rb
|
108
|
+
- lib/plumbus/ports.rb
|
109
|
+
- lib/plumbus/version.rb
|
110
|
+
- plumbus.gemspec
|
111
|
+
homepage: http://github.com/sotownsend/plumbus
|
112
|
+
licenses:
|
113
|
+
- MIT
|
114
|
+
metadata: {}
|
115
|
+
post_install_message:
|
116
|
+
rdoc_options: []
|
117
|
+
require_paths:
|
118
|
+
- lib
|
119
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
120
|
+
requirements:
|
121
|
+
- - ">="
|
122
|
+
- !ruby/object:Gem::Version
|
123
|
+
version: '0'
|
124
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
125
|
+
requirements:
|
126
|
+
- - ">="
|
127
|
+
- !ruby/object:Gem::Version
|
128
|
+
version: '0'
|
129
|
+
requirements: []
|
130
|
+
rubyforge_project:
|
131
|
+
rubygems_version: 2.4.8
|
132
|
+
signing_key:
|
133
|
+
specification_version: 4
|
134
|
+
summary: Plubus is an agnostic micro-service router.
|
135
|
+
test_files: []
|