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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b57e11a1d1707de2319945e009d0ddb52cef370d
4
- data.tar.gz: c487af813d9c74f14c1e1a337cb48be74714be75
3
+ metadata.gz: 9446d050ad21ca78739f4d986fd7703a683df9b9
4
+ data.tar.gz: 2f43f268796cd00c1b77e2fe107ef16fba2ee567
5
5
  SHA512:
6
- metadata.gz: 3635a11d7b1b7ff4a9e19c9e22ebd2ed59b59b2265021e1e455eeefec3e8cc77f86bc1c160dfd9ba61998788716b08263a07a8afe13a5f1fd1f3e1434a25d509
7
- data.tar.gz: ab06cdfef10e8ef1618db0cc3220f64a0aa61298cfade95f73a9835d03e066dcf32f045c2bf945aa6e2aed03735b1e0fdff4f68f9aa3c058ededc9e0678ae99c
6
+ metadata.gz: d81714bc20bb38db199483e30702b99155916b71ab9bec05262beb20cdb2f5d22812edae1af9308424c254de8ab8a0c3b1f0facad459217145809747b7269bf7
7
+ data.tar.gz: 274515576b96b3173eccec4d8e04888ed797a732f0e250a6bddbbee474b36d047f9fd852f41e5b7bd0d0a255a94ff4b1e55972073f3d020f8c0f96bf9e9cea56
@@ -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
- _args = JSON.parse(args, symbolize_names: true)
11
- # {uuid: uuid, _method: method, result: result}
12
- callback = @funs.delete _args[:uuid]
13
- callback.call(_args[:result]) if !callback.nil?
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)
@@ -8,35 +8,35 @@ module RedisRpc
8
8
 
9
9
  class Client
10
10
 
11
- def initialize(url, sub_channel, pub_channel, level: Logger::WARN)
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
- @res = Response.new(Redis.new(url: url), pub_channel)
16
- @callback = Callback.new
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
- @thread = Thread.new do
25
+ @handler = Thread.new do
23
26
  begin
24
- @redis.subscribe(@sub_channel, RedisRpc::EXCEPTION_CHANNEL) do |on|
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
- case channel.to_sym
32
- when RedisRpc::EXCEPTION_CHANNEL
33
- @logger.error("exception: #{args}")
34
- else
35
- begin
36
- @callback.exec_callback(args)
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
@@ -0,0 +1,6 @@
1
+ module RedisRpc
2
+
3
+ class FunctionCallbackError < StandardError
4
+ end
5
+
6
+ end
@@ -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
- @res = Response.new(@redis, channel)
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 = JSON.parse(args, symbolize_names: true)
17
- raise(ArgumentError, "miss callback uuid") if _args[:uuid].nil?
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
- @res.catch(e)
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
@@ -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 publish(request)
12
- @redis.publish(@channel, request.to_json)
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
- def catch(e)
16
- publish(RedisRpc::EXCEPTION_CHANNEL, e.message.to_s)
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 method_missing(m, *args)
20
- publish(m, args)
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
@@ -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
- @logic = Logic.new(url, front_object, pub_channel)
16
- init_log(level)
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, RedisRpc::EXCEPTION_CHANNEL) do |on|
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
- case channel.to_sym
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)")
@@ -1,3 +1,3 @@
1
1
  module RedisRpc
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
data/lib/redis_rpc.rb CHANGED
@@ -11,8 +11,32 @@ module RedisRpc
11
11
 
12
12
  class << self
13
13
 
14
- def new
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.1
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