ruby_mailman 0.9.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 +25 -0
- data/.ruby-version +1 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +1 -0
- data/README.md +173 -0
- data/Rakefile +5 -0
- data/lib/ruby_mailman/central_service_interface.rb +24 -0
- data/lib/ruby_mailman/mailman.rb +33 -0
- data/lib/ruby_mailman/response.rb +56 -0
- data/lib/ruby_mailman/subscription/message.rb +15 -0
- data/lib/ruby_mailman/subscription.rb +25 -0
- data/lib/ruby_mailman/version.rb +3 -0
- data/lib/ruby_mailman/zmq_client.rb +50 -0
- data/lib/ruby_mailman.rb +8 -0
- data/ruby_mailman.gemspec +25 -0
- data/spec/integration/request_spec.rb +101 -0
- data/spec/integration/subscribe_spec.rb +72 -0
- data/spec/lib/ruby_mailman/central_service_interface_spec.rb +30 -0
- data/spec/lib/ruby_mailman/mailman_spec.rb +64 -0
- data/spec/lib/ruby_mailman/response_spec.rb +120 -0
- data/spec/lib/ruby_mailman/subscription_spec.rb +40 -0
- data/spec/lib/ruby_mailman/zmq_client_spec.rb +88 -0
- data/spec/models/auth.pb.rb +24 -0
- data/spec/spec_helper.rb +1 -0
- data/spec/zmq_servers/publish.rb +27 -0
- data/spec/zmq_servers/reply.rb +20 -0
- metadata +151 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: 841cc56a61b4a16b14dcf1126c8a6f1228021042
|
|
4
|
+
data.tar.gz: 82eea3a9156d4c42b3ed1f6ff6d68dd9a8c58532
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 596d35d65745351ede2e99fdfdb281becbb4fc703c752a8c75db9911b549da031eecba15ffd8345c90210ac716ae4fbe3914fa4a05809a04e1ffd467ba5c8d24
|
|
7
|
+
data.tar.gz: 464957a5983d49b6f84912775e26102eeed8e205a850076e2650452c90fb36e1df6f460082d6845aa83139535aff422b8736e2628c90a5b27bed64aabf666c4f
|
data/.gitignore
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
*.gem
|
|
2
|
+
*.rbc
|
|
3
|
+
.bundle
|
|
4
|
+
.config
|
|
5
|
+
.yardoc
|
|
6
|
+
Gemfile.lock
|
|
7
|
+
InstalledFiles
|
|
8
|
+
_yardoc
|
|
9
|
+
coverage
|
|
10
|
+
doc/
|
|
11
|
+
lib/bundler/man
|
|
12
|
+
pkg
|
|
13
|
+
rdoc
|
|
14
|
+
spec/reports
|
|
15
|
+
test/tmp
|
|
16
|
+
test/version_tmp
|
|
17
|
+
tmp
|
|
18
|
+
*.bundle
|
|
19
|
+
*.so
|
|
20
|
+
*.o
|
|
21
|
+
*.a
|
|
22
|
+
mkmf.log
|
|
23
|
+
vendor/protobufs
|
|
24
|
+
vendor/bundle
|
|
25
|
+
lib/*pb.rb
|
data/.ruby-version
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
2.1.1
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
© Regents of the University of Minnesota. All rights reserved.
|
data/README.md
ADDED
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
# Ruby Mailman
|
|
2
|
+
|
|
3
|
+
- A ruby library for interacting with Central Service
|
|
4
|
+
- Sending Messages
|
|
5
|
+
- Subscribing to Channels
|
|
6
|
+
- Follows the spec outlined in https://github.umn.edu/umnapi/services_interface
|
|
7
|
+
|
|
8
|
+
## Sending Messages
|
|
9
|
+
|
|
10
|
+
Central Services will expect objects to be serialized [protobuf objects](https://github.umn.edu/umnapi/protobufs). If you send other types of objects in your messages it probably will not work.
|
|
11
|
+
|
|
12
|
+
```ruby
|
|
13
|
+
|
|
14
|
+
module Interfaces
|
|
15
|
+
class Auth < ::Protobuf::Message; end
|
|
16
|
+
|
|
17
|
+
class Auth
|
|
18
|
+
optional :string, :email, 2
|
|
19
|
+
optional :string, :public_key, 3
|
|
20
|
+
optional :string, :private_key, 4
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
auth = Interfaces::Auth.new
|
|
27
|
+
message = auth.encode
|
|
28
|
+
|
|
29
|
+
RubyMailman::Mailman.deliver(:create, message)
|
|
30
|
+
RubyMailman::Mailman.deliver(:update, message)
|
|
31
|
+
RubyMailman::Mailman.deliver(:destroy, message)
|
|
32
|
+
|
|
33
|
+
RubyMailman::Mailman.create(message)
|
|
34
|
+
RubyMailman::Mailman.update(message)
|
|
35
|
+
RubyMailman::Mailman.destroy(message)
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### Responses
|
|
39
|
+
|
|
40
|
+
Central Services has 3 types of response:
|
|
41
|
+
- success ('200')
|
|
42
|
+
- retry ('409')
|
|
43
|
+
- failure ('500')
|
|
44
|
+
|
|
45
|
+
#### Success
|
|
46
|
+
|
|
47
|
+
```ruby
|
|
48
|
+
response = Mailman.deliver(:create, obj)
|
|
49
|
+
response.success?
|
|
50
|
+
#=> true
|
|
51
|
+
response.retry?
|
|
52
|
+
#=> false
|
|
53
|
+
response.fail?
|
|
54
|
+
#=> false
|
|
55
|
+
response.body
|
|
56
|
+
#=> '200'
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
#### Retry
|
|
60
|
+
|
|
61
|
+
```ruby
|
|
62
|
+
response = Mailman.deliver(:create, obj)
|
|
63
|
+
response.success?
|
|
64
|
+
#=> false
|
|
65
|
+
response.retry?
|
|
66
|
+
#=> true
|
|
67
|
+
response.fail?
|
|
68
|
+
#=> false
|
|
69
|
+
response.body
|
|
70
|
+
#=> '409'
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
#### Failure
|
|
74
|
+
|
|
75
|
+
```ruby
|
|
76
|
+
response = Mailman.deliver(:create, obj)
|
|
77
|
+
response.success?
|
|
78
|
+
#=> false
|
|
79
|
+
response.retry?
|
|
80
|
+
#=> false
|
|
81
|
+
response.fail?
|
|
82
|
+
#=> true
|
|
83
|
+
response.body
|
|
84
|
+
#=> '500'
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Subscribing
|
|
88
|
+
|
|
89
|
+
You need to write some code that will handle the responses you'll get from subscription. There are a couple of ways to do this.
|
|
90
|
+
|
|
91
|
+
#### Listener Class
|
|
92
|
+
|
|
93
|
+
It just has to implement the `call` message with an arity of two. The channel will be the first parameter, the message will be the second. Do whatever you want within the method.
|
|
94
|
+
|
|
95
|
+
```ruby
|
|
96
|
+
class MyListener
|
|
97
|
+
def call(channel, message)
|
|
98
|
+
# your code to handle the new message
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
RubyMailman::Subscription.subscribe(channel: :key, listener: MyListener.new)
|
|
104
|
+
#=> #<RubyMailman::Subscription:0x007fa2d3835978 ...>
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
#### Listener Lambda
|
|
108
|
+
|
|
109
|
+
Since lambdas respond to `call`, you can do
|
|
110
|
+
|
|
111
|
+
```ruby
|
|
112
|
+
my_listener = lambda{ |channel, message| #your code }
|
|
113
|
+
RubyMailman::Subscription.subscribe(channel: :key, listener: my_listener)
|
|
114
|
+
#=> #<RubyMailman::Subscription:0x007fa2d3835978 ...>
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### Subscription Messages
|
|
118
|
+
|
|
119
|
+
Your listener will receive `call` with the channel and the message. The message is an instance of RubyMailman::Subscription::Message and responds to:
|
|
120
|
+
|
|
121
|
+
- channel: the channel again
|
|
122
|
+
- action: `create`, `update` or `destroy`
|
|
123
|
+
- content: A serialized protobuff object
|
|
124
|
+
|
|
125
|
+
This is a very specific message, since it's really only designed to do one thing -- tell your service about new/changed/destroyed objects. Let's look at an example of a service that care about Auth objects, and it locally persists those Auth objects as LocalAuth:
|
|
126
|
+
|
|
127
|
+
```ruby
|
|
128
|
+
class AuthListener
|
|
129
|
+
def call(channel, message)
|
|
130
|
+
a = Interfaces::Auth.new
|
|
131
|
+
a.decode(message.content)
|
|
132
|
+
|
|
133
|
+
AuthLogger.log("Message received on #{message.channel} telling me to #{message.action} the object #{a.to_s}")
|
|
134
|
+
|
|
135
|
+
case message.action
|
|
136
|
+
when 'create'
|
|
137
|
+
LocalAuth.new(a).save #We'll leave the implementation of LocalAuth to your imagination.
|
|
138
|
+
when 'update'
|
|
139
|
+
LocalAuth.replace(a)
|
|
140
|
+
when 'destroy'
|
|
141
|
+
LocalAuth.destroy(a)
|
|
142
|
+
else
|
|
143
|
+
raise ArgumentError
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
RubyMailman::Subscription.new(channel: Auth, listener: AuthListener.new)
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
## Setup
|
|
152
|
+
|
|
153
|
+
- Add `gem ruby_mailman` to your service
|
|
154
|
+
- `bundle install --path ./vendor/bundle`
|
|
155
|
+
|
|
156
|
+
## Local Setup and Running Tests
|
|
157
|
+
|
|
158
|
+
- Clone the repo
|
|
159
|
+
- `bundle install --path ./vendor/bundle`
|
|
160
|
+
- `bundle exec rake`
|
|
161
|
+
|
|
162
|
+
## Development
|
|
163
|
+
|
|
164
|
+
To work on the gem:
|
|
165
|
+
|
|
166
|
+
- Fork this repo
|
|
167
|
+
- Submit your changes through a pull request
|
|
168
|
+
- Tests are required for any pull requests
|
|
169
|
+
|
|
170
|
+
## License
|
|
171
|
+
|
|
172
|
+
© Regents of the University of Minnesota. All rights reserved.
|
|
173
|
+
|
data/Rakefile
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
class CentralServiceInterface
|
|
2
|
+
def self.deliver(action,object,cs_client = CSTransportClient)
|
|
3
|
+
self.new(cs_client).deliver(action,object)
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
def self.subscribe(channel, listener, cs_client = CSTransportClient)
|
|
7
|
+
self.new(cs_client).subscribe(channel, listener)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def initialize(cs_client)
|
|
11
|
+
self.central_service_client = cs_client
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def deliver(action,object)
|
|
15
|
+
central_service_client.request(action,object)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def subscribe(channel, listener)
|
|
19
|
+
central_service_client.subscribe(channel, listener)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
private
|
|
23
|
+
attr_accessor :central_service_client
|
|
24
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
module RubyMailman
|
|
2
|
+
class Mailman
|
|
3
|
+
def self.deliver(action, obj, cs = CentralServiceInterface)
|
|
4
|
+
self.new(action, obj, cs).deliver
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def self.create(obj, cs = CentralServiceInterface)
|
|
8
|
+
self.deliver(:create, obj, cs)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def self.update(obj, cs = CentralServiceInterface)
|
|
12
|
+
self.deliver(:update, obj, cs)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def self.destroy(obj, cs = CentralServiceInterface)
|
|
16
|
+
self.deliver(:destroy, obj, cs)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def initialize(action, object, central_service)
|
|
20
|
+
self.action = action
|
|
21
|
+
self.object = object
|
|
22
|
+
self.central_service = central_service
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def deliver
|
|
26
|
+
Response.build(central_service.deliver(action.to_s, object))
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
private
|
|
30
|
+
|
|
31
|
+
attr_accessor :action, :object, :central_service
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
module RubyMailman
|
|
2
|
+
class Response
|
|
3
|
+
attr_reader :body
|
|
4
|
+
def self.build(raw_response)
|
|
5
|
+
#Work with both a string "200" and an array ["200"]
|
|
6
|
+
raw_response = Array(raw_response).join
|
|
7
|
+
case raw_response
|
|
8
|
+
when "200"
|
|
9
|
+
SuccessResponse.new(raw_response)
|
|
10
|
+
when "409"
|
|
11
|
+
RetryResponse.new(raw_response)
|
|
12
|
+
when "500"
|
|
13
|
+
FailResponse.new(raw_response)
|
|
14
|
+
else
|
|
15
|
+
self.new(raw_response)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def success?
|
|
20
|
+
false
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def retry?
|
|
24
|
+
false
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def fail?
|
|
28
|
+
false
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def initialize(body)
|
|
32
|
+
self.body = body
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
private
|
|
36
|
+
attr_writer :body
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
class SuccessResponse < Response
|
|
40
|
+
def success?
|
|
41
|
+
true
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
class RetryResponse < Response
|
|
46
|
+
def retry?
|
|
47
|
+
true
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
class FailResponse < Response
|
|
52
|
+
def fail?
|
|
53
|
+
true
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
module RubyMailman
|
|
2
|
+
class Subscription
|
|
3
|
+
class Message
|
|
4
|
+
attr_reader :channel, :action, :content
|
|
5
|
+
def initialize(channel, raw_message)
|
|
6
|
+
self.channel = channel
|
|
7
|
+
self.action = raw_message[0]
|
|
8
|
+
self.content = raw_message[1]
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
private
|
|
12
|
+
attr_writer :channel, :action, :content
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
module RubyMailman
|
|
2
|
+
class Subscription
|
|
3
|
+
def self.subscribe(args, cs = CentralServiceInterface)
|
|
4
|
+
channel = args.fetch(:channel) do
|
|
5
|
+
raise ArgumentError, "Subscribtion requries a channel"
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
listener = args.fetch(:listener) do
|
|
9
|
+
raise ArgumentError, "Subscribtion requries a listener"
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
self.new(channel, listener, cs)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def initialize(channel, listener, cs)
|
|
16
|
+
self.channel = channel
|
|
17
|
+
self.listener = listener
|
|
18
|
+
self.central_service = cs
|
|
19
|
+
central_service.subscribe(channel, listener)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
private
|
|
23
|
+
attr_accessor :channel, :listener, :central_service
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
require 'ffi-rzmq'
|
|
2
|
+
|
|
3
|
+
class ZMQConfiguration
|
|
4
|
+
def self.server
|
|
5
|
+
ENV['0MQServerAddress'] || "tcp://localhost:6666"
|
|
6
|
+
end
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
class ZMQRequestClient
|
|
10
|
+
def self.run(action, object)
|
|
11
|
+
context = ZMQ::Context.new
|
|
12
|
+
connection = context.socket(ZMQ::REQ)
|
|
13
|
+
connection.connect(ZMQConfiguration.server)
|
|
14
|
+
connection.send_strings([action, object])
|
|
15
|
+
receiver = ""
|
|
16
|
+
connection.recv_string(receiver)
|
|
17
|
+
receiver
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
class ZMQSubscriptionClient
|
|
22
|
+
def self.run(channel, listener, message_builder = RubyMailman::Subscription::Message)
|
|
23
|
+
context = ZMQ::Context.new
|
|
24
|
+
connection = context.socket(ZMQ::SUB)
|
|
25
|
+
connection.connect(ZMQConfiguration.server)
|
|
26
|
+
connection.setsockopt(ZMQ::SUBSCRIBE, channel)
|
|
27
|
+
|
|
28
|
+
Thread.new do
|
|
29
|
+
loop do
|
|
30
|
+
received_channel = ''
|
|
31
|
+
connection.recv_string(received_channel)
|
|
32
|
+
message = []
|
|
33
|
+
connection.recv_strings(message)
|
|
34
|
+
listener.call(received_channel, message_builder.new(received_channel, message))
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
class ZMQClient
|
|
41
|
+
attr_reader :connection
|
|
42
|
+
|
|
43
|
+
def self.request(action, object, concrete_client = ZMQRequestClient)
|
|
44
|
+
concrete_client.run(action, object)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def self.subscribe(channel, listener, concrete_client = ZMQSubscriptionClient)
|
|
48
|
+
concrete_client.run(channel, listener)
|
|
49
|
+
end
|
|
50
|
+
end
|
data/lib/ruby_mailman.rb
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
require "ruby_mailman/version"
|
|
2
|
+
require "ruby_mailman/mailman"
|
|
3
|
+
require "ruby_mailman/subscription"
|
|
4
|
+
require "ruby_mailman/subscription/message"
|
|
5
|
+
require "ruby_mailman/response"
|
|
6
|
+
require "ruby_mailman/central_service_interface"
|
|
7
|
+
require "ruby_mailman/zmq_client"
|
|
8
|
+
CSTransportClient = ZMQClient
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
|
+
require 'ruby_mailman/version'
|
|
5
|
+
|
|
6
|
+
Gem::Specification.new do |spec|
|
|
7
|
+
spec.name = "ruby_mailman"
|
|
8
|
+
spec.version = RubyMailman::VERSION
|
|
9
|
+
spec.authors = ["Ian Whitney"]
|
|
10
|
+
spec.email = ["whit0694@umn.edu"]
|
|
11
|
+
spec.summary = %q{A ruby library for connecting to Central Service}
|
|
12
|
+
spec.description = %q{Ruby implementation of the Central Service interface. Meant for use with UMN API Services written in Ruby.}
|
|
13
|
+
spec.homepage = "https://github.umn.edu/umnapi/ruby_mailman/"
|
|
14
|
+
|
|
15
|
+
spec.files = `git ls-files -z`.split("\x0")
|
|
16
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
|
17
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
|
18
|
+
spec.require_paths = ["lib"]
|
|
19
|
+
|
|
20
|
+
spec.add_development_dependency "bundler", "~> 1.6"
|
|
21
|
+
spec.add_development_dependency "rake"
|
|
22
|
+
spec.add_development_dependency "protobuf"
|
|
23
|
+
spec.add_development_dependency "rspec", "~> 3.0"
|
|
24
|
+
spec.add_development_dependency "ffi-rzmq"
|
|
25
|
+
end
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
require_relative '../../lib/ruby_mailman'
|
|
4
|
+
require_relative '../models/auth.pb'
|
|
5
|
+
require_relative "../zmq_servers/reply"
|
|
6
|
+
|
|
7
|
+
RSpec.describe "Making requests" do
|
|
8
|
+
|
|
9
|
+
let(:auth) { Interfaces::Auth.new }
|
|
10
|
+
|
|
11
|
+
describe "main methods work" do
|
|
12
|
+
before(:example) do
|
|
13
|
+
@server_configuration = {
|
|
14
|
+
port: 6666,
|
|
15
|
+
reply: -> { "#{rand}" }
|
|
16
|
+
}
|
|
17
|
+
@pid = TestServer::Reply.run_as_process(@server_configuration)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
after(:example) do
|
|
21
|
+
Process.kill("KILL", @pid)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
it "returns non nil when using the .deliver method" do
|
|
25
|
+
expect(RubyMailman::Mailman.deliver(:create, auth.encode)).not_to be_nil
|
|
26
|
+
expect(RubyMailman::Mailman.deliver(:update, auth.encode)).not_to be_nil
|
|
27
|
+
expect(RubyMailman::Mailman.deliver(:destroy, auth.encode)).not_to be_nil
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it "returns non nil when using the named method" do
|
|
31
|
+
expect(RubyMailman::Mailman.create(auth.encode)).not_to be_nil
|
|
32
|
+
expect(RubyMailman::Mailman.update(auth.encode)).not_to be_nil
|
|
33
|
+
expect(RubyMailman::Mailman.destroy(auth.encode)).not_to be_nil
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
describe "responses behave as expected" do
|
|
38
|
+
describe "When the server repsonds with '200'" do
|
|
39
|
+
before(:example) do
|
|
40
|
+
@server_configuration = {
|
|
41
|
+
port: 6666,
|
|
42
|
+
reply: -> { "200" }
|
|
43
|
+
}
|
|
44
|
+
@pid = TestServer::Reply.run_as_process(@server_configuration)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
after(:example) do
|
|
48
|
+
Process.kill("KILL", @pid)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it "Requests get a sucessful response" do
|
|
52
|
+
expect(RubyMailman::Mailman.deliver(:create, auth.encode).success?).to be_truthy
|
|
53
|
+
expect(RubyMailman::Mailman.deliver(:create, auth.encode).retry?).to be_falsey
|
|
54
|
+
expect(RubyMailman::Mailman.deliver(:create, auth.encode).fail?).to be_falsey
|
|
55
|
+
expect(RubyMailman::Mailman.deliver(:create, auth.encode).body).to eq("200")
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
describe "When the server repsonds with '409'" do
|
|
60
|
+
before(:example) do
|
|
61
|
+
@server_configuration = {
|
|
62
|
+
port: 6666,
|
|
63
|
+
reply: -> { "409" }
|
|
64
|
+
}
|
|
65
|
+
@pid = TestServer::Reply.run_as_process(@server_configuration)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
after(:example) do
|
|
69
|
+
Process.kill("KILL", @pid)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
it "Requests get a retry response" do
|
|
73
|
+
expect(RubyMailman::Mailman.deliver(:create, auth.encode).success?).to be_falsey
|
|
74
|
+
expect(RubyMailman::Mailman.deliver(:create, auth.encode).retry?).to be_truthy
|
|
75
|
+
expect(RubyMailman::Mailman.deliver(:create, auth.encode).fail?).to be_falsey
|
|
76
|
+
expect(RubyMailman::Mailman.deliver(:create, auth.encode).body).to eq("409")
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
describe "When the server repsonds with '500'" do
|
|
81
|
+
before(:example) do
|
|
82
|
+
@server_configuration = {
|
|
83
|
+
port: 6666,
|
|
84
|
+
reply: -> { "500" }
|
|
85
|
+
}
|
|
86
|
+
@pid = TestServer::Reply.run_as_process(@server_configuration)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
after(:example) do
|
|
90
|
+
Process.kill("KILL", @pid)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
it "Requests get a failure response" do
|
|
94
|
+
expect(RubyMailman::Mailman.deliver(:create, auth.encode).success?).to be_falsey
|
|
95
|
+
expect(RubyMailman::Mailman.deliver(:create, auth.encode).retry?).to be_falsey
|
|
96
|
+
expect(RubyMailman::Mailman.deliver(:create, auth.encode).fail?).to be_truthy
|
|
97
|
+
expect(RubyMailman::Mailman.deliver(:create, auth.encode).body).to eq("500")
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'securerandom'
|
|
3
|
+
require 'protobuf'
|
|
4
|
+
|
|
5
|
+
require_relative '../models/auth.pb'
|
|
6
|
+
require_relative '../../lib/ruby_mailman'
|
|
7
|
+
require_relative "../zmq_servers/publish"
|
|
8
|
+
|
|
9
|
+
class MyListener
|
|
10
|
+
attr_reader :channel, :message
|
|
11
|
+
def call(channel, message)
|
|
12
|
+
@channel = channel
|
|
13
|
+
@message = message
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
RSpec.describe "Subscribing to channels" do
|
|
18
|
+
let(:listener) { MyListener.new }
|
|
19
|
+
|
|
20
|
+
before(:example) do
|
|
21
|
+
@message_action = ['create','update','destroy'].sample
|
|
22
|
+
auth = Interfaces::Auth.new
|
|
23
|
+
auth.email = rand.to_s
|
|
24
|
+
auth.public_key = SecureRandom.uuid
|
|
25
|
+
auth.private_key = SecureRandom.uuid
|
|
26
|
+
@message_content = auth.encode
|
|
27
|
+
|
|
28
|
+
@server_configuration = {
|
|
29
|
+
channel: "mychannel",
|
|
30
|
+
port: 6666,
|
|
31
|
+
message_parts: [@message_action, @message_content],
|
|
32
|
+
publish_delay: 0.05
|
|
33
|
+
}
|
|
34
|
+
@pid = TestServer::Publish.run_as_process(@server_configuration)
|
|
35
|
+
@test_delay = @server_configuration[:publish_delay] * 2
|
|
36
|
+
|
|
37
|
+
#wait so the publisher process can get rolling
|
|
38
|
+
sleep(@test_delay)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
after(:example) do
|
|
42
|
+
Process.kill("KILL", @pid)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
it "returns a RubyMailman::Subscription instance when subscribing" do
|
|
46
|
+
subscription_return = RubyMailman::Subscription.subscribe(channel: @server_configuration[:channel], listener: listener)
|
|
47
|
+
expect(subscription_return).to be_a(RubyMailman::Subscription)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
it "calls the listener when a new message is published" do
|
|
51
|
+
expect(listener).to receive(:call).at_least(:once)
|
|
52
|
+
RubyMailman::Subscription.subscribe(channel: @server_configuration[:channel], listener: listener)
|
|
53
|
+
sleep(@test_delay)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
it "calls the listener with the channel name and a RubyMailman::Subscription::Message instance" do
|
|
57
|
+
RubyMailman::Subscription.subscribe(channel: @server_configuration[:channel], listener: listener)
|
|
58
|
+
sleep(@test_delay)
|
|
59
|
+
|
|
60
|
+
expect(listener.channel).to eq(@server_configuration[:channel])
|
|
61
|
+
expect(listener.message).to be_a(RubyMailman::Subscription::Message)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
it "The message instance has the channel, action and content we expect" do
|
|
65
|
+
RubyMailman::Subscription.subscribe(channel: @server_configuration[:channel], listener: listener)
|
|
66
|
+
sleep(@test_delay)
|
|
67
|
+
|
|
68
|
+
expect(listener.message.channel).to eq(@server_configuration[:channel])
|
|
69
|
+
expect(listener.message.action).to eq(@message_action)
|
|
70
|
+
expect(listener.message.content).to eq(@message_content)
|
|
71
|
+
end
|
|
72
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
require_relative "../../../lib/ruby_mailman"
|
|
3
|
+
|
|
4
|
+
RSpec.describe CentralServiceInterface do
|
|
5
|
+
let (:client_class_double) { class_double(ZMQClient) }
|
|
6
|
+
|
|
7
|
+
describe "self.deliver" do
|
|
8
|
+
before do
|
|
9
|
+
@action = "action#{rand}"
|
|
10
|
+
@object = Object.new
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it "uses the provided client to make a request" do
|
|
14
|
+
expect(client_class_double).to receive(:request).with(@action, @object) { true }
|
|
15
|
+
CentralServiceInterface.deliver(@action,@object,client_class_double)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
describe "self.subscribe" do
|
|
20
|
+
before do
|
|
21
|
+
@channel = "channel#{rand}"
|
|
22
|
+
@listener = Object.new
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it "uses the provided client to subscribe" do
|
|
26
|
+
expect(client_class_double).to receive(:subscribe).with(@channel, @listener) { true }
|
|
27
|
+
CentralServiceInterface.subscribe(@channel, @listener, client_class_double)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require_relative "../../../lib/ruby_mailman"
|
|
3
|
+
|
|
4
|
+
Mailman = RubyMailman::Mailman
|
|
5
|
+
|
|
6
|
+
describe Mailman do
|
|
7
|
+
let (:cs_interface_double) { double(CentralServiceInterface) }
|
|
8
|
+
let (:object_double) { Object.new }
|
|
9
|
+
|
|
10
|
+
before do
|
|
11
|
+
allow(RubyMailman::Response).to receive(:build) { Object.new }
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
describe "notifies of creation" do
|
|
15
|
+
it "has the CentralServiceInterface do the work" do
|
|
16
|
+
expect(cs_interface_double).to receive(:deliver).with("create", object_double)
|
|
17
|
+
Mailman.deliver(:create, object_double, cs_interface_double)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it "supports the .deliver syntax" do
|
|
21
|
+
expect(cs_interface_double).to receive(:deliver).with("create", object_double)
|
|
22
|
+
Mailman.deliver(:create, object_double, cs_interface_double)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it "works with the .create syntax" do
|
|
26
|
+
expect(cs_interface_double).to receive(:deliver).with("create", object_double)
|
|
27
|
+
Mailman.create(object_double, cs_interface_double)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
describe "notifies of update" do
|
|
32
|
+
it "has the CentralServiceInterface do the work" do
|
|
33
|
+
expect(cs_interface_double).to receive(:deliver).with("update", object_double)
|
|
34
|
+
Mailman.deliver(:update, object_double, cs_interface_double)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
it "supports the .deliver syntax" do
|
|
38
|
+
expect(cs_interface_double).to receive(:deliver).with("update", object_double)
|
|
39
|
+
Mailman.deliver(:update, object_double, cs_interface_double)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
it "works with the .update syntax" do
|
|
43
|
+
expect(cs_interface_double).to receive(:deliver).with("update", object_double)
|
|
44
|
+
Mailman.update(object_double, cs_interface_double)
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
describe "notifies of destruction" do
|
|
49
|
+
it "has the CentralServiceInterface do the work" do
|
|
50
|
+
expect(cs_interface_double).to receive(:deliver).with("destroy", object_double)
|
|
51
|
+
Mailman.deliver(:destroy, object_double, cs_interface_double)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
it "supports the .deliver syntax" do
|
|
55
|
+
expect(cs_interface_double).to receive(:deliver).with("destroy", object_double)
|
|
56
|
+
Mailman.deliver(:destroy, object_double, cs_interface_double)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
it "works with the .destroy syntax" do
|
|
60
|
+
expect(cs_interface_double).to receive(:deliver).with("destroy", object_double)
|
|
61
|
+
Mailman.destroy(object_double, cs_interface_double)
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require_relative "../../../lib/ruby_mailman"
|
|
3
|
+
|
|
4
|
+
Response = RubyMailman::Response
|
|
5
|
+
SuccessResponse = RubyMailman::SuccessResponse
|
|
6
|
+
RetryResponse = RubyMailman::RetryResponse
|
|
7
|
+
FailResponse = RubyMailman::FailResponse
|
|
8
|
+
|
|
9
|
+
describe Response do
|
|
10
|
+
describe "build" do
|
|
11
|
+
it "creates and returns a SuccessResponse if the raw_response is '200'" do
|
|
12
|
+
x = Object.new
|
|
13
|
+
expect(SuccessResponse).to receive(:new).with('200') { x }
|
|
14
|
+
expect(Response.build('200')).to eq(x)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it "returns a SuccessResponse if the raw_response is '409'" do
|
|
18
|
+
x = Object.new
|
|
19
|
+
expect(RetryResponse).to receive(:new).with('409') { x }
|
|
20
|
+
expect(Response.build('409')).to eq(x)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it "returns a FailResponse if the raw_response is '500'" do
|
|
24
|
+
x = Object.new
|
|
25
|
+
expect(FailResponse).to receive(:new).with('500') { x }
|
|
26
|
+
expect(Response.build('500')).to eq(x)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it "returns a undecorated response with any other raw_response" do
|
|
30
|
+
x = Object.new
|
|
31
|
+
raw_response = rand(100).to_s
|
|
32
|
+
expect(Response).to receive(:new).with(raw_response) { x }
|
|
33
|
+
expect(Response.build(raw_response)).to eq(x)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
it "has a body equal to the raw_response" do
|
|
37
|
+
['200', '409', '500', rand(100).to_s].each do |code|
|
|
38
|
+
expect(Response.build(code).body).to eq(code)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
describe "success?" do
|
|
44
|
+
it "is false" do
|
|
45
|
+
expect(Response.new('').success?).to be_falsey
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
describe "retry?" do
|
|
50
|
+
it "is false" do
|
|
51
|
+
expect(Response.new('').retry?).to be_falsey
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
describe "fail?" do
|
|
56
|
+
it "is false" do
|
|
57
|
+
expect(Response.new('').fail?).to be_falsey
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
describe SuccessResponse do
|
|
62
|
+
describe "success?" do
|
|
63
|
+
it "is false" do
|
|
64
|
+
expect(SuccessResponse.new('').success?).to be_truthy
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
describe "retry?" do
|
|
69
|
+
it "is false" do
|
|
70
|
+
expect(SuccessResponse.new('').retry?).to be_falsey
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
describe "fail?" do
|
|
75
|
+
it "is false" do
|
|
76
|
+
expect(SuccessResponse.new('').fail?).to be_falsey
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
describe FailResponse do
|
|
82
|
+
describe "success?" do
|
|
83
|
+
it "is false" do
|
|
84
|
+
expect(FailResponse.new('').success?).to be_falsey
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
describe "retry?" do
|
|
89
|
+
it "is false" do
|
|
90
|
+
expect(FailResponse.new('').retry?).to be_falsey
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
describe "fail?" do
|
|
95
|
+
it "is false" do
|
|
96
|
+
expect(FailResponse.new('').fail?).to be_truthy
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
describe RetryResponse do
|
|
102
|
+
describe "success?" do
|
|
103
|
+
it "is false" do
|
|
104
|
+
expect(RetryResponse.new('').success?).to be_falsey
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
describe "retry?" do
|
|
109
|
+
it "is false" do
|
|
110
|
+
expect(RetryResponse.new('').retry?).to be_truthy
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
describe "fail?" do
|
|
115
|
+
it "is false" do
|
|
116
|
+
expect(RetryResponse.new('').fail?).to be_falsey
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require_relative "../../../lib/ruby_mailman"
|
|
3
|
+
|
|
4
|
+
Subscription = RubyMailman::Subscription
|
|
5
|
+
|
|
6
|
+
describe Subscription do
|
|
7
|
+
describe "subscribe" do
|
|
8
|
+
let(:args) { {channel: 'test', listener: Object.new } }
|
|
9
|
+
let(:cs_mock) { double(CentralServiceInterface) }
|
|
10
|
+
|
|
11
|
+
before do
|
|
12
|
+
allow(cs_mock).to receive(:subscribe) { true }
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
it "implements the method" do
|
|
16
|
+
expect(Subscription.respond_to?(:subscribe)).to be_truthy
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
it "requires a channel" do
|
|
20
|
+
args.delete(:channel)
|
|
21
|
+
expect { Subscription.subscribe(args,cs_mock) }.to raise_error(ArgumentError)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
it "requires a listener" do
|
|
25
|
+
args.delete(:listener)
|
|
26
|
+
expect { Subscription.subscribe(args,cs_mock) }.to raise_error(ArgumentError)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it "uses the Central Service Interface subscription method" do
|
|
30
|
+
expect(cs_mock).to receive(:subscribe).with(args[:channel], args[:listener])
|
|
31
|
+
Subscription.subscribe(args, cs_mock)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it "returns a Subscription instance" do
|
|
35
|
+
subscription_double = instance_double(Subscription)
|
|
36
|
+
expect(Subscription).to receive(:new) { subscription_double }
|
|
37
|
+
expect(Subscription.subscribe(args, cs_mock)).to eq(subscription_double)
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
require_relative "../../../lib/ruby_mailman"
|
|
3
|
+
require_relative "../../zmq_servers/reply"
|
|
4
|
+
require_relative "../../zmq_servers/publish"
|
|
5
|
+
|
|
6
|
+
RSpec.describe ZMQClient do
|
|
7
|
+
describe "request" do
|
|
8
|
+
let (:request_client) { class_double(ZMQRequestClient) }
|
|
9
|
+
let (:action) { "action#{rand}" }
|
|
10
|
+
let (:object) { Object.new }
|
|
11
|
+
|
|
12
|
+
it "uses the provided client to make a request" do
|
|
13
|
+
expect(request_client).to receive(:run).with(action, object) { true }
|
|
14
|
+
ZMQClient.request(action, object, request_client)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
describe "subscribe" do
|
|
19
|
+
let (:subscription_client) { class_double(ZMQSubscriptionClient) }
|
|
20
|
+
let (:channel) { "channel#{rand}" }
|
|
21
|
+
let (:listener) { Object.new }
|
|
22
|
+
|
|
23
|
+
it "uses the provided client to make a request" do
|
|
24
|
+
expect(subscription_client).to receive(:run).with(channel, listener) { true }
|
|
25
|
+
ZMQClient.subscribe(channel, listener, subscription_client)
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
RSpec.describe ZMQRequestClient do
|
|
31
|
+
describe "run" do
|
|
32
|
+
before(:example) do
|
|
33
|
+
reply_randomizer = rand
|
|
34
|
+
@server_configuration = {
|
|
35
|
+
port: 6666,
|
|
36
|
+
reply: -> {"reply #{reply_randomizer}"},
|
|
37
|
+
publish_delay: 0.03
|
|
38
|
+
}
|
|
39
|
+
@pid = TestServer::Reply.run_as_process(@server_configuration)
|
|
40
|
+
@test_delay = @server_configuration[:publish_delay] * 2
|
|
41
|
+
#wait so the publisher process can get rolling
|
|
42
|
+
sleep(@test_delay)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
it "returns a reply" do
|
|
46
|
+
action = 'action'
|
|
47
|
+
object = 'object'
|
|
48
|
+
reply = ZMQRequestClient.run(action,object)
|
|
49
|
+
expect(reply).to eq(@server_configuration[:reply].call)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
after(:example) do
|
|
53
|
+
Process.kill("KILL", @pid)
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
RSpec.describe ZMQSubscriptionClient do
|
|
59
|
+
describe "run" do
|
|
60
|
+
let (:message_builder) { class_double(RubyMailman::Subscription::Message) }
|
|
61
|
+
let (:message) { instance_double(RubyMailman::Subscription::Message) }
|
|
62
|
+
|
|
63
|
+
before(:example) do
|
|
64
|
+
@server_configuration = {
|
|
65
|
+
channel: "mychannel",
|
|
66
|
+
port: 6666,
|
|
67
|
+
message_parts: ["published message", rand(20).to_s],
|
|
68
|
+
publish_delay: 0.03
|
|
69
|
+
}
|
|
70
|
+
@pid = TestServer::Publish.run_as_process(@server_configuration)
|
|
71
|
+
@test_delay = @server_configuration[:publish_delay] * 2
|
|
72
|
+
#wait so the publisher process can get rolling
|
|
73
|
+
sleep(@test_delay)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
it "Creates a Message and then calls the listener" do
|
|
77
|
+
listener = lambda{|channel, message| rand}
|
|
78
|
+
expect(message_builder).to receive(:new).at_least(:once).with(@server_configuration[:channel],@server_configuration[:message_parts]) { message }
|
|
79
|
+
expect(listener).to receive(:call).at_least(:once).with(@server_configuration[:channel], message)
|
|
80
|
+
ZMQSubscriptionClient.run(@server_configuration[:channel], listener, message_builder)
|
|
81
|
+
sleep(@test_delay)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
after(:example) do
|
|
85
|
+
Process.kill("KILL", @pid)
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
##
|
|
2
|
+
# This file is auto-generated. DO NOT EDIT!
|
|
3
|
+
#
|
|
4
|
+
require 'protobuf/message'
|
|
5
|
+
|
|
6
|
+
module Interfaces
|
|
7
|
+
|
|
8
|
+
##
|
|
9
|
+
# Message Classes
|
|
10
|
+
#
|
|
11
|
+
class Auth < ::Protobuf::Message; end
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
##
|
|
15
|
+
# Message Fields
|
|
16
|
+
#
|
|
17
|
+
class Auth
|
|
18
|
+
optional :string, :email, 2
|
|
19
|
+
optional :string, :public_key, 3
|
|
20
|
+
optional :string, :private_key, 4
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
end
|
|
24
|
+
|
data/spec/spec_helper.rb
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
require "rspec/core"
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
require 'ffi-rzmq'
|
|
2
|
+
|
|
3
|
+
module TestServer
|
|
4
|
+
class Publish
|
|
5
|
+
def self.run_as_process(configuration)
|
|
6
|
+
Kernel.fork do
|
|
7
|
+
|
|
8
|
+
port = configuration[:port] || 6666
|
|
9
|
+
channel = configuration[:channel]
|
|
10
|
+
message_parts = configuration[:message_parts]
|
|
11
|
+
publish_delay = configuration[:publish_delay]
|
|
12
|
+
|
|
13
|
+
context = ZMQ::Context.new
|
|
14
|
+
publisher = context.socket(ZMQ::PUB)
|
|
15
|
+
publisher.setsockopt(ZMQ::LINGER,1)
|
|
16
|
+
publisher.bind("tcp://*:#{port}")
|
|
17
|
+
|
|
18
|
+
loop do
|
|
19
|
+
full_message = [message_parts[0].to_s, message_parts[1].to_s]
|
|
20
|
+
publisher.send_string(channel, ZMQ::SNDMORE)
|
|
21
|
+
publisher.send_strings(full_message)
|
|
22
|
+
sleep(publish_delay)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
require 'ffi-rzmq'
|
|
2
|
+
|
|
3
|
+
module TestServer
|
|
4
|
+
class Reply
|
|
5
|
+
def self.run_as_process(configuration)
|
|
6
|
+
port = configuration[:port] || '6666'
|
|
7
|
+
reply = configuration[:reply]
|
|
8
|
+
Kernel.fork do
|
|
9
|
+
context = ZMQ::Context.new
|
|
10
|
+
socket = context.socket(ZMQ::REP)
|
|
11
|
+
socket.bind("tcp://*:#{port}")
|
|
12
|
+
loop do
|
|
13
|
+
request = []
|
|
14
|
+
socket.recv_strings(request)
|
|
15
|
+
socket.send_string(reply.call)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: ruby_mailman
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.9.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Ian Whitney
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2014-09-29 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: '0'
|
|
34
|
+
type: :development
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - ">="
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '0'
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: protobuf
|
|
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: rspec
|
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - "~>"
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: '3.0'
|
|
62
|
+
type: :development
|
|
63
|
+
prerelease: false
|
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
+
requirements:
|
|
66
|
+
- - "~>"
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
version: '3.0'
|
|
69
|
+
- !ruby/object:Gem::Dependency
|
|
70
|
+
name: ffi-rzmq
|
|
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
|
+
description: Ruby implementation of the Central Service interface. Meant for use with
|
|
84
|
+
UMN API Services written in Ruby.
|
|
85
|
+
email:
|
|
86
|
+
- whit0694@umn.edu
|
|
87
|
+
executables: []
|
|
88
|
+
extensions: []
|
|
89
|
+
extra_rdoc_files: []
|
|
90
|
+
files:
|
|
91
|
+
- ".gitignore"
|
|
92
|
+
- ".ruby-version"
|
|
93
|
+
- Gemfile
|
|
94
|
+
- LICENSE.txt
|
|
95
|
+
- README.md
|
|
96
|
+
- Rakefile
|
|
97
|
+
- lib/ruby_mailman.rb
|
|
98
|
+
- lib/ruby_mailman/central_service_interface.rb
|
|
99
|
+
- lib/ruby_mailman/mailman.rb
|
|
100
|
+
- lib/ruby_mailman/response.rb
|
|
101
|
+
- lib/ruby_mailman/subscription.rb
|
|
102
|
+
- lib/ruby_mailman/subscription/message.rb
|
|
103
|
+
- lib/ruby_mailman/version.rb
|
|
104
|
+
- lib/ruby_mailman/zmq_client.rb
|
|
105
|
+
- ruby_mailman.gemspec
|
|
106
|
+
- spec/integration/request_spec.rb
|
|
107
|
+
- spec/integration/subscribe_spec.rb
|
|
108
|
+
- spec/lib/ruby_mailman/central_service_interface_spec.rb
|
|
109
|
+
- spec/lib/ruby_mailman/mailman_spec.rb
|
|
110
|
+
- spec/lib/ruby_mailman/response_spec.rb
|
|
111
|
+
- spec/lib/ruby_mailman/subscription_spec.rb
|
|
112
|
+
- spec/lib/ruby_mailman/zmq_client_spec.rb
|
|
113
|
+
- spec/models/auth.pb.rb
|
|
114
|
+
- spec/spec_helper.rb
|
|
115
|
+
- spec/zmq_servers/publish.rb
|
|
116
|
+
- spec/zmq_servers/reply.rb
|
|
117
|
+
homepage: https://github.umn.edu/umnapi/ruby_mailman/
|
|
118
|
+
licenses: []
|
|
119
|
+
metadata: {}
|
|
120
|
+
post_install_message:
|
|
121
|
+
rdoc_options: []
|
|
122
|
+
require_paths:
|
|
123
|
+
- lib
|
|
124
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
125
|
+
requirements:
|
|
126
|
+
- - ">="
|
|
127
|
+
- !ruby/object:Gem::Version
|
|
128
|
+
version: '0'
|
|
129
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
130
|
+
requirements:
|
|
131
|
+
- - ">="
|
|
132
|
+
- !ruby/object:Gem::Version
|
|
133
|
+
version: '0'
|
|
134
|
+
requirements: []
|
|
135
|
+
rubyforge_project:
|
|
136
|
+
rubygems_version: 2.2.2
|
|
137
|
+
signing_key:
|
|
138
|
+
specification_version: 4
|
|
139
|
+
summary: A ruby library for connecting to Central Service
|
|
140
|
+
test_files:
|
|
141
|
+
- spec/integration/request_spec.rb
|
|
142
|
+
- spec/integration/subscribe_spec.rb
|
|
143
|
+
- spec/lib/ruby_mailman/central_service_interface_spec.rb
|
|
144
|
+
- spec/lib/ruby_mailman/mailman_spec.rb
|
|
145
|
+
- spec/lib/ruby_mailman/response_spec.rb
|
|
146
|
+
- spec/lib/ruby_mailman/subscription_spec.rb
|
|
147
|
+
- spec/lib/ruby_mailman/zmq_client_spec.rb
|
|
148
|
+
- spec/models/auth.pb.rb
|
|
149
|
+
- spec/spec_helper.rb
|
|
150
|
+
- spec/zmq_servers/publish.rb
|
|
151
|
+
- spec/zmq_servers/reply.rb
|