ruby_rabbitmq_janus 2.1.1 → 2.2.0.pre.42

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.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/config/default.md +3 -4
  3. data/config/default.yml +7 -6
  4. data/lib/generators/ruby_rabbitmq_janus/templates/migration.rb +1 -0
  5. data/lib/rrj/errors/error.rb +16 -4
  6. data/lib/rrj/errors/janus/janus.rb +0 -1
  7. data/lib/rrj/errors/janus/processus/keepalive.rb +5 -17
  8. data/lib/rrj/errors/janus/processus/keepalive/initializer.rb +61 -0
  9. data/lib/rrj/errors/janus/processus/keepalive/thread.rb +16 -0
  10. data/lib/rrj/errors/janus/processus/keepalive/timer.rb +16 -0
  11. data/lib/rrj/errors/rabbit/connect.rb +12 -12
  12. data/lib/rrj/errors/tools/gem/cluster.rb +7 -7
  13. data/lib/rrj/errors/tools/gem/config.rb +0 -14
  14. data/lib/rrj/errors/tools/gem/option.rb +7 -0
  15. data/lib/rrj/info.rb +1 -1
  16. data/lib/rrj/init.rb +0 -11
  17. data/lib/rrj/janus/processus/concurrency.rb +8 -5
  18. data/lib/rrj/janus/processus/event.rb +8 -5
  19. data/lib/rrj/janus/processus/keepalive/keepalive_initializer.rb +74 -0
  20. data/lib/rrj/janus/processus/keepalive/keepalive_message.rb +52 -0
  21. data/lib/rrj/janus/processus/keepalive/keepalive_thread.rb +71 -0
  22. data/lib/rrj/janus/processus/keepalive/keepalive_timer.rb +64 -0
  23. data/lib/rrj/janus/responses/response.rb +8 -1
  24. data/lib/rrj/janus/transactions/transaction.rb +1 -1
  25. data/lib/rrj/models/active_record.rb +6 -2
  26. data/lib/rrj/models/concerns/janus_instance_callbacks.rb +69 -0
  27. data/lib/rrj/models/concerns/{janus_instance_concern.rb → janus_instance_methods.rb} +7 -10
  28. data/lib/rrj/models/concerns/janus_instance_validations.rb +20 -0
  29. data/lib/rrj/models/mongoid.rb +7 -2
  30. data/lib/rrj/rabbit/connect.rb +14 -12
  31. data/lib/rrj/rabbit/publish/keepalive.rb +33 -0
  32. data/lib/rrj/rabbit/publish/publisher.rb +1 -0
  33. data/lib/rrj/tools/gem/cluster.rb +15 -25
  34. data/lib/rrj/tools/gem/config.rb +1 -8
  35. data/lib/rrj/tools/gem/option.rb +16 -9
  36. data/spec/rrj/tools/gem/rrj_cluster_spec.rb +2 -6
  37. data/spec/rrj/tools/gem/rrj_config_spec.rb +1 -6
  38. data/spec/support/schemas/config/config.json +13 -5
  39. metadata +30 -7
  40. data/lib/rrj/janus/processus/keepalive.rb +0 -79
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rrj/janus/processus/keepalive/keepalive_timer'
4
+ require 'rrj/janus/processus/keepalive/keepalive_message'
5
+ require 'rrj/janus/processus/keepalive/keepalive_thread'
6
+
7
+ module RubyRabbitmqJanus
8
+ module Janus
9
+ module Concurrencies
10
+ # @author VAILLANT Jeremy <jeremy.vaillant@dazzl.tv>
11
+ #
12
+ # # Manage keepalive message
13
+ #
14
+ # Create a thread for sending a message with type keepalive to session
15
+ # created by this instanciate gem
16
+ class KeepaliveInitializer < Concurrency
17
+ # Initialize a singleton object for sending keepalive to janus
18
+ def initialize(instance)
19
+ super()
20
+ @thread = KeepaliveThread.new(instance, rabbit) { initialize_thread }
21
+ rescue
22
+ raise Errors::Janus::KeepaliveInitializer::Initializer
23
+ end
24
+
25
+ # Get thread with Ruby ID
26
+ def self.thread(thread)
27
+ ObjectSpace._id2ref(thread)
28
+ rescue RangeError
29
+ puts "No thread with ID : #{thread}"
30
+ end
31
+
32
+ # Give a session Integer his gem is instantiate.
33
+ # Is waiting a thread return a response to message created sending.
34
+ #
35
+ # @example Ask session
36
+ # KeepaliveInitializer.new(123).session
37
+ # => 852803383803249
38
+ #
39
+ # @return [Fixnum] Identifier to session created by Janus
40
+ def session
41
+ @thread.timer.session do
42
+ lock.synchronize do
43
+ condition.wait(lock)
44
+ @thread.session
45
+ end
46
+ end
47
+ rescue
48
+ raise Errors::Janus::KeepaliveInitializer::Session
49
+ end
50
+
51
+ # Ask Object ID to thread managing keepalive message
52
+ #
53
+ # @example Ask ID
54
+ # KeepaliveInitializer.new(123).thread
55
+ # => 70233080652140
56
+ #
57
+ # @return [Integer] Identifier to thread in Ruby
58
+ def thread_id
59
+ @thread.__id__
60
+ rescue
61
+ raise Errors::Janus::KeepaliveInitializer::Thread
62
+ end
63
+
64
+ private
65
+
66
+ def transaction_running
67
+ @thread.initialize_janus_session
68
+ lock.synchronize { condition.signal }
69
+ @thread.start
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ # :reek:UtilityFunction
4
+
5
+ module RubyRabbitmqJanus
6
+ module Janus
7
+ module Concurrencies
8
+ # Manage message used for keepalive thread
9
+ class KeepaliveMessage
10
+ def initialize(instance)
11
+ @instance = instance
12
+ end
13
+
14
+ def session
15
+ Janus::Messages::Standard.new('base::create', param_instance)
16
+ end
17
+
18
+ def response_session(message)
19
+ RubyRabbitmqJanus::Janus::Responses::Standard.new(message).session
20
+ end
21
+
22
+ def keepalive(session)
23
+ parameter = param_session(session)
24
+ Janus::Messages::Standard.new('base::keepalive', parameter)
25
+ end
26
+
27
+ def response_acknowledgement(message)
28
+ RubyRabbitmqJanus::Janus::Responses::Standard.new(message).error?
29
+ end
30
+
31
+ def destroy(session)
32
+ parameter = param_session(session)
33
+ Janus::Messages::Standard.new('base::destroy', parameter)
34
+ end
35
+
36
+ def response_destroy(message)
37
+ RubyRabbitmqJanus::Janus::Responses::Standard.new(message)
38
+ end
39
+
40
+ private
41
+
42
+ def param_instance
43
+ { 'instance' => @instance }
44
+ end
45
+
46
+ def param_session(session)
47
+ { 'session_id' => session }.merge(param_instance)
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ # :reek:TooManyInstanceVariables
4
+
5
+ module RubyRabbitmqJanus
6
+ module Janus
7
+ module Concurrencies
8
+ # Object thread
9
+ class KeepaliveThread < Thread
10
+ attr_reader :timer, :instance, :session
11
+
12
+ def initialize(instance, rabbit, &block)
13
+ @publisher = @session = nil
14
+ @rabbit = rabbit
15
+ @timer = KeepaliveTimer.new
16
+ @message = KeepaliveMessage.new(instance)
17
+ super(&block)
18
+ end
19
+
20
+ # Initialize a transaction with Janus Instance.
21
+ # Create a session and save response
22
+ def initialize_janus_session
23
+ @publisher = publisher
24
+ @session = response_session
25
+ end
26
+
27
+ def start
28
+ @timer.loop_keepalive { response_keepalive }
29
+ end
30
+
31
+ def kill
32
+ response_destroy
33
+ super
34
+ end
35
+
36
+ def instance_is_down
37
+ janus = Models::JanusInstance.find_by_session(@session)
38
+ janus.set(enable: false)
39
+
40
+ Tools::Log.instance.fatal \
41
+ "Janus Instance [#{janus.instance}] is down, kill thread."
42
+ Thread.instance_method(:kill).bind(self).call
43
+ end
44
+
45
+ private
46
+
47
+ def publisher
48
+ Rabbit::Publisher::PublishKeepalive.new(@rabbit.channel)
49
+ end
50
+
51
+ def response_session
52
+ @message.response_session(publish(@message.session))
53
+ end
54
+
55
+ def response_keepalive
56
+ keepalive = @message.keepalive(@session)
57
+ @message.response_acknowledgement(publish(keepalive))
58
+ end
59
+
60
+ def response_destroy
61
+ destroy = @message.destroy(@session)
62
+ @message.response_destroy(publish(destroy))
63
+ end
64
+
65
+ def publish(message)
66
+ @publisher.publish(message)
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'timeout'
4
+ require 'timers'
5
+
6
+ module RubyRabbitmqJanus
7
+ module Janus
8
+ module Concurrencies
9
+ # @author VAILLANT Jeremy <jeremy.vaillant@dazzl.tv>
10
+ #
11
+ # # Manage time for thread
12
+ #
13
+ # Configure all timer used in keepalive class
14
+ class KeepaliveTimer
15
+ # Initialize timer to keeaplive thread.
16
+ # Configure timer with :
17
+ # - interval for each keepalive message
18
+ # - timeout for session response
19
+ # - timeout for publish message
20
+ def initialize
21
+ @time_to_live = Tools::Config.instance.ttl
22
+ @time_publish = @time_to_live + 5
23
+ @timer = Timers::Group.new
24
+ end
25
+
26
+ # Execute a loop with timer for sending keepalive message
27
+ # to Janus Instance
28
+ def loop_keepalive(&block)
29
+ @timer.now_and_every(@time_to_live) { prepare_loop(&block) }
30
+ loop { @timer.wait }
31
+ end
32
+
33
+ # Test if session is present/exist in Janus Instance
34
+ def session(&block)
35
+ Timeout.timeout(@time_publish) { yield }
36
+ rescue Timeout::Error
37
+ stop_timer
38
+ block.binding.receiver.instance_is_down
39
+ end
40
+
41
+ # Stop timer to keepalive thread
42
+ def stop_timer
43
+ @timer.pause
44
+ end
45
+
46
+ # Start timer to keepalive thread
47
+ def start_timer
48
+ @timer.resume
49
+ end
50
+
51
+ private
52
+
53
+ def prepare_loop(&block)
54
+ Timeout.timeout(@time_publish) do
55
+ yield
56
+ end
57
+ rescue Timeout::Error
58
+ stop_timer
59
+ block.binding.receiver.instance_is_down
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -11,7 +11,7 @@ module RubyRabbitmqJanus
11
11
  # Read a message in rabbitmq queue. This message is formatted to JSON
12
12
  # or Hash format. For developpment it's possible to used a `nice` JSON.
13
13
  class Response
14
- # Instanciate a response
14
+ # Instantiate a response
15
15
  #
16
16
  # @param [Hash] response_janus
17
17
  # Request parsing after Janus/RabbitMQ receive a response to request
@@ -49,6 +49,13 @@ module RubyRabbitmqJanus
49
49
  raise Errors::Janus::Response::ToHash
50
50
  end
51
51
 
52
+ # Test if response it's an error
53
+ #
54
+ # @return [Boolean]
55
+ def error?
56
+ @request['janus'].match?('error')
57
+ end
58
+
52
59
  private
53
60
 
54
61
  attr_accessor :request
@@ -15,7 +15,7 @@ module RubyRabbitmqJanus
15
15
  # @param [Fixnum] session
16
16
  # Use a session identifier for created message
17
17
  def initialize(session)
18
- @rabbit = Rabbit::Connect.new
18
+ @rabbit = RubyRabbitmqJanus::Rabbit::Connect.new
19
19
  @session = session
20
20
  @publisher = @exclusive = nil
21
21
  rescue
@@ -6,9 +6,13 @@ module RubyRabbitmqJanus
6
6
  #
7
7
  # Store instance information for MongoID database
8
8
  class JanusInstance < ::ActiveRecord::Base
9
- include RubyRabbitmqJanus::Models::JanusInstanceConcern
9
+ include RubyRabbitmqJanus::Models::JanusInstanceCallbacks
10
+ include RubyRabbitmqJanus::Models::JanusInstanceMethods
11
+ include RubyRabbitmqJanus::Models::JanusInstanceValidations
10
12
 
11
- before_destroy { destroy_before_action }
13
+ after_create { callback_after_after }
14
+ after_update { callback_update_after }
15
+ after_destroy { callback_destroy_after }
12
16
  end
13
17
  end
14
18
  end
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyRabbitmqJanus
4
+ # Contains all model for this gem
5
+ module Models
6
+ # Configure callback for Janus Instance models
7
+ module JanusInstanceCallbacks
8
+ extend ActiveSupport::Concern
9
+
10
+ # Create a session in Janus Instance
11
+ def callback_create_after
12
+ Tools::Log.instance.debug 'Callback AFTER_VALIDATION'
13
+ create_a_session_in_janus_instance if enable
14
+ end
15
+
16
+ # Update a keepalive transaction in Janus Instance
17
+ # Enable or Disable transaction
18
+ def callback_update_after
19
+ Tools::Log.instance.debug 'Callback AFTER_UPDATE'
20
+ if enable && enable_changed?
21
+ create_a_session_in_janus_instance
22
+ elsif !enable && enable_changed?
23
+ disable_a_session_in_janus_instance
24
+ end
25
+ end
26
+
27
+ # Destroy a session in Janus Instance
28
+ def callback_destroy_after
29
+ Tools::Log.instance.debug 'Callback AFTER_DESTROY'
30
+ destroy_a_session_in_janus_instance if enable && session? && thread?
31
+ end
32
+
33
+ private
34
+
35
+ def create_a_session_in_janus_instance
36
+ info_instance('Create session')
37
+ janus_instance = keepalive_object_new
38
+ set(session: janus_instance.session, thread: janus_instance.thread_id)
39
+ end
40
+
41
+ def disable_a_session_in_janus_instance
42
+ info_instance('Destroy session')
43
+ keepalive_object_thread.kill
44
+ unset(%I[thread session])
45
+ end
46
+
47
+ def destroy_a_session_in_janus_instance
48
+ info_instance('Destroy session')
49
+ keepalive_object_thread.kill
50
+ end
51
+
52
+ def keepalive_object
53
+ RubyRabbitmqJanus::Janus::Concurrencies::KeepaliveInitializer
54
+ end
55
+
56
+ def keepalive_object_new
57
+ keepalive_object.new(instance)
58
+ end
59
+
60
+ def keepalive_object_thread
61
+ keepalive_object.thread(thread)
62
+ end
63
+
64
+ def info_instance(text)
65
+ Tools::Log.instance.debug "#{text} in Janus Instance [##{instance}]"
66
+ end
67
+ end
68
+ end
69
+ end
@@ -5,17 +5,9 @@
5
5
  module RubyRabbitmqJanus
6
6
  module Models
7
7
  # Add method for JanusInstance model
8
- module JanusInstanceConcern
8
+ module JanusInstanceMethods
9
9
  extend ActiveSupport::Concern
10
10
 
11
- # Send an action for destroying a session in Janus Gateway instance
12
- def destroy_before_action
13
- options = { 'session_id' => session, 'instance' => instance }
14
- search_initializer(options) do |transaction|
15
- transaction.publish_message('base::destroy', options)
16
- end
17
- end
18
-
19
11
  # Class methods for JanusInstance model
20
12
  module ClassMethods
21
13
  # Disable an instance
@@ -23,7 +15,7 @@ module RubyRabbitmqJanus
23
15
  JanusInstance.find_by(session: session_id).set(enable: false)
24
16
  end
25
17
 
26
- # Delete all instance disabled
18
+ # Clean all instance disabled
27
19
  def destroys
28
20
  JanusInstance.where(enable: false).delete_all
29
21
  end
@@ -41,6 +33,11 @@ module RubyRabbitmqJanus
41
33
  rescue
42
34
  nil
43
35
  end
36
+
37
+ # Get all instance active
38
+ def enabled
39
+ JanusInstance.where(enable: true)
40
+ end
44
41
  end
45
42
 
46
43
  private
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyRabbitmqJanus
4
+ module Models
5
+ # Configure validation for JanusInstance model
6
+ module JanusInstanceValidations
7
+ extend ActiveSupport::Concern
8
+
9
+ included do
10
+ # Instance number it's mandatory, unique and with type Integer
11
+ validates :instance, presence: true,
12
+ numericality: { only_integer: true },
13
+ uniqueness: true
14
+ # This instance it's a state (enable or disable)
15
+ validates :enable, presence: true,
16
+ inclusion: { in: [true, false] }
17
+ end
18
+ end
19
+ end
20
+ end