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 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