cargosocket 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE.md +23 -0
- data/lib/cargosocket.rb +6 -0
- data/lib/cargosocket/extensions/cargobull.rb +25 -0
- data/lib/cargosocket/stream.rb +75 -0
- data/lib/cargosocket/stream_adapters/cargobull_adapter.rb +49 -0
- data/lib/cargosocket/stream_adapters/e_m_channel_adapter.rb +42 -0
- data/lib/cargosocket/test_helper.rb +1 -0
- metadata +78 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 47b62251f65e525e81eacb09114d5a02de7960df
|
4
|
+
data.tar.gz: e6b19b1a1e83babb0afb075178e2bec8b1c9f90d
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c072d7ec21a201c6b95cf06fb9a77ec599241154312a2b0eac9ea5deda9893fde5bf549b8429c042cabf9215c7503d854c156713e9ccb07c746a199e19095ac8
|
7
|
+
data.tar.gz: cdaef4f77b65a5236bf721445658bc7e5fc37a23bf68bcdab03918aa9ef91177c8ccf32197fa73ed0ab572e4cde6d1c877e1deeadf511ecb68c577e524195c90
|
data/LICENSE.md
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
Copyright (c) 2016, Matthias Geier
|
2
|
+
All rights reserved.
|
3
|
+
|
4
|
+
Redistribution and use in source and binary forms, with or without
|
5
|
+
modification, are permitted provided that the following conditions are met:
|
6
|
+
|
7
|
+
* Redistributions of source code must retain the above copyright notice, this
|
8
|
+
list of conditions and the following disclaimer.
|
9
|
+
|
10
|
+
* Redistributions in binary form must reproduce the above copyright notice,
|
11
|
+
this list of conditions and the following disclaimer in the documentation
|
12
|
+
and/or other materials provided with the distribution.
|
13
|
+
|
14
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
15
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
16
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
17
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
18
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
19
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
20
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
21
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
22
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
23
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
data/lib/cargosocket.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
|
2
|
+
module Cargobull
|
3
|
+
def self.streamer(cargoenv=env.get)
|
4
|
+
cargoenv[:session] = {}
|
5
|
+
cargoenv.freeze
|
6
|
+
Cargosocket::Stream.call(cargoenv)
|
7
|
+
end
|
8
|
+
|
9
|
+
module Dispatch
|
10
|
+
METHOD_MAP.merge!({
|
11
|
+
"CHANNELS" => :channels,
|
12
|
+
"REFERENCE" => :reference,
|
13
|
+
"SUBSCRIBE" => :subscribe,
|
14
|
+
"UNSUBSCRIBE" => :unsubscribe,
|
15
|
+
"ERROR" => :error,
|
16
|
+
"POP" => :pop,
|
17
|
+
"PUSH" => :push
|
18
|
+
})
|
19
|
+
|
20
|
+
def self.call_no_transform(env, *args)
|
21
|
+
dispatch(env, nil, nil, *args)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
@@ -0,0 +1,75 @@
|
|
1
|
+
|
2
|
+
module Cargosocket
|
3
|
+
module Stream
|
4
|
+
WS_OPT_KEYS = %w{host port debug secure secure_proxy tls_options
|
5
|
+
close_timeout outbound_limit}.map(&:to_sym)
|
6
|
+
|
7
|
+
def self.call(cargoenv)
|
8
|
+
raise "requires stream adapter" unless cargoenv[:adapter]
|
9
|
+
|
10
|
+
EM.run do
|
11
|
+
ws_config = WS_OPT_KEYS.reduce({}) do |acc, key|
|
12
|
+
acc[key] = cargoenv[key] if cargoenv.has_key?(key)
|
13
|
+
next acc
|
14
|
+
end
|
15
|
+
EM::WebSocket.run(ws_config){ |ws| config_socket(cargoenv, ws) }
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.config_socket(cargoenv, ws)
|
20
|
+
ws.onopen do |w|
|
21
|
+
path = w.path.sub(/^\//, '')
|
22
|
+
periodic_ping(cargoenv, ws)
|
23
|
+
EM.add_timer(0.5){ setup_connection(cargoenv, ws, path, w.query) }
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.periodic_ping(cargoenv, ws)
|
28
|
+
EM.add_periodic_timer(cargoenv[:ping_timer] || 5){ ws.ping }
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.setup_connection(cargoenv, ws, path, query)
|
32
|
+
cb_adapter = StreamAdapters::CargobullAdapter
|
33
|
+
|
34
|
+
channels = cb_adapter.channels(cargoenv, path, query)
|
35
|
+
ref = cb_adapter.reference(cargoenv, path, query)
|
36
|
+
if channels && ref
|
37
|
+
state = cargoenv[:adapter].subscribe(*channels) do |channel, message|
|
38
|
+
cb_adapter.pop(cargoenv, path, ref, channel, message,
|
39
|
+
&ws.method(:send))
|
40
|
+
end
|
41
|
+
|
42
|
+
state.keys.each do |channel|
|
43
|
+
cb_adapter.subscribe(cargoenv, path, ref, channel) do |v|
|
44
|
+
cargoenv[:adapter].push(channel, v)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
ws.onmessage do |message|
|
49
|
+
state.keys.each do |channel|
|
50
|
+
cb_adapter.push(cargoenv, path, ref, channel,
|
51
|
+
message.strip){ |v| cargoenv[:adapter].push(channel, v) }
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
ws.onerror do |error|
|
56
|
+
cargoenv[:adapter].unsubscribe(state) do |channel|
|
57
|
+
cb_adapter.error(cargoenv, path, ref, channel) do |v|
|
58
|
+
cargoenv[:adapter].push(channel, v)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
ws.onclose do
|
64
|
+
cargoenv[:adapter].unsubscribe(state) do |channel|
|
65
|
+
cb_adapter.unsubscribe(cargoenv, path, ref, channel) do |v|
|
66
|
+
cargoenv[:adapter].push(channel, v)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
else
|
71
|
+
ws.close(3001, channels.inspect || ref.to_s || "unknown")
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
|
2
|
+
module Cargosocket
|
3
|
+
module StreamAdapters
|
4
|
+
module CargobullAdapter
|
5
|
+
def self.if_value(value)
|
6
|
+
return if value.last.nil?
|
7
|
+
yield(value.last)
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.dispatch_to(m, *args)
|
11
|
+
Cargobull::Dispatch.send(m, *args)
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.channels(cargoenv, path, query)
|
15
|
+
r = dispatch_to(:call_no_transform, cargoenv, "CHANNELS", path, query)
|
16
|
+
if r.first == 200 && r.last.is_a?(Array) && !r.last.empty?
|
17
|
+
r.last.map(&:to_sym)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.reference(cargoenv, path, query)
|
22
|
+
r = dispatch_to(:call_no_transform, cargoenv, "REFERENCE", path, query)
|
23
|
+
if r.first == 200
|
24
|
+
r.last
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.subscribe(cargoenv, *args)
|
29
|
+
if_value(dispatch_to(:call, cargoenv, "SUBSCRIBE", *args), &Proc.new)
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.unsubscribe(cargoenv, *args)
|
33
|
+
if_value(dispatch_to(:call, cargoenv, "UNSUBSCRIBE", *args), &Proc.new)
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.error(cargoenv, *args)
|
37
|
+
if_value(dispatch_to(:call, cargoenv, "ERROR", *args), &Proc.new)
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.push(cargoenv, *args)
|
41
|
+
if_value(dispatch_to(:call, cargoenv, "PUSH", *args), &Proc.new)
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.pop(cargoenv, *args)
|
45
|
+
if_value(dispatch_to(:call, cargoenv, "POP", *args), &Proc.new)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
|
2
|
+
module Cargosocket
|
3
|
+
module StreamAdapters
|
4
|
+
module EMChannelAdapter
|
5
|
+
CHANNELS = {}
|
6
|
+
DISPATCHERS = []
|
7
|
+
|
8
|
+
def self.dispatch(to)
|
9
|
+
# DISPATCHERS << to
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.push(*to, message)
|
13
|
+
to.each do |channel|
|
14
|
+
if channel.is_a?(Symbol)
|
15
|
+
CHANNELS[channel].push(message) if CHANNELS.has_key?(channel)
|
16
|
+
else
|
17
|
+
# channel.push(message)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.subscribe(*to)
|
23
|
+
callback = Proc.new
|
24
|
+
return to.reduce({}) do |acc, channel|
|
25
|
+
CHANNELS[channel] ||= EM::Channel.new
|
26
|
+
acc[channel] = CHANNELS[channel].subscribe(&callback.curry[channel])
|
27
|
+
next acc
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.unsubscribe(from)
|
32
|
+
from.each do |channel, cid|
|
33
|
+
yield(channel)
|
34
|
+
CHANNELS[channel].unsubscribe(cid)
|
35
|
+
if CHANNELS[channel].num_subscribers == DISPATCHERS.count
|
36
|
+
CHANNELS.delete(channel)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'cargosocket'
|
metadata
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: cargosocket
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Matthias Geier
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-04-14 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: em-websocket
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.5.1
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.5.1
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: cargobull
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0.3'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0.3'
|
41
|
+
description:
|
42
|
+
email:
|
43
|
+
executables: []
|
44
|
+
extensions: []
|
45
|
+
extra_rdoc_files: []
|
46
|
+
files:
|
47
|
+
- LICENSE.md
|
48
|
+
- lib/cargosocket.rb
|
49
|
+
- lib/cargosocket/extensions/cargobull.rb
|
50
|
+
- lib/cargosocket/stream.rb
|
51
|
+
- lib/cargosocket/stream_adapters/cargobull_adapter.rb
|
52
|
+
- lib/cargosocket/stream_adapters/e_m_channel_adapter.rb
|
53
|
+
- lib/cargosocket/test_helper.rb
|
54
|
+
homepage: https://github.com/matthias-geier/cargosocket
|
55
|
+
licenses:
|
56
|
+
- BSD-2
|
57
|
+
metadata: {}
|
58
|
+
post_install_message:
|
59
|
+
rdoc_options: []
|
60
|
+
require_paths:
|
61
|
+
- lib
|
62
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
63
|
+
requirements:
|
64
|
+
- - ">="
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: 2.1.0
|
67
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
68
|
+
requirements:
|
69
|
+
- - ">="
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
version: '0'
|
72
|
+
requirements: []
|
73
|
+
rubyforge_project:
|
74
|
+
rubygems_version: 2.4.5.1
|
75
|
+
signing_key:
|
76
|
+
specification_version: 4
|
77
|
+
summary: Middleware to create a websocket service
|
78
|
+
test_files: []
|