wamp_rails 0.0.2

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: 19e8fd3cd6bce5cd796b61ffd66bf192e9111d8c
4
+ data.tar.gz: 074bc2d2a48553b137d91aa5891d6460c76c7b47
5
+ SHA512:
6
+ metadata.gz: 41802f7ba79647f9b93778fb368c667126aa8ff5550d8f7c8b956b17a99ce56b48182e719e7938cf5645ceb25449c5e4b80328d1654b93cecb3ff4b21a36c861
7
+ data.tar.gz: f08c277926435a50a89e0307274d9a8dc49b3049d1daea47416a8e331463dbfe2309141b4502211e58e14d0fcdd895d9e3ec820e62fc35be0d0edd832479ad23
@@ -0,0 +1,10 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ .idea
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.3.0
5
+ before_install: gem install bundler -v 1.13.2
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in wamp_rails.gemspec
4
+ gemspec
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 Eric Chapman
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,142 @@
1
+ # WampRails
2
+
3
+ This library allows the GEM [wamp_client](https://github.com/ericchapman/ruby_wamp_client)
4
+ to be integrated into a Rails application.
5
+
6
+ The 'wamp_client' GEM uses the Event Machine implementation of Web Sockets to
7
+ connect to the WAMP router. This requires the Rails application to spin off
8
+ an independent thread where the EM reactor will run.
9
+
10
+ The library also wraps the connection logic under the library so that the
11
+ Rails application doesn't need to handle it.
12
+
13
+ All calls to the library are implemented as "commands". When a call is made to
14
+ the client, the library will create a command and do the following
15
+
16
+ - If the thread is the same thread as the EM reactor, it will immediately
17
+ execute the command
18
+ - Else place the command into the queue that the reactor will check on every
19
+ tick
20
+
21
+ This ensures that the Rails application does not need to worry about the thread.
22
+
23
+ This however has the side effect where all calls to the library are executed
24
+ synchronously (they will block the current thread) unless the callback is nil.
25
+
26
+ ## Initialize
27
+
28
+ The client is initialized as shown below. The options are the same as
29
+ 'wamp_client' with the addition of the 'name' option which is used for
30
+ logging.
31
+
32
+ ``` ruby
33
+ options = {
34
+ name: 'main router',
35
+ uri: 'ws://router.example.com,
36
+ realm: 'realm1'
37
+ }
38
+
39
+ wamp_client = WampRails::Client.new(options)
40
+ wamp_client.open
41
+ ```
42
+
43
+ ## Routes
44
+
45
+ Routes are created using the 'routes' block. This must be called BEFORE
46
+ 'open'. Below is an example
47
+
48
+ ``` ruby
49
+ options = {
50
+ uri: 'ws://router.example.com,
51
+ realm: 'realm1'
52
+ }
53
+
54
+ wamp_client = WampRails::Client.new(options)
55
+
56
+ # Configure the Routes
57
+ wamp_client.routes do
58
+ add_subscription 'topic', MySubscriptionClass
59
+ add_subscription 'topic.*', MyWildcardSubscriptionClass, {wildcard: true}
60
+
61
+ add_procedure 'procedure.', MyPrefixProcedureClass, {prefix: true}
62
+ end
63
+
64
+ wamp_client.open
65
+ ```
66
+
67
+ When 'routes' is used, the client object will automatically re-register/subscribe
68
+ to the procedures/topics on reconnect. Otherwise if 'register' or 'subscribe'
69
+ are going to be called directly, then the system must wait for the connection
70
+ to become active by calling
71
+
72
+ ``` ruby
73
+ wamp_client.wait_for_active
74
+ ```
75
+
76
+ ## Commands
77
+
78
+ The client currently supports the following commands from the WampClient library
79
+
80
+ - call
81
+ - publish
82
+ - register
83
+ - subscribe
84
+
85
+ The methods have the same parameters as the WampClient library
86
+
87
+ ## Controllers
88
+
89
+ The 'register' and 'subscribe' commands require 'handlers' to be implemented.
90
+ In order to ensure thread safety and consistency with Rails, the handlers
91
+ are implemented as 'controller' classes.
92
+
93
+ When a call or publish is received, the library will instantiate the supplied
94
+ class with following methods available
95
+
96
+ - args (Array) - The arguments
97
+ - kwargs (Hash) - The keyword arguments
98
+ - details (Hash) - The details
99
+ - client [WampRails::Client) - The client. This can be used if the
100
+ handler needs to send a Wamp message
101
+
102
+ ### Register
103
+ To create a register controller, create a class that subclasses from
104
+ 'WampRails::Controller::Procedure' and implements 'handler'. See below
105
+
106
+ ``` ruby
107
+ class MyRegisterController < WampRails:::Controller::Procedure
108
+
109
+ def handler
110
+ the_args = self.args
111
+ the_kwargs = self.kwargs
112
+ the_details = self.details
113
+ the_client = self.client
114
+
115
+ # Do Something
116
+
117
+ # Return the result (see WampClient for more details on implementing procedures)
118
+ true
119
+ end
120
+
121
+ end
122
+ ```
123
+
124
+ ### Subscribe
125
+ To create a subscribe controller, create a class that subclasses from
126
+ 'WampRails::Controller::Subscription' and implements 'handler'. See below
127
+
128
+ ``` ruby
129
+ class MySubscribeController < WampRails:::Controller::Subscription
130
+
131
+ def handler
132
+ the_args = self.args
133
+ the_kwargs = self.kwargs
134
+ the_details = self.details
135
+ the_client = self.client
136
+
137
+ # Do Something
138
+
139
+ end
140
+
141
+ end
142
+ ```
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "wamp_rails"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,40 @@
1
+ =begin
2
+
3
+ Copyright (c) 2016 Eric Chapman
4
+
5
+ MIT License
6
+
7
+ Permission is hereby granted, free of charge, to any person obtaining
8
+ a copy of this software and associated documentation files (the
9
+ "Software"), to deal in the Software without restriction, including
10
+ without limitation the rights to use, copy, modify, merge, publish,
11
+ distribute, sublicense, and/or sell copies of the Software, and to
12
+ permit persons to whom the Software is furnished to do so, subject to
13
+ the following conditions:
14
+
15
+ The above copyright notice and this permission notice shall be
16
+ included in all copies or substantial portions of the Software.
17
+
18
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
22
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25
+
26
+ =end
27
+
28
+ require 'wamp_rails/version'
29
+ require 'wamp_rails/error'
30
+ require 'wamp_rails/commands/base_command'
31
+ require 'wamp_rails/commands/base_handler'
32
+ require 'wamp_rails/commands/call'
33
+ require 'wamp_rails/commands/publish'
34
+ require 'wamp_rails/commands/register'
35
+ require 'wamp_rails/commands/subscribe'
36
+ require 'wamp_rails/controllers/base_controller'
37
+ require 'wamp_rails/controllers/procedure'
38
+ require 'wamp_rails/controllers/subscription'
39
+ require 'wamp_rails/client'
40
+
@@ -0,0 +1,206 @@
1
+ require 'thread'
2
+ require 'wamp_client/connection'
3
+
4
+ module WampRails
5
+
6
+ class Client
7
+ attr_accessor :options, :wamp, :cmd_queue, :thread, :name, :active, :verbose
8
+ attr_accessor :registrations, :subscriptions
9
+
10
+ # Called when the WAMP session presents a challenge
11
+ # @param authmethod [String]
12
+ # @param extra [Hash]
13
+ @on_challenge
14
+ def on_challenge(&on_challenge)
15
+ @on_challenge = on_challenge
16
+ end
17
+
18
+ # Returns true if the connection is active
19
+ def is_active?
20
+ self.active
21
+ end
22
+
23
+ # Waits for the session to become active
24
+ def wait_for_active
25
+ until self.is_active?
26
+ end
27
+ end
28
+
29
+ # Constructor for creating a client. Options are
30
+ # @param options [Hash] The different options to pass to the connection
31
+ # @option options [String] :name - The name of the WAMP Client
32
+ # @option options [WampClient::Connection] :wamp - Allows a different WAMP to be passed in
33
+ # @option options [String] :uri The uri of the WAMP router to connect to
34
+ # @option options [String] :realm The realm to connect to
35
+ # @option options [String, nil] :protocol The protocol (default if wamp.2.json)
36
+ # @option options [String, nil] :authid The id to authenticate with
37
+ # @option options [Array, nil] :authmethods The different auth methods that the client supports
38
+ # @option options [Hash] :headers Custom headers to include during the connection
39
+ # @option options [WampClient::Serializer::Base] :serializer The serializer to use (default is json)
40
+ def initialize(options=nil)
41
+ self.options = options || {}
42
+ self.cmd_queue = Queue.new
43
+ self.registrations = []
44
+ self.subscriptions = []
45
+ self.name = self.options[:name] || 'default'
46
+ self.wamp = self.options[:wamp] || WampClient::Connection.new(self.options)
47
+ self.verbose = self.options[:verbose]
48
+ self.active = false
49
+
50
+ # WAMP initialization. Note that all callbacks are called on the reactor thread
51
+ self.wamp.on_connect do
52
+ puts "WAMP Rails Client #{self.name} connection established" if self.verbose
53
+ end
54
+
55
+ self.wamp.on_join do |session, details|
56
+ puts "WAMP Rails Client #{self.name} was established" if self.verbose
57
+ self.active = true
58
+
59
+ # Register the procedures
60
+ self.registrations.each do |registration|
61
+ self._queue_command(registration)
62
+ end
63
+
64
+ # Subscribe to the topics
65
+ self.subscriptions.each do |subscription|
66
+ self._queue_command(subscription)
67
+ end
68
+ end
69
+
70
+ self.wamp.on_leave do |reason, details|
71
+ puts "WAMP Rails Client #{self.name} left because '#{reason}'" if self.verbose
72
+ self.active = false
73
+ end
74
+
75
+ self.wamp.on_disconnect do |reason|
76
+ puts "WAMP Rails Client #{self.name} disconnected because '#{reason}'" if self.verbose
77
+ self.active = false
78
+ end
79
+
80
+ self.wamp.on_challenge do |authmethod, extra|
81
+ if @on_challenge
82
+ @on_challenge.call(authmethod, extra)
83
+ else
84
+ puts "WAMP Rails Client #{self.name} auth challenge was received but no method was implemented." if self.verbose
85
+ nil
86
+ end
87
+ end
88
+
89
+ # Catch SIGINT
90
+ Signal.trap('INT') { self.close }
91
+ Signal.trap('TERM') { self.close }
92
+ end
93
+
94
+ # Opens the connection
95
+ def open
96
+ # Create the background thread
97
+ self.thread = Thread.new do
98
+ EM.tick_loop do
99
+ unless self.cmd_queue.empty?
100
+ command = self.cmd_queue.pop
101
+ self._execute_command(command)
102
+ end
103
+ end
104
+ self.wamp.open
105
+ end
106
+ end
107
+
108
+ # Closes the connection
109
+ def close
110
+ self.wamp.close
111
+ end
112
+
113
+ #region Route Methods
114
+
115
+ # Used to configure the routes for the client
116
+ def routes(&block)
117
+ self.instance_eval(&block)
118
+ end
119
+
120
+ # Adds a procedure to the client
121
+ def add_procedure(procedure, klass, options=nil)
122
+ options ||= {}
123
+ raise WampRails::Error.new('"add_procedure" must be called BEFORE "open"') if self.thread
124
+ self.registrations << WampRails::Command::Register.new(procedure, klass, options, self)
125
+ end
126
+
127
+ # Adds a subscription to the client
128
+ def add_subscription(topic, klass, options=nil)
129
+ options ||= {}
130
+ raise WampRails::Error.new('"add_subscription" must be called BEFORE "open"') if self.thread
131
+ self.subscriptions << WampRails::Command::Subscribe.new(topic, klass, options, self)
132
+ end
133
+
134
+ #endregion
135
+
136
+ #region WAMP Methods
137
+
138
+ # Performs a WAMP call
139
+ # @note This method is blocking if the callback is not nil
140
+ def call(procedure, args=nil, kwargs=nil, options={}, &callback)
141
+ command = WampRails::Command::Call.new(procedure, args, kwargs, options, self)
142
+ self._queue_command(command, callback)
143
+ end
144
+
145
+ # Performs a WAMP publish
146
+ # @note This method is blocking if the callback is not nil
147
+ def publish(topic, args=nil, kwargs=nil, options={}, &callback)
148
+ command = WampRails::Command::Publish.new(topic, args, kwargs, options, self)
149
+ self._queue_command(command, callback)
150
+ end
151
+
152
+ # Performs a WAMP register
153
+ # @note This method is blocking if the callback is not nil
154
+ def register(procedure, klass, options={}, &callback)
155
+ command = WampRails::Command::Register.new(procedure, klass, options, self)
156
+ self._queue_command(command, callback)
157
+ end
158
+
159
+ # Performs a WAMP subscribe
160
+ # @note This method is blocking if the callback is not nil
161
+ def subscribe(topic, klass, options={}, &callback)
162
+ command = WampRails::Command::Subscribe.new(topic, klass, options, self)
163
+ self._queue_command(command, callback)
164
+ end
165
+
166
+ #endregion
167
+
168
+ #region Private Methods
169
+
170
+ # Queues the command and blocks it the callback is not nil
171
+ # @param [WampRails::Command::Base] - The command to queue
172
+ # @param [Block] - The block to call when complete
173
+ def _queue_command(command, callback=nil)
174
+
175
+ # If the current thread is the EM thread, execute the command. Else put it in the queue
176
+ if self.thread == Thread.current
177
+ self._execute_command(command)
178
+ else
179
+ self.cmd_queue.push(command)
180
+ end
181
+
182
+ # If the callback is defined, block until it finishes
183
+ if callback
184
+ callback_args = command.queue.pop
185
+ callback.call(callback_args.result, callback_args.error, callback_args.details)
186
+ end
187
+ end
188
+
189
+ # Executes the command
190
+ # @param [WampRails::Command::Base] - The command to execute
191
+ def _execute_command(command)
192
+ begin
193
+ unless self.is_active?
194
+ raise WampRails::Error.new("WAMP Rails Client #{self.name} is currently not active.")
195
+ end
196
+
197
+ command.execute
198
+ rescue Exception => e
199
+ puts e.to_s if self.verbose
200
+ command.callback(nil, {error: 'wamp_rails.error', args: [e.to_s], kwargs: nil}, nil)
201
+ end
202
+ end
203
+ #endregion
204
+
205
+ end
206
+ end
@@ -0,0 +1,39 @@
1
+ module WampRails
2
+ module Command
3
+ class BaseCommand
4
+ attr_accessor :queue, :client
5
+
6
+ # The callback object to place in the queue
7
+ class CallbackArgs
8
+ attr_accessor :result, :error, :details
9
+ def initialize(result, error, details)
10
+ self.result = result
11
+ self.error = error
12
+ self.details = details
13
+ end
14
+ end
15
+
16
+ def initialize(client)
17
+ self.queue = Queue.new
18
+ self.client = client
19
+ end
20
+
21
+ # Returns the session from the client
22
+ def session
23
+ self.client.wamp.session
24
+ end
25
+
26
+
27
+ # Executes the command. This is called by the library in the EM Thread
28
+ def execute
29
+ # Override when sub classing
30
+ end
31
+
32
+ # Used in sub-classes to handle the response
33
+ def callback(result, error, details)
34
+ self.queue.push(CallbackArgs.new(result, error, details))
35
+ end
36
+
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,20 @@
1
+ module WampRails
2
+ module Command
3
+ class BaseHandler < BaseCommand
4
+ attr_accessor :klass
5
+
6
+ def handler
7
+ lambda { |args, kwargs, details|
8
+ object = klass.new(args, kwargs, details, client)
9
+ object.handler
10
+ }
11
+ end
12
+
13
+ def initialize(client, klass)
14
+ super(client)
15
+ self.klass = klass
16
+ end
17
+
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,24 @@
1
+ module WampRails
2
+ module Command
3
+
4
+ class Call < BaseCommand
5
+ attr_accessor :procedure, :args, :kwargs, :options
6
+
7
+ def initialize(procedure, args, kwargs, options, client)
8
+ super(client)
9
+ self.procedure = procedure
10
+ self.args = args
11
+ self.kwargs = kwargs
12
+ self.options = options
13
+ end
14
+
15
+ def execute
16
+ session.call(procedure, args, kwargs, options) do |result, error, details|
17
+ self.callback(result, error, details)
18
+ end
19
+ end
20
+
21
+ end
22
+
23
+ end
24
+ end
@@ -0,0 +1,24 @@
1
+ module WampRails
2
+ module Command
3
+
4
+ class Publish < BaseCommand
5
+ attr_accessor :topic, :args, :kwargs, :options
6
+
7
+ def initialize(topic, args, kwargs, options, client)
8
+ super(client)
9
+ self.topic = topic
10
+ self.args = args
11
+ self.kwargs = kwargs
12
+ self.options = options
13
+ end
14
+
15
+ def execute
16
+ session.publish(topic, args, kwargs, options) do |result, error, details|
17
+ self.callback(result, error, details)
18
+ end
19
+ end
20
+
21
+ end
22
+
23
+ end
24
+ end
@@ -0,0 +1,23 @@
1
+ module WampRails
2
+ module Command
3
+ class Register < BaseHandler
4
+ attr_accessor :procedure, :options
5
+
6
+ def initialize(procedure, klass, options, client)
7
+ super(client, klass)
8
+ self.procedure = procedure
9
+ self.options = options
10
+
11
+ unless self.klass < WampRails::Controller::Procedure
12
+ raise WampRails::Error.new('klass must be a WampRails::Controller::Procedure class')
13
+ end
14
+ end
15
+
16
+ def execute
17
+ session.register(procedure, handler, options) do |result, error, details|
18
+ self.callback(result, error, details)
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,23 @@
1
+ module WampRails
2
+ module Command
3
+ class Subscribe < BaseHandler
4
+ attr_accessor :topic, :klass, :options
5
+
6
+ def initialize(topic, klass, options, client)
7
+ super(client, klass)
8
+ self.topic = topic
9
+ self.options = options
10
+
11
+ unless self.klass < WampRails::Controller::Subscription
12
+ raise WampRails::Error.new('klass must be a WampRails::Controller::Subscription class')
13
+ end
14
+ end
15
+
16
+ def execute
17
+ session.subscribe(topic, handler, options) do |result, error, details|
18
+ self.callback(result, error, details)
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,34 @@
1
+ module WampRails
2
+ module Controller
3
+ class BaseController
4
+
5
+ def initialize(args, kwargs, details, client)
6
+ @args = args || []
7
+ @kwargs = kwargs || {}
8
+ @details = details || {}
9
+ @client = client
10
+ end
11
+
12
+ def handler
13
+ raise WampRails::Error.new('WampRails::Controller::Base is an abstract class. "handler" must be defined')
14
+ end
15
+
16
+ def args
17
+ @args
18
+ end
19
+
20
+ def kwargs
21
+ @kwargs
22
+ end
23
+
24
+ def details
25
+ @details
26
+ end
27
+
28
+ def client
29
+ @client
30
+ end
31
+
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,9 @@
1
+ require 'wamp_rails/error'
2
+
3
+ module WampRails
4
+ module Controller
5
+ class Procedure < BaseController
6
+
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ require 'wamp_rails'
2
+
3
+ module WampRails
4
+ module Controller
5
+ class Subscription < BaseController
6
+
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,5 @@
1
+ module WampRails
2
+ class Error < Exception
3
+
4
+ end
5
+ end
@@ -0,0 +1,3 @@
1
+ module WampRails
2
+ VERSION = '0.0.2'
3
+ end
@@ -0,0 +1,129 @@
1
+ require 'spec_helper'
2
+
3
+ describe WampRails::Client do
4
+ before(:each) {
5
+ @client = described_class.new({wamp: WampRailsTest::TestConnection.new({})})
6
+ @client.routes do
7
+ add_procedure 'route.procedure', WampRailsTest::TestProcedureController
8
+ add_subscription 'route.topic', WampRailsTest::TestSubscriptionController
9
+ end
10
+ @client.open
11
+ @client.wait_for_active
12
+ }
13
+
14
+ after(:each) {
15
+ @client.close
16
+ }
17
+
18
+ describe 'commands' do
19
+ describe 'call' do
20
+ it 'sends a call command' do
21
+ @client.call('test.procedure', ['test'], {test: true}) do |result, error, details|
22
+ expect(result.count).to eq(4)
23
+ expect(result[0]).to eq('test.procedure')
24
+ expect(error).to be_nil
25
+ end
26
+ end
27
+
28
+ it 'processes an error' do
29
+ @client.call('test.procedure', ['test'], {test: true}, {error: true}) do |result, error, details|
30
+ expect(result).to be_nil
31
+ expect(error[:error]).to eq('wamp_rails.error')
32
+ expect(error[:args][0]).to eq('test exception')
33
+ end
34
+ end
35
+
36
+ end
37
+
38
+ describe 'publish' do
39
+ it 'sends a publish command' do
40
+ @client.publish('test.topic', ['test'], {test: true}) do |result, error, details|
41
+ expect(result.count).to eq(4)
42
+ expect(result[0]).to eq('test.topic')
43
+ expect(error).to be_nil
44
+ end
45
+ end
46
+
47
+ it 'processes an error' do
48
+ @client.publish('test.topic', ['test'], {test: true}, {error: true}) do |result, error, details|
49
+ expect(result).to be_nil
50
+ expect(error[:error]).to eq('wamp_rails.error')
51
+ expect(error[:args][0]).to eq('test exception')
52
+ end
53
+ end
54
+ end
55
+
56
+ describe 'register' do
57
+ it 'sends a register command' do
58
+ @client.register('test.procedure', WampRailsTest::TestProcedureController, {test: true}) do |result, error, details|
59
+ expect(result.count).to eq(4)
60
+ expect(result[0]).to eq('test.procedure')
61
+ expect(error).to be_nil
62
+ end
63
+ end
64
+
65
+ it 'processes an error' do
66
+ @client.register('test.procedure', WampRailsTest::TestProcedureController, {error: true}) do |result, error, details|
67
+ expect(result).to be_nil
68
+ expect(error[:error]).to eq('wamp_rails.error')
69
+ expect(error[:args][0]).to eq('test exception')
70
+ end
71
+ end
72
+
73
+ it 'raises an error when the class is incorrect' do
74
+ expect {
75
+ @client.register('test.procedure', Exception) do |result, error, details|
76
+ expect(result).to be_nil
77
+ expect(error[:error]).to eq('wamp_rails.error')
78
+ end
79
+ }.to raise_exception(WampRails::Error)
80
+ end
81
+ end
82
+
83
+ describe 'subscribe' do
84
+ it 'sends a subscribe command' do
85
+ @client.subscribe('test.topic', WampRailsTest::TestSubscriptionController, {test: true}) do |result, error, details|
86
+ expect(result.count).to eq(3)
87
+ expect(result[0]).to eq('test.topic')
88
+ expect(error).to be_nil
89
+ end
90
+ end
91
+
92
+ it 'processes an error' do
93
+ @client.subscribe('test.topic', WampRailsTest::TestSubscriptionController, {error: true}) do |result, error, details|
94
+ expect(result).to be_nil
95
+ expect(error[:error]).to eq('wamp_rails.error')
96
+ expect(error[:args][0]).to eq('test exception')
97
+ end
98
+ end
99
+
100
+ it 'raises an error when the class is incorrect' do
101
+ expect {
102
+ @client.subscribe('test.topic', Exception) do |result, error, details|
103
+ expect(result).to be_nil
104
+ expect(error[:error]).to eq('wamp_rails.error')
105
+ end
106
+ }.to raise_exception(Exception)
107
+ end
108
+ end
109
+
110
+ describe 'controllers' do
111
+
112
+ describe 'register' do
113
+ it 'calls the controller' do
114
+ @client.call('route.procedure', [4], {number: 5}) do |r, e, d|
115
+ expect(r[0][0]).to eq(9)
116
+ end
117
+ end
118
+ end
119
+
120
+ describe 'subscribe' do
121
+ it 'calls the controller' do
122
+ @client.publish('route.topic', [5], {number:4}) do |r, e, d|
123
+ expect(WampRailsTest::TestSubscriptionController.count).to eq(9)
124
+ end
125
+ end
126
+ end
127
+ end
128
+ end
129
+ end
@@ -0,0 +1,10 @@
1
+ require 'simplecov'
2
+ SimpleCov.start do
3
+ add_filter 'spec/'
4
+ end
5
+
6
+ require_relative '../lib/wamp_rails'
7
+
8
+ require 'wamp_rails'
9
+
10
+ Dir[File.expand_path('spec/support/**/*.rb')].each { |f| require f }
@@ -0,0 +1,18 @@
1
+ require 'wamp_client/connection'
2
+
3
+ module WampRailsTest
4
+ class TestConnection < WampClient::Connection
5
+
6
+ def open
7
+ EM.run do
8
+ self.session = WampRailsTest::TestSession.new
9
+ @on_join.call(self.session, {})
10
+ end
11
+ end
12
+
13
+ def close
14
+ EM.stop
15
+ end
16
+
17
+ end
18
+ end
@@ -0,0 +1,11 @@
1
+ require 'wamp_rails'
2
+
3
+ module WampRailsTest
4
+ class TestProcedureController < WampRails::Controller::Procedure
5
+
6
+ def handler
7
+ [(args[0] + kwargs[:number]), details, client]
8
+ end
9
+
10
+ end
11
+ end
@@ -0,0 +1,60 @@
1
+ module WampRailsTest
2
+ class TestSession
3
+ attr_accessor :calls, :registrations, :publishes, :subscriptions
4
+
5
+ def initialize
6
+ self.clear
7
+ end
8
+
9
+ def is_open?
10
+ true
11
+ end
12
+
13
+ def clear
14
+ self.calls = {}
15
+ self.registrations = {}
16
+ self.publishes = {}
17
+ self.subscriptions = {}
18
+ end
19
+
20
+ def call(procedure, args, kwargs, options, &callback)
21
+ self.calls[procedure] = { p: procedure, a: args, k: kwargs, o:options, c: callback }
22
+ raise Exception.new('test exception') if options[:error]
23
+
24
+ object = self.registrations[procedure]
25
+ handler = object != nil ? object[:h] : nil
26
+ if handler
27
+ response = handler.call(args, kwargs, {procedure: procedure, session: self})
28
+ callback.call([response], nil, {}) if callback
29
+ else
30
+ callback.call([procedure, args, kwargs, options], nil, {}) if callback
31
+ end
32
+ end
33
+
34
+ def register(procedure, handler, options=nil, interrupt=nil, &callback)
35
+ self.registrations[procedure] = { p: procedure, h: handler, o:options, i: interrupt, c:callback }
36
+ raise Exception.new('test exception') if options[:error]
37
+ callback.call([procedure, handler, options, interrupt], nil, {}) if callback
38
+ end
39
+
40
+ def publish(topic, args, kwargs, options, &callback)
41
+ self.publishes[topic] = { t: topic, a: args, k: kwargs, o:options, c: callback }
42
+ raise Exception.new('test exception') if options[:error]
43
+
44
+ object = self.subscriptions[topic]
45
+ handler = object != nil ? object[:h] : nil
46
+ if handler
47
+ handler.call(args, kwargs, {topic: topic, session: self})
48
+ callback.call([true], nil, {}) if callback
49
+ else
50
+ callback.call([topic, args, kwargs, options], nil, {}) if callback
51
+ end
52
+ end
53
+
54
+ def subscribe(topic, handler, options={}, &callback)
55
+ self.subscriptions[topic] = { t: topic, h: handler, o:options, c:callback }
56
+ raise Exception.new('test exception') if options[:error]
57
+ callback.call([topic, handler, options], nil, {}) if callback
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,15 @@
1
+ module WampRailsTest
2
+ class TestSubscriptionController < WampRails::Controller::Subscription
3
+ @@count = 0
4
+
5
+ def self.count
6
+ @@count
7
+ end
8
+
9
+ def handler
10
+ @@count = args[0] + kwargs[:number]
11
+ nil
12
+ end
13
+
14
+ end
15
+ end
@@ -0,0 +1,11 @@
1
+ require "spec_helper"
2
+
3
+ describe WampRails do
4
+ it "has a version number" do
5
+ expect(WampRails::VERSION).not_to be nil
6
+ end
7
+
8
+ it "does something useful" do
9
+ expect(false).to eq(true)
10
+ end
11
+ end
@@ -0,0 +1,28 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'wamp_rails/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "wamp_rails"
8
+ spec.version = WampRails::VERSION
9
+ spec.authors = ['Eric Chapman']
10
+ spec.email = ['eric.chappy@gmail.com']
11
+ spec.summary = %q{Web Application Messaging Protocol Client for Rails}
12
+ spec.description = %q{An implementation of The Web Application Messaging Protocol (WAMP)}
13
+ spec.homepage = 'https://github.com/ericchapman/ruby_wamp_rails'
14
+ spec.license = 'MIT'
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ['lib']
20
+
21
+ spec.add_development_dependency 'bundler', '~> 1.7'
22
+ spec.add_development_dependency 'rake', '~> 10.0'
23
+ spec.add_development_dependency 'rspec'
24
+ spec.add_development_dependency 'simplecov'
25
+ spec.add_development_dependency 'codecov'
26
+
27
+ spec.add_dependency 'wamp_client', '~> 0.0.7'
28
+ end
metadata ADDED
@@ -0,0 +1,167 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: wamp_rails
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Eric Chapman
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-11-27 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.7'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.7'
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: '0'
48
+ type: :development
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: simplecov
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
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: codecov
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: wamp_client
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: 0.0.7
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: 0.0.7
97
+ description: An implementation of The Web Application Messaging Protocol (WAMP)
98
+ email:
99
+ - eric.chappy@gmail.com
100
+ executables:
101
+ - console
102
+ - setup
103
+ extensions: []
104
+ extra_rdoc_files: []
105
+ files:
106
+ - ".gitignore"
107
+ - ".rspec"
108
+ - ".travis.yml"
109
+ - Gemfile
110
+ - LICENSE.txt
111
+ - README.md
112
+ - Rakefile
113
+ - bin/console
114
+ - bin/setup
115
+ - lib/wamp_rails.rb
116
+ - lib/wamp_rails/client.rb
117
+ - lib/wamp_rails/commands/base_command.rb
118
+ - lib/wamp_rails/commands/base_handler.rb
119
+ - lib/wamp_rails/commands/call.rb
120
+ - lib/wamp_rails/commands/publish.rb
121
+ - lib/wamp_rails/commands/register.rb
122
+ - lib/wamp_rails/commands/subscribe.rb
123
+ - lib/wamp_rails/controllers/base_controller.rb
124
+ - lib/wamp_rails/controllers/procedure.rb
125
+ - lib/wamp_rails/controllers/subscription.rb
126
+ - lib/wamp_rails/error.rb
127
+ - lib/wamp_rails/version.rb
128
+ - spec/client_spec.rb
129
+ - spec/spec_helper.rb
130
+ - spec/support/test_connection.rb
131
+ - spec/support/test_procedure_controller.rb
132
+ - spec/support/test_session.rb
133
+ - spec/support/test_subscription_controller.rb
134
+ - spec/wamp_rails_spec.rb
135
+ - wamp_rails.gemspec
136
+ homepage: https://github.com/ericchapman/ruby_wamp_rails
137
+ licenses:
138
+ - MIT
139
+ metadata: {}
140
+ post_install_message:
141
+ rdoc_options: []
142
+ require_paths:
143
+ - lib
144
+ required_ruby_version: !ruby/object:Gem::Requirement
145
+ requirements:
146
+ - - ">="
147
+ - !ruby/object:Gem::Version
148
+ version: '0'
149
+ required_rubygems_version: !ruby/object:Gem::Requirement
150
+ requirements:
151
+ - - ">="
152
+ - !ruby/object:Gem::Version
153
+ version: '0'
154
+ requirements: []
155
+ rubyforge_project:
156
+ rubygems_version: 2.5.1
157
+ signing_key:
158
+ specification_version: 4
159
+ summary: Web Application Messaging Protocol Client for Rails
160
+ test_files:
161
+ - spec/client_spec.rb
162
+ - spec/spec_helper.rb
163
+ - spec/support/test_connection.rb
164
+ - spec/support/test_procedure_controller.rb
165
+ - spec/support/test_session.rb
166
+ - spec/support/test_subscription_controller.rb
167
+ - spec/wamp_rails_spec.rb