redis_rpc 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/redis_rpc/callback.rb +14 -5
- data/lib/redis_rpc/client.rb +18 -20
- data/lib/redis_rpc/error.rb +6 -0
- data/lib/redis_rpc/logic.rb +16 -8
- data/lib/redis_rpc/parser.rb +50 -0
- data/lib/redis_rpc/response.rb +49 -7
- data/lib/redis_rpc/server.rb +7 -14
- data/lib/redis_rpc/version.rb +1 -1
- data/lib/redis_rpc.rb +25 -1
- metadata +3 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9446d050ad21ca78739f4d986fd7703a683df9b9
|
4
|
+
data.tar.gz: 2f43f268796cd00c1b77e2fe107ef16fba2ee567
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d81714bc20bb38db199483e30702b99155916b71ab9bec05262beb20cdb2f5d22812edae1af9308424c254de8ab8a0c3b1f0facad459217145809747b7269bf7
|
7
|
+
data.tar.gz: 274515576b96b3173eccec4d8e04888ed797a732f0e250a6bddbbee474b36d047f9fd852f41e5b7bd0d0a255a94ff4b1e55972073f3d020f8c0f96bf9e9cea56
|
data/lib/redis_rpc/callback.rb
CHANGED
@@ -1,16 +1,25 @@
|
|
1
|
+
require "redis_rpc/error.rb"
|
2
|
+
|
1
3
|
module RedisRpc
|
2
4
|
|
3
5
|
class Callback
|
4
6
|
|
5
|
-
def initialize
|
7
|
+
def initialize(logger)
|
8
|
+
@logger = logger
|
6
9
|
@funs = {}
|
7
10
|
end
|
8
11
|
|
9
12
|
def exec_callback(args)
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
13
|
+
begin
|
14
|
+
# {uuid: uuid, _method: method, result: result, error: error}
|
15
|
+
callback = @funs.delete args[:uuid]
|
16
|
+
if !callback.nil?
|
17
|
+
callback.call(args[:error].nil? ? nil : FunctionCallbackError.new(args[:error]), args[:result])
|
18
|
+
true
|
19
|
+
end
|
20
|
+
rescue Exception => e
|
21
|
+
@logger.error(e)
|
22
|
+
end
|
14
23
|
end
|
15
24
|
|
16
25
|
def push(uuid, callback)
|
data/lib/redis_rpc/client.rb
CHANGED
@@ -8,35 +8,35 @@ module RedisRpc
|
|
8
8
|
|
9
9
|
class Client
|
10
10
|
|
11
|
-
|
11
|
+
attr_accessor :handler
|
12
|
+
|
13
|
+
def initialize(url, sub_channel, pub_channel, level: Logger::WARN, secret_key: nil, timeout: 10.0)
|
12
14
|
@redis = Redis.new(url: url)
|
13
15
|
@sub_channel = sub_channel
|
14
16
|
@pub_channel = pub_channel
|
15
|
-
@
|
16
|
-
@
|
17
|
-
init_log(level)
|
17
|
+
@timeout = timeout
|
18
|
+
@parser = Parser.new(secret_key)
|
19
|
+
@res = Response.new(Redis.new(url: url), pub_channel, init_log(level), @parser)
|
20
|
+
@callback = Callback.new(init_log(level))
|
18
21
|
exec
|
19
22
|
end
|
20
23
|
|
21
24
|
def exec
|
22
|
-
@
|
25
|
+
@handler = Thread.new do
|
23
26
|
begin
|
24
|
-
@redis.subscribe(@sub_channel
|
27
|
+
@redis.subscribe(@sub_channel) do |on|
|
25
28
|
on.subscribe do |channel, subscriptions|
|
26
29
|
@logger.info("Subscribed to ##{channel} (#{subscriptions} subscriptions)")
|
27
30
|
end
|
28
31
|
|
29
32
|
on.message do |channel, args|
|
30
33
|
@logger.info("##{channel}: #{args}")
|
31
|
-
|
32
|
-
|
33
|
-
@logger.error("
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
rescue Exception => e
|
38
|
-
@logger.error(e.message.to_s)
|
39
|
-
end
|
34
|
+
begin
|
35
|
+
_args = @parser.parse(args)
|
36
|
+
@logger.error(ArgumentError.new("miss method uuid")) and return if _args[:uuid].nil?
|
37
|
+
@res.sync_callback(_args, @timeout) if !@callback.exec_callback(_args)
|
38
|
+
rescue Exception => e
|
39
|
+
@logger.error(e)
|
40
40
|
end
|
41
41
|
end
|
42
42
|
on.unsubscribe do |channel, subscriptions|
|
@@ -68,13 +68,11 @@ module RedisRpc
|
|
68
68
|
params: args,
|
69
69
|
uuid: SecureRandom.uuid
|
70
70
|
}
|
71
|
-
@callback.push(request[:uuid], block)
|
72
|
-
@res.publish(request)
|
71
|
+
@callback.push(request[:uuid], block) if !block.nil?
|
72
|
+
_sync_handler = @res.publish(request, @timeout)
|
73
|
+
return block.nil? ? _sync_handler : nil
|
73
74
|
end
|
74
75
|
|
75
76
|
end
|
76
77
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
78
|
end
|
data/lib/redis_rpc/logic.rb
CHANGED
@@ -5,24 +5,32 @@ module RedisRpc
|
|
5
5
|
|
6
6
|
attr_accessor :res
|
7
7
|
|
8
|
-
def initialize(url, callback, channel)
|
8
|
+
def initialize(url, callback, channel, logger, parser)
|
9
9
|
@redis = Redis.new(url: url)
|
10
|
-
@
|
10
|
+
@logger = logger
|
11
|
+
@res = Response.new(@redis, channel, logger, parser)
|
11
12
|
@callback = callback
|
13
|
+
@parser = parser
|
12
14
|
end
|
13
15
|
|
14
|
-
def exec(args)
|
16
|
+
def exec(args, timeout)
|
15
17
|
begin
|
16
|
-
_args =
|
17
|
-
|
18
|
-
raise(ArgumentError, "miss method name") if _args[:method].nil?
|
18
|
+
_args = @parser.parse(args)
|
19
|
+
logger.error(ArgumentError.new("miss method name or uuid")) and return if _args[:uuid].nil? || _args[:method].nil?
|
19
20
|
|
20
21
|
result = @callback.send(_args[:method], *_args[:params])
|
21
|
-
@res.publish({uuid: _args[:uuid], _method: _args[:method], result: result})
|
22
|
+
@res.publish({uuid: _args[:uuid], _method: _args[:method], result: result}, timeout)
|
22
23
|
rescue Exception => e
|
23
|
-
|
24
|
+
if defined?(_args) && !_args.nil?
|
25
|
+
@res.catch(_args[:uuid], e)
|
26
|
+
else
|
27
|
+
@logger.error(e)
|
28
|
+
end
|
24
29
|
end
|
30
|
+
rescue Exception => e
|
31
|
+
@logger.error(e)
|
25
32
|
end
|
33
|
+
|
26
34
|
end
|
27
35
|
|
28
36
|
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'openssl'
|
2
|
+
require "base64"
|
3
|
+
|
4
|
+
module RedisRpc
|
5
|
+
|
6
|
+
class Parser
|
7
|
+
|
8
|
+
attr_accessor :secret_key
|
9
|
+
|
10
|
+
def initialize(secret_key)
|
11
|
+
@secret_key = secret_key
|
12
|
+
@aes = Base64Aes.new(@secret_key) if !@secret_key.nil?
|
13
|
+
end
|
14
|
+
|
15
|
+
def parse(args)
|
16
|
+
args = @aes.decrypt(args) if !@secret_key.nil?
|
17
|
+
_args = JSON.parse(args, symbolize_names: true)
|
18
|
+
end
|
19
|
+
|
20
|
+
def pack(args)
|
21
|
+
args = @aes.encrypt(args) if !@secret_key.nil?
|
22
|
+
args
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
class Base64Aes
|
28
|
+
def initialize(key)
|
29
|
+
@key = key
|
30
|
+
@cipher = OpenSSL::Cipher::AES.new(128, :CBC).encrypt
|
31
|
+
@decipher = OpenSSL::Cipher::AES.new(128, :CBC).decrypt
|
32
|
+
end
|
33
|
+
def encrypt(data)
|
34
|
+
@cipher.key = @key
|
35
|
+
encode64(@cipher.update(data) + @cipher.final)
|
36
|
+
end
|
37
|
+
def decrypt(encrypted)
|
38
|
+
@decipher.key = @key
|
39
|
+
@decipher.update(decode64(encrypted)) + @decipher.final
|
40
|
+
end
|
41
|
+
private
|
42
|
+
def encode64(str)
|
43
|
+
Base64.strict_encode64 str
|
44
|
+
end
|
45
|
+
def decode64(str)
|
46
|
+
Base64.strict_decode64 str
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
data/lib/redis_rpc/response.rb
CHANGED
@@ -1,23 +1,65 @@
|
|
1
1
|
require 'json'
|
2
|
+
require "redis_rpc/error.rb"
|
3
|
+
require "redis_rpc/parser.rb"
|
4
|
+
|
2
5
|
module RedisRpc
|
3
6
|
|
4
7
|
class Response
|
5
8
|
|
6
|
-
def initialize(redis, channel)
|
9
|
+
def initialize(redis, channel, logger, parser)
|
7
10
|
@redis = redis
|
8
11
|
@channel = channel
|
12
|
+
@logger = logger
|
13
|
+
@parser = parser
|
14
|
+
end
|
15
|
+
|
16
|
+
def publish(request, timeout)
|
17
|
+
request_str = @parser.pack(request.to_json)
|
18
|
+
@redis.publish(@channel, request_str)
|
19
|
+
SyncHandler.new(@redis, request[:uuid], request[:method], @parser.secret_key, timeout)
|
20
|
+
end
|
21
|
+
|
22
|
+
def sync_callback(args, timeout=5)
|
23
|
+
# {uuid: uuid, _method: method, result: result, error: error}
|
24
|
+
@redis.set(args[:uuid], @parser.pack(args.to_json))
|
25
|
+
@redis.expire(args[:uuid], timeout.to_i)
|
9
26
|
end
|
10
27
|
|
11
|
-
def
|
12
|
-
@
|
28
|
+
def catch(uuid, e)
|
29
|
+
@logger.error("#{uuid}: #{e}")
|
30
|
+
request_str = @parser.pack({uuid: uuid, error: e}.to_json)
|
31
|
+
@redis.publish(@channel, request_str)
|
13
32
|
end
|
14
33
|
|
15
|
-
|
16
|
-
|
34
|
+
end
|
35
|
+
|
36
|
+
class SyncHandler
|
37
|
+
|
38
|
+
SLEEP_TIME = 0.01
|
39
|
+
|
40
|
+
def initialize(redis, uuid, _method, secret_key, timeout=30)
|
41
|
+
@redis = redis
|
42
|
+
@uuid = uuid
|
43
|
+
@_method = _method
|
44
|
+
@expires_at = Time.now + timeout
|
45
|
+
@parser = Parser.new(secret_key)
|
17
46
|
end
|
18
47
|
|
19
|
-
def
|
20
|
-
|
48
|
+
def sync
|
49
|
+
while Time.now <= @expires_at
|
50
|
+
result = @redis.get(@uuid)
|
51
|
+
if !result.nil?
|
52
|
+
@redis.del(@uuid)
|
53
|
+
_args = @parser.parse(result)
|
54
|
+
if !_args[:result].nil?
|
55
|
+
return _args[:result]
|
56
|
+
elsif !_args[:error].nil?
|
57
|
+
raise(FunctionCallbackError.new(_args[:error]))
|
58
|
+
end
|
59
|
+
end
|
60
|
+
sleep SLEEP_TIME
|
61
|
+
end
|
62
|
+
raise(Timeout::Error.new("method: #{@_method} wait for timeout"))
|
21
63
|
end
|
22
64
|
|
23
65
|
end
|
data/lib/redis_rpc/server.rb
CHANGED
@@ -3,17 +3,19 @@ require 'logger'
|
|
3
3
|
require "redis_rpc/client.rb"
|
4
4
|
require "redis_rpc/version.rb"
|
5
5
|
require "redis_rpc/logic.rb"
|
6
|
+
require "redis_rpc/parser.rb"
|
6
7
|
|
7
8
|
module RedisRpc
|
8
9
|
|
9
10
|
class Server
|
10
11
|
|
11
|
-
def initialize(url, sub_channel, pub_channel, front_object, level: Logger::WARN, standalone: true)
|
12
|
+
def initialize(url, sub_channel, pub_channel, front_object, level: Logger::WARN, standalone: true, secret_key: nil, timeout: 10.0)
|
12
13
|
@redis = Redis.new(url: url)
|
13
14
|
@sub_channel = sub_channel
|
14
15
|
@pub_channel = pub_channel
|
15
|
-
@
|
16
|
-
|
16
|
+
@timeout = timeout
|
17
|
+
@parser = Parser.new(secret_key)
|
18
|
+
@logic = Logic.new(url, front_object, pub_channel, init_log(level), @parser)
|
17
19
|
standalone ? standalone_exec : exec
|
18
20
|
end
|
19
21
|
|
@@ -25,23 +27,14 @@ module RedisRpc
|
|
25
27
|
|
26
28
|
def exec
|
27
29
|
begin
|
28
|
-
@redis.subscribe(@sub_channel
|
30
|
+
@redis.subscribe(@sub_channel) do |on|
|
29
31
|
on.subscribe do |channel, subscriptions|
|
30
32
|
@logger.info("Subscribed to ##{channel} (#{subscriptions} subscriptions)")
|
31
33
|
end
|
32
34
|
|
33
35
|
on.message do |channel, args|
|
34
36
|
@logger.info("##{channel}: #{args}")
|
35
|
-
|
36
|
-
when RedisRpc::EXCEPTION_CHANNEL
|
37
|
-
@logger.error("exception: #{args}")
|
38
|
-
else
|
39
|
-
begin
|
40
|
-
@logic.exec(args)
|
41
|
-
rescue Exception => e
|
42
|
-
@logger.error(e.message.to_s)
|
43
|
-
end
|
44
|
-
end
|
37
|
+
@logic.exec(args, @timeout)
|
45
38
|
end
|
46
39
|
on.unsubscribe do |channel, subscriptions|
|
47
40
|
@logger.info("Unsubscribed from ##{channel} (#{subscriptions} subscriptions)")
|
data/lib/redis_rpc/version.rb
CHANGED
data/lib/redis_rpc.rb
CHANGED
@@ -11,8 +11,32 @@ module RedisRpc
|
|
11
11
|
|
12
12
|
class << self
|
13
13
|
|
14
|
-
|
14
|
+
# Create a new server instance
|
15
|
+
#
|
16
|
+
# @param [String] :url (value of the environment variable REDIS_URL) a Redis URL, for a TCP connection: `redis://:[password]@[hostname]:[port]/[db]` (password, port and database are optional), for a unix socket connection: `unix://[path to Redis socket]`. This overrides all other options.
|
17
|
+
# @param [String] :sub_channel a channel to listen.
|
18
|
+
# @param [String] :pub_channel a channel to publish.
|
19
|
+
# @param [Object] :front_object The object that handles requests on the server.
|
20
|
+
# @option options [Logger::] :level (Logger::WARN) Logger options.
|
21
|
+
# @option options [Boolean] :standalone (true) set true if use a thread to handle this server.
|
22
|
+
# @option options [String] :secret_key (nil) set a long String greater than 16 when you want to encryt the data.
|
23
|
+
# @option options [Float] :timeout (10.0) timeout in seconds
|
15
24
|
|
25
|
+
def server(*args)
|
26
|
+
RedisRpc::Server.new *args
|
27
|
+
end
|
28
|
+
|
29
|
+
# Create a new client instance
|
30
|
+
#
|
31
|
+
# @param [String] :url (value of the environment variable REDIS_URL) a Redis URL, for a TCP connection: `redis://:[password]@[hostname]:[port]/[db]` (password, port and database are optional), for a unix socket connection: `unix://[path to Redis socket]`. This overrides all other options.
|
32
|
+
# @param [String] :sub_channel a channel to listen.
|
33
|
+
# @param [String] :pub_channel a channel to publish.
|
34
|
+
# @option options [Logger::] :level (Logger::WARN) Logger options.
|
35
|
+
# @option options [String] :secret_key (nil) set a long String greater than 16 when you want to encryt the data.
|
36
|
+
# @option options [Float] :timeout (10.0) timeout in seconds
|
37
|
+
|
38
|
+
def client(*args)
|
39
|
+
RedisRpc::Client.new *args
|
16
40
|
end
|
17
41
|
|
18
42
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: redis_rpc
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- benko
|
@@ -19,7 +19,9 @@ files:
|
|
19
19
|
- lib/redis_rpc.rb
|
20
20
|
- lib/redis_rpc/callback.rb
|
21
21
|
- lib/redis_rpc/client.rb
|
22
|
+
- lib/redis_rpc/error.rb
|
22
23
|
- lib/redis_rpc/logic.rb
|
24
|
+
- lib/redis_rpc/parser.rb
|
23
25
|
- lib/redis_rpc/response.rb
|
24
26
|
- lib/redis_rpc/server.rb
|
25
27
|
- lib/redis_rpc/version.rb
|