redis_rpc 0.0.1 → 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.
- 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
|