ruby_rabbitmq_janus 0.3.0 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +64 -7
  3. data/.reek +7 -0
  4. data/.rubocop.yml +0 -3
  5. data/README.md +40 -2
  6. data/config/default.md +22 -6
  7. data/config/default.yml +24 -6
  8. data/config/requests/{test.json → admin/handle_info.json} +2 -4
  9. data/config/requests/admin/handles.json +6 -0
  10. data/config/requests/admin/log_level.json +6 -0
  11. data/config/requests/admin/sessions.json +5 -0
  12. data/config/requests/{attach.json → base/attach.json} +0 -0
  13. data/config/requests/{create.json → base/create.json} +0 -0
  14. data/config/requests/{destroy.json → base/destroy.json} +0 -0
  15. data/config/requests/{detach.json → base/detach.json} +0 -0
  16. data/config/requests/{info.json → base/info.json} +0 -0
  17. data/config/requests/base/keepalive.json +5 -0
  18. data/lib/generators/ruby_rabbitmq_janus/configuration_generator.rb +23 -0
  19. data/lib/generators/ruby_rabbitmq_janus/create_request_generator.rb +90 -0
  20. data/lib/generators/ruby_rabbitmq_janus/default_request_generator.rb +21 -0
  21. data/lib/generators/ruby_rabbitmq_janus/initializer_generator.rb +17 -0
  22. data/lib/rrj/errors/config.rb +21 -0
  23. data/lib/rrj/errors/error.rb +56 -0
  24. data/lib/rrj/errors/janus.rb +14 -0
  25. data/lib/rrj/errors/janus_message.rb +45 -0
  26. data/lib/rrj/errors/janus_response.rb +78 -0
  27. data/lib/rrj/errors/janus_transaction.rb +31 -0
  28. data/lib/rrj/errors/rabbit.rb +21 -0
  29. data/lib/rrj/errors/request.rb +21 -0
  30. data/lib/rrj/info.rb +40 -0
  31. data/lib/rrj/init.rb +113 -44
  32. data/lib/rrj/janus/admin.rb +27 -0
  33. data/lib/rrj/janus/janus.rb +10 -33
  34. data/lib/rrj/janus/keepalive.rb +69 -0
  35. data/lib/rrj/janus/message.rb +77 -22
  36. data/lib/rrj/janus/response.rb +79 -41
  37. data/lib/rrj/janus/transaction.rb +53 -0
  38. data/lib/rrj/janus/transaction_admin.rb +43 -0
  39. data/lib/rrj/janus/transaction_handle.rb +40 -0
  40. data/lib/rrj/janus/transaction_session.rb +17 -0
  41. data/lib/rrj/rabbit/connect.rb +75 -0
  42. data/lib/rrj/rabbit/propertie.rb +37 -0
  43. data/lib/rrj/rabbit/publish.rb +100 -0
  44. data/lib/rrj/rabbit/rabbit.rb +11 -0
  45. data/lib/rrj/tools/config.rb +63 -0
  46. data/lib/rrj/tools/env.rb +21 -0
  47. data/lib/rrj/tools/log.rb +106 -0
  48. data/lib/rrj/tools/replaces.rb +115 -0
  49. data/lib/rrj/tools/replaces_admin.rb +44 -0
  50. data/lib/rrj/tools/requests.rb +57 -0
  51. data/lib/rrj/tools/tools.rb +14 -0
  52. data/lib/ruby_rabbitmq_janus.rb +8 -13
  53. data/rrj.gemspec +7 -3
  54. metadata +108 -28
  55. data/config.reek +0 -3
  56. data/lib/rrj/config.rb +0 -57
  57. data/lib/rrj/janus/error.rb +0 -8
  58. data/lib/rrj/janus/message_async.rb +0 -54
  59. data/lib/rrj/janus/message_sync.rb +0 -34
  60. data/lib/rrj/log.rb +0 -63
  61. data/lib/rrj/rabbitmq/rabbitmq.rb +0 -82
  62. data/lib/rrj/request/path.rb +0 -21
  63. data/lib/rrj/request/replaces.rb +0 -109
  64. data/lib/rrj/request/requests.rb +0 -55
  65. data/lib/rrj/request/type_data.rb +0 -30
  66. data/lib/rrj/version.rb +0 -17
@@ -1,55 +1,93 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'json'
4
-
5
3
  module RubyRabbitmqJanus
6
- # @author VAILLANT Jeremy <jeremy.vaillant@dazzl.tv>
7
- # Response Janus received to RabbitMQ server
8
- class ResponseJanus
9
- # Initialiaze a response reading in RabbitMQ queue
10
- def initialize(channel, connection, opts = {})
11
- @channel = channel
12
- @connection = connection
13
- @opts = opts
14
- @response = nil
15
- end
4
+ module Janus
5
+ # @author VAILLANT Jeremy <jeremy.vaillant@dazzl.tv>
6
+ # Read and decryt a response to janus
7
+ class Response
8
+ # Instanciate a response
9
+ def initialize(response_janus)
10
+ @request = response_janus
11
+ rescue => error
12
+ Tools::Log.instance.debug "Request error : #{@request}"
13
+ raise Errors::JanusResponseInit, error
14
+ else
15
+ Tools::Log.instance.debug "Response return : #{to_json}"
16
+ end
16
17
 
17
- # Read a response to janus (in RabbitMQ queue)
18
- # @return [Hash] resultat to request
19
- def read
20
- Log.instance.debug 'Read a response'
21
- the_queue = @channel.queue(Config.instance.options['queues']['queue_from'])
22
- the_queue.subscribe(block: true) do |info, prop, pay|
23
- listen(info, prop, pay)
18
+ # Return request to json format
19
+ def to_json
20
+ analysis
21
+ @request.to_json
22
+ rescue => error
23
+ Tools::Log.instance.debug "Request error : #{@request}"
24
+ raise Errors::JanusResponseJson, error
25
+ end
26
+
27
+ # Return request to json format with nice format
28
+ def to_nice_json
29
+ JSON.pretty_generate to_hash
30
+ rescue => error
31
+ Tools::Log.instance.debug "Request error : #{@request}"
32
+ raise Errors::JanusResponsePrettyJson, error
24
33
  end
25
- return_response_json
26
- end
27
34
 
28
- private
35
+ # Return request to hash format
36
+ def to_hash
37
+ analysis
38
+ @request
39
+ rescue => error
40
+ Tools::Log.instance.debug "Request error : #{@request}"
41
+ raise Errors::JanusResponseHash, error
42
+ end
29
43
 
30
- # Listen a response to queue
31
- def listen(_delivery_info, properties, payload)
32
- if @opts['properties']['correlation'] == properties[:correlation_id]
33
- @response = payload
34
- @connection.close
44
+ # Return a response simple for client
45
+ def for_plugin
46
+ case @request['janus']
47
+ when 'success' then @request['plugindata']['data']
48
+ when 'ack' then {}
49
+ end
50
+ rescue => error
51
+ Tools::Log.instance.debug "Request error : #{@request}"
52
+ raise Errors::JanusResponsePluginData, error
35
53
  end
36
- end
37
54
 
38
- # Format the response returning
39
- def return_response_json
40
- @response = JSON.parse(@response)
41
- case @opts['janus']
42
- when 'create'
43
- merge('session_id')
44
- when 'attach'
45
- merge('handle_id')
55
+ # Return a integer to session
56
+ def session
57
+ data_id
46
58
  end
47
- @response
48
- end
49
59
 
50
- # Update value to element in Hash
51
- def merge(key)
52
- @response[key] = @response['data']['id']
60
+ # Return a integer to handle
61
+ def sender
62
+ data_id
63
+ end
64
+
65
+ private
66
+
67
+ # Read a hash and return an identifier
68
+ def data_id
69
+ analysis
70
+ @request['data']['id'].to_i
71
+ rescue => error
72
+ raise Errors::JanusResponseDataId, error
73
+ end
74
+
75
+ # Analysis response and send exception if janus return an error
76
+ # :reek:DuplicateMethodCall
77
+ def analysis
78
+ raise Errors::JanusResponseSimple, @request['error'] if error_simple?
79
+ raise Errors::JanusResponsePlugin, @request['plugindata']['data'] if error_plugin?
80
+ end
81
+
82
+ # Test if message response contains an simple error
83
+ def error_simple?
84
+ @request['janus'].equal? 'error'
85
+ end
86
+
87
+ # Test if message response contains an error in plugin
88
+ def error_plugin?
89
+ @request.key?('plugindata') && @request['plugindata']['data'].key?('error_code')
90
+ end
53
91
  end
54
92
  end
55
93
  end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyRabbitmqJanus
4
+ module Janus
5
+ # @author VAILLANT Jeremy <jeremy.vaillant@dazzl.tv>
6
+ # This class work with janus and send a series of message
7
+ # :reek:TooManyInstanceVariables
8
+ class Transaction
9
+ # Initialize an transaction
10
+ def initialize(session)
11
+ @rabbit = Rabbit::Connect.new
12
+ @session = session
13
+ @response = @handle = @publish = nil
14
+ rescue => error
15
+ raise Errors::JanusTransaction, error
16
+ end
17
+
18
+ # Opening a short transaction with rabbitmq and close when is ending
19
+ def connect(exclusive)
20
+ @rabbit.transaction_short do
21
+ choose_queue(exclusive)
22
+ send_a_message { yield }
23
+ end
24
+ end
25
+
26
+ private
27
+
28
+ attr_reader :rabbit, :session, :response, :handle, :publish
29
+
30
+ # determine queue used
31
+ # :reek:ControlParameter and :reek:BooleanParameter
32
+ def choose_queue(exclusive = false)
33
+ chan = @rabbit.channel
34
+ @publish = if exclusive
35
+ Rabbit::PublishNonExclusive.new(chan)
36
+ else
37
+ Rabbit::PublishExclusive.new(chan, '')
38
+ end
39
+ end
40
+
41
+ # Send a message to queue
42
+ def send_a_message
43
+ Janus::Response.new(@publish.send_a_message(yield))
44
+ end
45
+
46
+ # Associate handle to transaction
47
+ def create_handle
48
+ msg = Janus::Message.new('base::attach', 'session_id' => @session)
49
+ @handle = send_a_message { msg }.sender
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyRabbitmqJanus
4
+ module Janus
5
+ # @author VAILLANT Jeremy <jeremy.vaillant@dazzl.tv>
6
+ # This class work with janus and send a series of message
7
+ class TransactionAdmin < TransactionHandle
8
+ # Initialize conncetion to Rabbit and Janus
9
+ def connect
10
+ rabbit.transaction_short do
11
+ choose_queue
12
+ send_a_message { yield }
13
+ end
14
+ end
15
+
16
+ def handle_connect
17
+ rabbit.transaction_long do
18
+ choose_queue
19
+ create_handle
20
+ yield
21
+ end
22
+ end
23
+
24
+ # Publish an message in handle
25
+ def publish_message_handle(type, options = {})
26
+ opts = { 'session_id' => session, 'handle_id' => handle }
27
+ msg = Janus::MessageAdmin.new(type, opts.merge!(options))
28
+ Janus::Response.new(publish.send_a_message(msg))
29
+ end
30
+
31
+ # Stop an handle running
32
+ def handle_running_stop
33
+ secret = Tools::Config.instance.options['rabbit']['admin_pass']
34
+ publish_message_handle('base::detach', admin_secret: secret)
35
+ end
36
+
37
+ # Define queue used for admin message
38
+ def choose_queue
39
+ @publish = Rabbit::PublishAdmin.new(rabbit.channel)
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyRabbitmqJanus
4
+ module Janus
5
+ # @author VAILLANT Jeremy <jeremy.vaillant@dazzl.tv>
6
+ # This class work with janus and send a series of message
7
+ class TransactionHandle < TransactionSession
8
+ # Initialize connection to Rabbit and Janus
9
+ def handle_connect(exclusive)
10
+ rabbit.transaction_long do
11
+ choose_queue(exclusive)
12
+ create_handle
13
+ yield
14
+ end
15
+ end
16
+
17
+ # Initialize connection to Rabbit and Janus and close after sending an received
18
+ # a response
19
+ def handle_connect_and_stop(exclusive)
20
+ rabbit.transaction_short do
21
+ choose_queue(exclusive)
22
+ create_handle
23
+ yield
24
+ end
25
+ end
26
+
27
+ # Stop an handle running
28
+ def handle_running_stop
29
+ publish_message_handle('base::detach')
30
+ end
31
+
32
+ # Publish an message in handle
33
+ def publish_message_handle(type, options = {})
34
+ opts = { 'session_id' => session, 'handle_id' => handle }
35
+ msg = Janus::Message.new(type, opts.merge!(options))
36
+ Janus::Response.new(publish.send_a_message(msg))
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyRabbitmqJanus
4
+ module Janus
5
+ # @author VAILLANT Jeremy <jeremy.vaillant@dazzl.tv>
6
+ # This class work with janus and send a series of message for session level
7
+ class TransactionSession < Transaction
8
+ # Connect to session and post an message
9
+ def session_connect(exclusive)
10
+ rabbit.transaction_short do
11
+ choose_queue(exclusive)
12
+ send_a_message { yield }
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyRabbitmqJanus
4
+ module Rabbit
5
+ # @author VAILLANT Jeremy <jeremy.vaillant@dazzl.tv>
6
+ # Class for manage connection with rabbitmq
7
+ class Connect
8
+ # Initialize connection to server RabbitMQ
9
+ def initialize
10
+ Tools::Log.instance.debug 'Initialize connection with RabbitMQ'
11
+ @rabbit = Bunny.new(read_options_server)
12
+ end
13
+
14
+ # Create an transaction with rabbitmq and close after response is received
15
+ def transaction_short
16
+ response = transaction_long { yield }
17
+ close
18
+ response
19
+ end
20
+
21
+ # Create an transaction with rabbitmq and not close
22
+ def transaction_long
23
+ start
24
+ yield
25
+ end
26
+
27
+ # Openning a connection with Rabbitmq
28
+ def start
29
+ Tools::Log.instance.debug 'Connection to rabbitmq START'
30
+ @rabbit.start
31
+ rescue => message
32
+ raise Errors::ConnectionRabbitmqFailed, message
33
+ end
34
+
35
+ # Close connection to server RabbitMQ
36
+ def close
37
+ Tools::Log.instance.debug 'Connection to rabbitmq STOP'
38
+ @rabbit.close
39
+ rescue
40
+ raise Bunny::ConnectionClosedError
41
+ end
42
+
43
+ # Create an channel
44
+ def channel
45
+ Tools::Log.instance.debug 'Create an channel'
46
+ @rabbit.create_channel
47
+ end
48
+
49
+ private
50
+
51
+ # Read option for bunny instance (connection with rabbitmq)
52
+ # :reek:FeatureEnvy
53
+ def read_options_server
54
+ cfg = Tools::Config.instance.options['rabbit']
55
+ opts = {}
56
+ %w(host port pass user vhost).each do |val|
57
+ opts.merge!(val.to_sym => Tools::Env.instance.test_env_var(cfg, val))
58
+ end
59
+ opts.merge!(option_log_rabbit)
60
+ end
61
+
62
+ # Define option logs for bunny
63
+ def option_log_rabbit
64
+ if Tools::Log.instance.level.zero?
65
+ {
66
+ log_level: Tools::Log.instance.level,
67
+ log_file: Tools::Log.instance.logdev
68
+ }
69
+ else
70
+ {}
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyRabbitmqJanus
4
+ module Rabbit
5
+ # @author VAILLANT Jeremy <jeremy.vaillant@dazzl.tv>
6
+ # Manage properties to message sending in rabbitmq queue
7
+ class Propertie
8
+ attr_reader :correlation
9
+
10
+ # Initialize a message sending to rabbitmq
11
+ def initialize
12
+ Tools::Log.instance.debug 'initalize a propertie to message'
13
+ @correlation = SecureRandom.uuid
14
+ end
15
+
16
+ # Define options sending to rabbitmq
17
+ def options
18
+ Tools::Log.instance.debug 'Add options to propertie to message'
19
+ {
20
+ routing_key: Tools::Config.instance.options['queues']['queue_to'],
21
+ correlation_id: @correlation,
22
+ content_type: 'application/json'
23
+ }
24
+ end
25
+
26
+ # Define option sending to rabbitmq for janus admin message
27
+ def options_admin
28
+ Tools::Log.instance.debug 'Add options to propertie to message'
29
+ {
30
+ routing_key: Tools::Config.instance.options['queues']['admin']['queue_to'],
31
+ correlation_id: @correlation,
32
+ content_type: 'application/json'
33
+ }
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,100 @@
1
+ # frozen_string_literal: true
2
+
3
+ # :reek:FeatureEnvy and :reek:InstanceVariableAssumption
4
+ module RubyRabbitmqJanus
5
+ module Rabbit
6
+ # @author VAILLANT Jeremy <jeremy.vaillant@dazzl.tv>
7
+ # @abstract Publish message in RabbitMQ
8
+ class Publish
9
+ # Define Exchange operation
10
+ def initialize(exchange)
11
+ Tools::Log.instance.debug 'Create/Connect to queue'
12
+ @exchange = exchange.default_exchange
13
+ @message = nil
14
+ end
15
+
16
+ # Send a message in queue
17
+ def send_a_message(request)
18
+ Tools::Log.instance.info "Send request type : #{request.type}"
19
+ @message = request
20
+ @exchange.publish(@message.to_json, request.options)
21
+ end
22
+ end
23
+
24
+ # @author VAILLANT Jeremy <jeremy.vaillant@dazzl.tv>
25
+ # @abstract Publish an message in RabbitMQ and waiting a response
26
+ class PublishReply < Publish
27
+ # Initialize a queue
28
+ def initialize(exchange)
29
+ @condition = ConditionVariable.new
30
+ @lock = Mutex.new
31
+ @response = nil
32
+ subscribe_to_queue
33
+ super
34
+ end
35
+
36
+ # Publish an message in rabbitmq
37
+ def send_a_message(request)
38
+ Tools::Log.instance.info "Send request type : #{request.type}"
39
+ @exchange.publish(read_message(request),
40
+ request.options.merge!(reply_to: @reply.name))
41
+ @lock.synchronize { @condition.wait(@lock) }
42
+ @response
43
+ end
44
+
45
+ private
46
+
47
+ # Read message and return to JSON format
48
+ def read_message(request)
49
+ @message = request
50
+ @message.to_json
51
+ end
52
+
53
+ # Subscribe to queue in Rabbitmq
54
+ def subscribe_to_queue
55
+ @reply.subscribe do |_delivery_info, properties, payload|
56
+ if @message.correlation.eql?(properties.correlation_id)
57
+ @response = JSON.parse payload
58
+ @lock.synchronize { @condition.signal }
59
+ end
60
+ end
61
+ end
62
+ end
63
+
64
+ # @author VAILLANT Jeremy <jeremy.vaillant@dazzl.tv>
65
+ # Publish message in non exclusive queue
66
+ class PublishNonExclusive < PublishReply
67
+ # Initialize an queue non exclusive
68
+ def initialize(exchange)
69
+ @reply = exchange.queue(Tools::Config.instance.options['queues']['queue_from'])
70
+ super(exchange)
71
+ end
72
+ end
73
+
74
+ # Publish for admin Janus
75
+ class PublishAdmin < PublishReply
76
+ # Initialize an queue non exclusive
77
+ def initialize(exchange)
78
+ name = Tools::Config.instance.options['queues']['admin']['queue_from']
79
+ @reply = exchange.queue(name)
80
+ super(exchange)
81
+ end
82
+ end
83
+
84
+ # @author VAILLANT Jeremy <jeremy.vaillant@dazzl.tv>
85
+ # Publish message in exclusive queue
86
+ class PublishExclusive < PublishReply
87
+ # Initialize an queue exclusive
88
+ def initialize(exchange, name_queue = '')
89
+ @reply = exchange.queue(name_queue, exclusive: true)
90
+ super(exchange)
91
+ end
92
+
93
+ # Name to queue
94
+ # @return [String] Name to queue used
95
+ def queue_name
96
+ @reply.name
97
+ end
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rrj/rabbit/connect'
4
+ require 'rrj/rabbit/publish'
5
+ require 'rrj/rabbit/propertie'
6
+
7
+ module RubyRabbitmqJanus
8
+ # Module rabbit interaction
9
+ module Rabbit
10
+ end
11
+ end
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyRabbitmqJanus
4
+ module Tools
5
+ # @author VAILLANT Jeremy <jeremy.vaillant@dazzl.tv>
6
+ # Loading a yaml file for apply a configuration to gem.
7
+ class Config
8
+ include Singleton
9
+
10
+ attr_reader :options
11
+
12
+ # Define a default path to file configuration
13
+ DEFAULT_PATH = File.realpath(File.join(File.dirname(__FILE__), '..', '..'))
14
+
15
+ # Define a default name to file configuration
16
+ DEFAULT_CONF = 'config/default.yml'
17
+
18
+ # Define a default override file configuration
19
+ CUSTOMIZE_CONF = 'config/ruby-rabbitmq-janus.yml'
20
+
21
+ # Initialize configuration file default or customize if exist
22
+ def initialize
23
+ @options = nil
24
+ conf_customize
25
+ conf_default
26
+ define_log_level_used
27
+ end
28
+
29
+ private
30
+
31
+ # Load configuration file yaml
32
+ # @return [Yaml] Configuration file
33
+ # @param file [String] Path to configuration file (with name)
34
+ # :reek:UtilityFunction { public_methods_only: true }
35
+ def load_configuration(file)
36
+ Tools::Log.instance.info("Loading configuration file : #{file}")
37
+ YAML.load(File.read(file))
38
+ rescue
39
+ raise Errors::ConfigFileNotFound, file
40
+ end
41
+
42
+ # Load customize configuration file if exist
43
+ def conf_customize
44
+ file = File.join(Dir.pwd, CUSTOMIZE_CONF)
45
+ @options = load_configuration(file) if File.exist?(file)
46
+ end
47
+
48
+ # Load default configuration if customize configuration doesn't exist
49
+ def conf_default
50
+ file = File.join(DEFAULT_PATH, DEFAULT_CONF)
51
+ @options ||= load_configuration(file)
52
+ end
53
+
54
+ # Define log lvel used in this gem
55
+ def define_log_level_used
56
+ Tools::Log.instance.level = \
57
+ Tools::Log::LEVELS[@options['gem']['log']['level'].to_sym]
58
+ rescue
59
+ raise Errors::LevelNotDefine
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyRabbitmqJanus
4
+ # Contains all tools necessary in this gem
5
+ module Tools
6
+ # Class for tools used in gem
7
+ # :reek:UtilityFunction
8
+ class Env
9
+ include Singleton
10
+
11
+ def test_env_var(configuration, key)
12
+ test = configuration[key.to_s]
13
+ if test.is_a?(String)
14
+ test.include?('ENV') ? ENV[test.gsub("ENV['", '').gsub("']", '')] : test
15
+ else
16
+ test
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end