ia-redis-rpc 2.0.0.pre.dev

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.
data/redis-rpc.gemspec ADDED
@@ -0,0 +1,44 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/redis-rpc/version', __FILE__)
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = 'ia-redis-rpc'
6
+ s.version = RedisRpc::VERSION
7
+ s.license = 'GPL-3.0'
8
+ s.authors = ['Phuong Nguyen', 'Nathan Farrington']
9
+ s.email = ['nathan@nathanfarrington.com']
10
+
11
+ s.homepage = 'http://github.com/phuongnd08/redis-rpc-ruby'
12
+ s.summary = 'Lightweight RPC for Redis'
13
+ s.description = <<-DESCRIPTION
14
+ RedisRpc is the easiest to use RPC library in the world. (No small claim!).
15
+ This version is a repackage that only has Ruby implementation.
16
+
17
+ Redis is a powerful in-memory data structure server that is useful for building
18
+ fast distributed systems. Redis implements message queue functionality with its
19
+ use of list data structures and the `LPOP`, `BLPOP`, and `RPUSH` commands.
20
+ RedisRpc implements a lightweight RPC mechanism using Redis message queues to
21
+ temporarily hold RPC request and response messages. These messages are encoded
22
+ as JSON strings for portability.
23
+
24
+ Many other RPC mechanisms are either programming language specific (e.g.
25
+ Java RMI) or require boiler-plate code for explicit typing (e.g. Thrift).
26
+ RedisRpc was designed to be extremely easy to use by eliminating boiler-plate
27
+ code while also being programming language neutral. High performance was not
28
+ an initial goal of RedisRpc and other RPC libraries are likely to have better
29
+ performance. Instead, RedisRpc has better programmer performance; it lets you
30
+ get something working immediately.
31
+ DESCRIPTION
32
+
33
+ s.files = `git ls-files`.split("\n")
34
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
35
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
36
+ s.require_paths = ["lib"]
37
+
38
+ s.add_runtime_dependency 'redis'
39
+
40
+ s.add_development_dependency 'bundler'
41
+ s.add_development_dependency 'rake'
42
+ s.add_development_dependency 'rspec'
43
+ s.add_development_dependency 'byebug'
44
+ end
@@ -0,0 +1,62 @@
1
+ require_relative 'spec_helper'
2
+ require_relative '../examples/calc.rb'
3
+
4
+ describe Calculator do
5
+ context "locally" do
6
+ let(:calculator) { Calculator.new }
7
+
8
+ it 'should calculate' do
9
+ expect(calculator.val).to be == 0.0
10
+ expect(calculator.add(3)).to be == 3.0
11
+ expect(calculator.sub(2)).to be == 1.0
12
+ expect(calculator.mul(14)).to be == 14.0
13
+ expect(calculator.div(7)).to be == 2.0
14
+ expect(calculator.val).to be == 2.0
15
+ expect(calculator.clr).to be == 0.0
16
+ expect(calculator.val).to be == 0.0
17
+ end
18
+
19
+ it 'should raise when missing method is called' do
20
+ # noinspection RubyResolve
21
+ expect { calculator.a_missing_method }.to raise_error(NoMethodError)
22
+ end
23
+ end
24
+
25
+ context "over rpc" do
26
+ let(:rpc_server_builder) { lambda { RedisRpc::Server.new(Redis.new($REDIS_CONFIG), 'calc', Calculator.new, logger: Logger.new(STDERR)) } }
27
+ before(:each) do
28
+ @rpc_server = Thread.start {
29
+ rpc_server_builder.call.run
30
+ }
31
+ end
32
+ after(:each) { rpc_server_builder.call.stop! && @rpc_server.kill; rpc_server_builder.call.flush_queue! }
33
+ let(:calculator) { RedisRpc::Client.new($REDIS, 'calc', timeout: 2) }
34
+
35
+ it 'should calculate' do
36
+ expect(calculator.val).to be == 0.0
37
+ expect(calculator.add(3)).to be == 3.0
38
+ expect(calculator.sub(2)).to be == 1.0
39
+ expect(calculator.mul(14)).to be == 14.0
40
+ expect(calculator.div(7)).to be == 2.0
41
+ expect(calculator.val).to be == 2.0
42
+ expect(calculator.clr).to be == 0.0
43
+ expect(calculator.val).to be == 0.0
44
+ end
45
+
46
+ it 'should raise when missing method is called' do
47
+ # noinspection RubyResolve
48
+ expect { calculator.a_missing_method }.to raise_error(RedisRpc::RemoteException)
49
+ end
50
+
51
+ it 'should raise timeout when execution expires' do
52
+ expect { calculator.send(:sleep, 3) }.to raise_error RedisRpc::TimeoutException
53
+ end
54
+
55
+ context "the request is executed late" do
56
+ it "won't be executed" do
57
+ allow(calculator).to receive(:get_timeout_at).and_return(Time.now.to_i - 1)
58
+ expect { calculator.val }.to raise_error(RedisRpc::RemoteException, /Expired RPC call/)
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,26 @@
1
+ require_relative 'spec_helper.rb'
2
+
3
+ describe RedisRpc::Client do
4
+ let(:client) { RedisRpc::Client.new($REDIS, 'example', timeout: 1) }
5
+
6
+ context "terminated" do
7
+ it "clear the backlog" do
8
+ allow($REDIS).to receive(:blpop).and_raise SignalException.new("SIGTERM")
9
+ expect {
10
+ client.perform
11
+ }.to raise_error SignalException
12
+
13
+ expect($REDIS.llen("example")).to eq 0
14
+ end
15
+ end
16
+
17
+ context "timeout" do
18
+ it "clear the backlog" do
19
+ expect {
20
+ client.perform
21
+ }.to raise_error RedisRpc::TimeoutException
22
+
23
+ expect($REDIS.llen("example")).to eq 0
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,32 @@
1
+ require_relative 'spec_helper'
2
+
3
+ class KwargsEcho
4
+ def echo(args1, kwarg1:, kwarg2: :kwarg2)
5
+ {args1: args1, kwarg1: kwarg1, kwarg2: kwarg2}
6
+ end
7
+ end
8
+
9
+ describe KwargsEcho do
10
+ context "locally" do
11
+ let(:hall) { KwargsEcho.new }
12
+
13
+ it 'should echo' do
14
+ expect(hall.echo(1, kwarg1: :kw1)).to be == {args1: 1, kwarg1: :kw1, kwarg2: :kwarg2}
15
+ end
16
+ end
17
+
18
+ context "over rpc" do
19
+ let(:rpc_server_builder) { lambda { RedisRpc::Server.new(Redis.new($REDIS_CONFIG), 'hall', KwargsEcho.new, logger: Logger.new(STDERR)) } }
20
+ before(:each) do
21
+ @rpc_server = Thread.start {
22
+ rpc_server_builder.call.run
23
+ }
24
+ end
25
+ after(:each) { rpc_server_builder.call.stop! && @rpc_server.kill; rpc_server_builder.call.flush_queue! }
26
+ let(:hall) { RedisRpc::Client.new($REDIS, 'hall', timeout: 2) }
27
+
28
+ it 'should echo' do
29
+ expect(hall.echo(1, kwarg1: :kw1)).to be == { "args1" => 1, "kwarg1" => "kw1", "kwarg2" => "kwarg2" }
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,3 @@
1
+ port 9736
2
+ daemonize yes
3
+ pidfile redis-test.pid
@@ -0,0 +1,18 @@
1
+ require_relative 'spec_helper'
2
+
3
+ describe RedisRpc::Server do
4
+ context "running" do
5
+ it "stops" do
6
+ server = RedisRpc::Server.new(Redis.new($REDIS_CONFIG), 'calc', Array.new, logger: Logger.new(STDERR))
7
+ server_thread = Thread.start {
8
+ server.run
9
+ }
10
+ expect(server_thread.stop?).to be false
11
+ expect(server_thread.alive?).to be true
12
+
13
+ expect(server.stop!).to be true
14
+
15
+ expect(server_thread.stop?).to be true
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,53 @@
1
+ require 'bundler'
2
+ require 'logger'
3
+
4
+ begin
5
+ Bundler.require(:default, :development)
6
+ rescue Bundler::BundlerError => e
7
+ $stderr.puts e.message
8
+ $stderr.puts "Run `bundle install` to install missing gems"
9
+ exit e.status_code
10
+ end
11
+
12
+ RSpec.configure do |config|
13
+ config.before :suite do
14
+ raise 'redis-server must be on your path to run this test' if `which redis-server`.empty?
15
+ $REDIS_CONF_PATH = File.expand_path('../redis-test.conf', __FILE__)
16
+
17
+ redis_conf_contents = File.read($REDIS_CONF_PATH)
18
+ raise "pidfile must be specified in #{$REDIS_CONF_PATH}" unless redis_conf_contents['pidfile']
19
+
20
+ $REDIS_CONFIG = {
21
+ :host => 'localhost',
22
+ :port => (redis_conf_contents.match(/port ([0-9]+)/)[1].to_i rescue 6379),
23
+ :db => 15 # we'll be flushing regularly; db 15 is traditionally reserved for test
24
+ }
25
+
26
+ $stdout.write "Starting Redis on port #{$REDIS_CONFIG[:port]}... "; $stdout.flush
27
+ `redis-server #{$REDIS_CONF_PATH}`
28
+ puts 'Done.'
29
+
30
+ $REDIS = Redis.new($REDIS_CONFIG)
31
+ begin
32
+ $REDIS.ping
33
+ rescue Timeout::Error, Errno::ECONNREFUSED
34
+ retries ||= 3
35
+ sleep 1 and retry unless (retries -= 1).zero?
36
+ $stderr.puts 'Could not connect to Redis after 3 tries.'
37
+ exit
38
+ end
39
+ end
40
+
41
+ config.around :each do |example|
42
+ $REDIS.flushdb
43
+ example.call
44
+ end
45
+
46
+ config.after :suite do
47
+ pidfile = (File.read($REDIS_CONF_PATH).match(/pidfile (.+)$/)[1].chomp rescue nil)
48
+ $stdout.write "\nKilling test redis server... "; $stdout.flush
49
+ Process.kill("KILL", File.read(pidfile).chomp.to_i)
50
+ File.unlink(pidfile)
51
+ puts 'Done.'
52
+ end
53
+ end
metadata ADDED
@@ -0,0 +1,161 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ia-redis-rpc
3
+ version: !ruby/object:Gem::Version
4
+ version: 2.0.0.pre.dev
5
+ platform: ruby
6
+ authors:
7
+ - Phuong Nguyen
8
+ - Nathan Farrington
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2023-03-27 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: redis
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ">="
19
+ - !ruby/object:Gem::Version
20
+ version: '0'
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ version: '0'
28
+ - !ruby/object:Gem::Dependency
29
+ name: bundler
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: '0'
35
+ type: :development
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ - !ruby/object:Gem::Dependency
43
+ name: rake
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ type: :development
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ - !ruby/object:Gem::Dependency
57
+ name: rspec
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ type: :development
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ - !ruby/object:Gem::Dependency
71
+ name: byebug
72
+ requirement: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ version: '0'
84
+ description: |2
85
+ RedisRpc is the easiest to use RPC library in the world. (No small claim!).
86
+ This version is a repackage that only has Ruby implementation.
87
+
88
+ Redis is a powerful in-memory data structure server that is useful for building
89
+ fast distributed systems. Redis implements message queue functionality with its
90
+ use of list data structures and the `LPOP`, `BLPOP`, and `RPUSH` commands.
91
+ RedisRpc implements a lightweight RPC mechanism using Redis message queues to
92
+ temporarily hold RPC request and response messages. These messages are encoded
93
+ as JSON strings for portability.
94
+
95
+ Many other RPC mechanisms are either programming language specific (e.g.
96
+ Java RMI) or require boiler-plate code for explicit typing (e.g. Thrift).
97
+ RedisRpc was designed to be extremely easy to use by eliminating boiler-plate
98
+ code while also being programming language neutral. High performance was not
99
+ an initial goal of RedisRpc and other RPC libraries are likely to have better
100
+ performance. Instead, RedisRpc has better programmer performance; it lets you
101
+ get something working immediately.
102
+ email:
103
+ - nathan@nathanfarrington.com
104
+ executables: []
105
+ extensions: []
106
+ extra_rdoc_files: []
107
+ files:
108
+ - ".gitignore"
109
+ - CHANGELOG.markdown
110
+ - Gemfile
111
+ - LICENSE
112
+ - README.markdown
113
+ - Rakefile
114
+ - VERSION
115
+ - build-and-publish.sh
116
+ - docs/github-flavored-markdown.rb
117
+ - docs/redisrpc_example.ai
118
+ - docs/redisrpc_example.png
119
+ - docs/redisrpc_example.svg
120
+ - examples/calc.rb
121
+ - examples/client.rb
122
+ - examples/server.rb
123
+ - lib/redis-rpc.rb
124
+ - lib/redis-rpc/version.rb
125
+ - redis-rpc.gemspec
126
+ - spec/calculator_spec.rb
127
+ - spec/client_spec.rb
128
+ - spec/kwargs_spec.rb
129
+ - spec/redis-test.conf
130
+ - spec/server_spec.rb
131
+ - spec/spec_helper.rb
132
+ homepage: http://github.com/phuongnd08/redis-rpc-ruby
133
+ licenses:
134
+ - GPL-3.0
135
+ metadata: {}
136
+ post_install_message:
137
+ rdoc_options: []
138
+ require_paths:
139
+ - lib
140
+ required_ruby_version: !ruby/object:Gem::Requirement
141
+ requirements:
142
+ - - ">="
143
+ - !ruby/object:Gem::Version
144
+ version: '0'
145
+ required_rubygems_version: !ruby/object:Gem::Requirement
146
+ requirements:
147
+ - - ">"
148
+ - !ruby/object:Gem::Version
149
+ version: 1.3.1
150
+ requirements: []
151
+ rubygems_version: 3.3.3
152
+ signing_key:
153
+ specification_version: 4
154
+ summary: Lightweight RPC for Redis
155
+ test_files:
156
+ - spec/calculator_spec.rb
157
+ - spec/client_spec.rb
158
+ - spec/kwargs_spec.rb
159
+ - spec/redis-test.conf
160
+ - spec/server_spec.rb
161
+ - spec/spec_helper.rb