wamp_rails 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 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