rcom 0.0.1

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 95a36229bc381e17c5190154a0679add12a794bf
4
+ data.tar.gz: ab8d5adbcb9b0a599a3da61badd4197dfec6c732
5
+ SHA512:
6
+ metadata.gz: d2199539d074722c55d225ac420f953fc6299d15c24569d7e2e9ce1f58031d3ddc1b3782a23b2c340083b13768a1a6a0f485958c5aee4284e5f840ebc5a67df2
7
+ data.tar.gz: 28cf9fd25c94b73073c0cd3aeaa77fdccb2544c1a27a518d7da2401f1252c347eaea9d38fdeddd6f5c4f4b0a15396263dedf001440c873a815ffeba10ebcdc55
data/.gitignore ADDED
@@ -0,0 +1,23 @@
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
+ .DS_Store
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in rcom.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Marco Lisci
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,33 @@
1
+ # Rcom
2
+
3
+ Redis inter-service messaging: request-response, publish-subscribe and tasks. A thin, minimal layer on top of [Redis-rb](https://github.com/redis/redis-rb).
4
+
5
+ ## Installation.
6
+
7
+ - [Install](http://redis.io/topics/quickstart) a local Redis server and start it:
8
+ ```sh
9
+ # OSX example
10
+ $ brew install redis
11
+ $ redis-server
12
+ ```
13
+
14
+ - Add rcom to your Gemfile:
15
+ ```ruby
16
+ gem 'rcom'
17
+ ```
18
+
19
+ ## Usage.
20
+
21
+ ## Test.
22
+
23
+ ## Contributing.
24
+
25
+ 1. Fork it ( https://github.com/badshark/rcom/fork )
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create a new Pull Request
30
+
31
+ ## License.
32
+
33
+ [MIT](LICENSE.txt)
data/Rakefile ADDED
@@ -0,0 +1,14 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rake/testtask'
3
+
4
+ namespace :test do
5
+ Rake::TestTask.new(:spec) do |t|
6
+ t.pattern = 'test/spec/*_spec.rb'
7
+ end
8
+
9
+ Rake::TestTask.new(:all) do |t|
10
+ t.pattern = 'test/**/*.rb'
11
+ end
12
+ end
13
+
14
+
data/lib/rcom/node.rb ADDED
@@ -0,0 +1,14 @@
1
+ module Rcom
2
+ class Node
3
+ attr_reader :uri
4
+
5
+ def initialize(uri)
6
+ raise ArgumentError unless ENV[uri.upcase]
7
+ @uri = ENV[uri.upcase]
8
+ end
9
+
10
+ def connect
11
+ Redis.new(url: uri)
12
+ end
13
+ end
14
+ end
data/lib/rcom/rpc.rb ADDED
@@ -0,0 +1,53 @@
1
+ module Rcom
2
+ class Rpc
3
+ attr_reader :node, :service
4
+
5
+ def initialize(params)
6
+ @node = params[:node]
7
+ @service = params[:service]
8
+ end
9
+
10
+ def request(params)
11
+ request = {
12
+ id: SecureRandom.hex,
13
+ method: params[:method],
14
+ args: params[:args]
15
+ }
16
+ node.rpush(service, request.to_msgpack)
17
+ ch, response = node.brpop(request[:id], timeout=10)
18
+ MessagePack.unpack(
19
+ response,
20
+ symbolize_keys: true
21
+ )
22
+ end
23
+
24
+ def subscribe
25
+ begin
26
+ loop do
27
+ ch, request = node.brpop(service)
28
+ message = MessagePack.unpack(
29
+ request,
30
+ symbolize_keys: true
31
+ )
32
+ router = Rcom::Router.new(message)
33
+ yield router
34
+ node.rpush(message[:id], router.reply.to_msgpack)
35
+ end
36
+ rescue Interrupt => _
37
+ end
38
+ end
39
+ end
40
+
41
+ class Router
42
+ attr_accessor :message, :reply
43
+
44
+ def initialize(message)
45
+ @message = message
46
+ end
47
+
48
+ def on(method)
49
+ return nil unless message[:method] == method
50
+ yield message[:args]
51
+ end
52
+ end
53
+ end
data/lib/rcom/task.rb ADDED
@@ -0,0 +1,28 @@
1
+ module Rcom
2
+ class Task
3
+ attr_reader :node, :queue
4
+
5
+ def initialize(args)
6
+ @node = args[:node]
7
+ @queue = args[:queue]
8
+ end
9
+
10
+ def publish(message)
11
+ node.lpush(queue, message.to_msgpack)
12
+ end
13
+
14
+ def subscribe
15
+ begin
16
+ loop do
17
+ ch, request = node.brpop(queue)
18
+ message = MessagePack.unpack(
19
+ request,
20
+ symbolize_keys: true
21
+ )
22
+ yield message
23
+ end
24
+ rescue Interrupt => _
25
+ end
26
+ end
27
+ end
28
+ end
data/lib/rcom/topic.rb ADDED
@@ -0,0 +1,29 @@
1
+ module Rcom
2
+ class Topic
3
+ attr_reader :node, :key
4
+
5
+ def initialize(args)
6
+ @node = args[:node]
7
+ @key = args[:key]
8
+ end
9
+
10
+ def publish(message)
11
+ node.publish(key, message.to_msgpack)
12
+ end
13
+
14
+ def subscribe
15
+ begin
16
+ node.subscribe(key) do |on|
17
+ on.message do |channel, message|
18
+ message = MessagePack.unpack(
19
+ message,
20
+ symbolize_keys: true
21
+ )
22
+ yield message
23
+ end
24
+ end
25
+ rescue Interrupt => _
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,3 @@
1
+ module Rcom
2
+ VERSION = "0.0.1"
3
+ end
data/lib/rcom.rb ADDED
@@ -0,0 +1,8 @@
1
+ require 'securerandom'
2
+ require 'redis'
3
+ require 'msgpack'
4
+ require 'rcom/version'
5
+ require 'rcom/node'
6
+ require 'rcom/topic'
7
+ require 'rcom/task'
8
+ require 'rcom/rpc'
data/rcom.gemspec ADDED
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'rcom/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "rcom"
8
+ spec.version = Rcom::VERSION
9
+ spec.authors = ["Marco Lisci"]
10
+ spec.email = ["info@badshark.io"]
11
+ spec.summary = %q{Redis inter-service messaging.}
12
+ spec.description = %q{Redis inter-service messaging: request-response, publish-subscribe and tasks.}
13
+ spec.homepage = "https://github.com/badshark/rcom"
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.6"
22
+ spec.add_development_dependency "rake"
23
+ spec.add_development_dependency "yard"
24
+
25
+ spec.add_dependency "redis", "~> 3.1.0"
26
+ spec.add_dependency "msgpack", "~> 0.5.9"
27
+ end
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ ENV['LOCAL'] = 'redis://localhost'
3
+
4
+ require 'rcom'
5
+ require 'json'
6
+
7
+ node = Rcom::Node.new('local').connect
8
+ service = Rcom::Rpc.new(node: node, service: 'auth')
9
+
10
+ service.subscribe do |request|
11
+ request.on('user.key') do |params|
12
+ request.reply = 'xxxccc'
13
+ end
14
+ end
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env ruby
2
+ ENV['LOCAL'] = 'redis://localhost'
3
+
4
+ require 'rcom'
5
+ require 'json'
6
+
7
+ message = {
8
+ method: 'user.key',
9
+ args: 1
10
+ }
11
+ node = Rcom::Node.new('local').connect
12
+ service = Rcom::Rpc.new(node: node, service: 'auth')
13
+ p service.request(message)
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env ruby
2
+ ENV['LOCAL'] = 'redis://localhost'
3
+
4
+ require 'rcom'
5
+ require 'json'
6
+
7
+ node = Rcom::Node.new('local').connect
8
+ messages = Rcom::Task.new(node: node, queue: 'messages')
9
+
10
+ messages.subscribe do |message|
11
+ sleep 1
12
+ p message
13
+ end
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env ruby
2
+ ENV['LOCAL'] = 'redis://localhost'
3
+
4
+ require 'rcom'
5
+ require 'json'
6
+
7
+ message = {
8
+ id: 1,
9
+ key: 'xxxccc'
10
+ }
11
+ node = Rcom::Node.new('local').connect
12
+ messages = Rcom::Task.new(node: node, queue: 'messages')
13
+ messages.publish(message)
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ ENV['local'] = 'redis://localhost'
3
+
4
+ require 'rcom'
5
+ require 'json'
6
+
7
+ message = {
8
+ id: 1,
9
+ key: 'xxxccc'
10
+ }
11
+ node = Rcom::Node.new('local').connect
12
+ topic = Rcom::Topic.new(node: node, key: 'users')
13
+
14
+ topic.publish(message)
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env ruby
2
+ ENV['local'] = 'redis://localhost'
3
+
4
+ require 'rcom'
5
+ require 'json'
6
+
7
+ node = Rcom::Node.new('local').connect
8
+ topic = Rcom::Topic.new(node: node, key: 'users')
9
+
10
+ topic.subscribe do |message|
11
+ p message
12
+ end
@@ -0,0 +1,3 @@
1
+ require 'rcom'
2
+ require 'minitest/autorun'
3
+ require 'minitest/pride'
@@ -0,0 +1,23 @@
1
+ require_relative './_init'
2
+
3
+ describe 'Node' do
4
+ before do
5
+ ENV['LOCAL'] = 'redis://127.0.0.1'
6
+ @local = Rcom::Node.new('local')
7
+ end
8
+
9
+ it 'represents a Redis connection to a node' do
10
+ @local.must_be_instance_of Rcom::Node
11
+ end
12
+
13
+ it 'cannot represent a node not present in ENV' do
14
+ lambda do
15
+ Rcom::Node.new('mail')
16
+ end.must_raise ArgumentError
17
+ end
18
+
19
+ it 'can connect to the Redis node' do
20
+ connection = @local.connect
21
+ connection.must_be_instance_of Redis
22
+ end
23
+ end
@@ -0,0 +1,37 @@
1
+ require_relative './_init'
2
+
3
+ describe 'Rpc' do
4
+ before do
5
+ ENV['LOCAL'] = 'redis://localhost'
6
+ @node = Rcom::Node.new('local').connect
7
+ end
8
+
9
+ it 'represents a remote procedure call' do
10
+ service = Rcom::Rpc.new(node: @node, service: 'auth')
11
+ service.must_be_instance_of Rcom::Rpc
12
+ end
13
+
14
+ it 'works in a request/response scenario' do
15
+ user_key = 'xxxccc'
16
+ response = ''
17
+ publisher = 'bundle exec ruby test/bin/rpc_publisher.rb'
18
+ consumer = 'bundle exec ruby test/bin/rpc_consumer.rb'
19
+
20
+ # Start the consumer, wait for it to be up,
21
+ # start the publisher and wait for the message
22
+ # on the consumer side. Process, then kill
23
+ # the long-running consumer.
24
+
25
+ consumer_pid = spawn(consumer)
26
+ sleep 1
27
+
28
+ Open3.popen3(publisher) do |stdin, stdout, stderr, wait_thr|
29
+ response = stdout.gets
30
+ Process.kill('INT', wait_thr.pid)
31
+ end
32
+
33
+ Process.kill('INT', consumer_pid)
34
+
35
+ eval(response.chomp).must_equal user_key
36
+ end
37
+ end
@@ -0,0 +1,36 @@
1
+ require_relative './_init'
2
+
3
+ describe 'Task' do
4
+ # Doesn't stop processes
5
+ before do
6
+ ENV['LOCAL'] = 'redis://localhost'
7
+ @node = Rcom::Node.new('local').connect
8
+ end
9
+
10
+ it 'represents a Task' do
11
+ task = Rcom::Task.new(node: @node, queue: 'messages')
12
+ task.must_be_instance_of Rcom::Task
13
+ end
14
+
15
+ it 'works in a pub/consumer scenario' do
16
+ message = {
17
+ id: 1,
18
+ key: 'xxxccc'
19
+ }
20
+ completed_job = ''
21
+ publisher = 'bundle exec ruby test/bin/task_publisher.rb'
22
+ consumer = 'bundle exec ruby test/bin/task_consumer.rb'
23
+
24
+ # Start the consumer, wait for it to be up,
25
+ # start the publisher and wait for the message
26
+ # on the consumer side. Process, then kill
27
+ # the long-running consumer.
28
+ Open3.popen3(consumer) do |stdin, stdout, stderr, wait_thr|
29
+ spawn(publisher)
30
+ completed_job = stdout.gets
31
+ Process.kill('INT', wait_thr.pid)
32
+ end
33
+
34
+ eval(completed_job.chomp).must_equal message
35
+ end
36
+ end
@@ -0,0 +1,37 @@
1
+ require_relative './_init'
2
+
3
+ describe 'Topic' do
4
+ before do
5
+ ENV['LOCAL'] = 'redis://localhost'
6
+ @node = Rcom::Node.new('local').connect
7
+ end
8
+
9
+ it 'represents a Topic' do
10
+ topic = Rcom::Topic.new(node: @node, key: 'users')
11
+ topic.must_be_instance_of Rcom::Topic
12
+ end
13
+
14
+ it 'works in a pub/sub scenario' do
15
+ message = {
16
+ id: 1,
17
+ key: 'xxxccc'
18
+ }
19
+ read_message = ''
20
+ publisher = 'bundle exec ruby test/bin/topic_publisher.rb'
21
+ subscriber = 'bundle exec ruby test/bin/topic_subscriber.rb'
22
+
23
+ # Start the subscriber, wait for it to be up,
24
+ # start the publisher and wait for the message
25
+ # on the subscriber side. Then kill
26
+ # the long-running subscriber.
27
+ Open3.popen3(subscriber) do |stdin, stdout, stderr, wait_thr|
28
+ sleep 1
29
+ spawn(publisher)
30
+ read_message = stdout.gets
31
+ Process.kill('INT', wait_thr.pid)
32
+ end
33
+
34
+ output = eval read_message.chomp
35
+ output.must_equal message
36
+ end
37
+ end
metadata ADDED
@@ -0,0 +1,150 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rcom
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Marco Lisci
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-12-10 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: yard
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: redis
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 3.1.0
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 3.1.0
69
+ - !ruby/object:Gem::Dependency
70
+ name: msgpack
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: 0.5.9
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: 0.5.9
83
+ description: 'Redis inter-service messaging: request-response, publish-subscribe and
84
+ tasks.'
85
+ email:
86
+ - info@badshark.io
87
+ executables: []
88
+ extensions: []
89
+ extra_rdoc_files: []
90
+ files:
91
+ - ".gitignore"
92
+ - Gemfile
93
+ - LICENSE.txt
94
+ - README.md
95
+ - Rakefile
96
+ - lib/rcom.rb
97
+ - lib/rcom/node.rb
98
+ - lib/rcom/rpc.rb
99
+ - lib/rcom/task.rb
100
+ - lib/rcom/topic.rb
101
+ - lib/rcom/version.rb
102
+ - rcom.gemspec
103
+ - test/bin/rpc_consumer.rb
104
+ - test/bin/rpc_publisher.rb
105
+ - test/bin/task_consumer.rb
106
+ - test/bin/task_publisher.rb
107
+ - test/bin/topic_publisher.rb
108
+ - test/bin/topic_subscriber.rb
109
+ - test/spec/_init.rb
110
+ - test/spec/node_spec.rb
111
+ - test/spec/rpc_spec.rb
112
+ - test/spec/task_spec.rb
113
+ - test/spec/topic_spec.rb
114
+ homepage: https://github.com/badshark/rcom
115
+ licenses:
116
+ - MIT
117
+ metadata: {}
118
+ post_install_message:
119
+ rdoc_options: []
120
+ require_paths:
121
+ - lib
122
+ required_ruby_version: !ruby/object:Gem::Requirement
123
+ requirements:
124
+ - - ">="
125
+ - !ruby/object:Gem::Version
126
+ version: '0'
127
+ required_rubygems_version: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ requirements: []
133
+ rubyforge_project:
134
+ rubygems_version: 2.2.2
135
+ signing_key:
136
+ specification_version: 4
137
+ summary: Redis inter-service messaging.
138
+ test_files:
139
+ - test/bin/rpc_consumer.rb
140
+ - test/bin/rpc_publisher.rb
141
+ - test/bin/task_consumer.rb
142
+ - test/bin/task_publisher.rb
143
+ - test/bin/topic_publisher.rb
144
+ - test/bin/topic_subscriber.rb
145
+ - test/spec/_init.rb
146
+ - test/spec/node_spec.rb
147
+ - test/spec/rpc_spec.rb
148
+ - test/spec/task_spec.rb
149
+ - test/spec/topic_spec.rb
150
+ has_rdoc: