eventq_aws 1.14.0-java
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 +7 -0
 - data/bin/console +14 -0
 - data/bin/setup +8 -0
 - data/lib/eventq_aws/aws_eventq_client.rb +116 -0
 - data/lib/eventq_aws/aws_queue_client.rb +68 -0
 - data/lib/eventq_aws/aws_queue_manager.rb +98 -0
 - data/lib/eventq_aws/aws_queue_worker.rb +386 -0
 - data/lib/eventq_aws/aws_status_checker.rb +25 -0
 - data/lib/eventq_aws/aws_subscription_manager.rb +66 -0
 - data/lib/eventq_aws/jruby/aws_queue_worker.rb +370 -0
 - data/lib/eventq_aws/version.rb +5 -0
 - data/lib/eventq_aws.rb +37 -0
 - metadata +125 -0
 
    
        checksums.yaml
    ADDED
    
    | 
         @@ -0,0 +1,7 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            ---
         
     | 
| 
      
 2 
     | 
    
         
            +
            SHA256:
         
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 184374221348bf33be9f74cd8d4d8b0f26b9dea45056bd13f1eb930d03149a81
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: 3c5a842fed0e4e52ebf001b91a76348d5fb4f5c6db53ec516aaecaf523ed1b29
         
     | 
| 
      
 5 
     | 
    
         
            +
            SHA512:
         
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: daea0b813cac8d208a55c6882bdcbf17f4e602779f6da0981be747d7ec8b88ca63734b7d625b2e5739b94b89f72f48fc5a2535c83f7d519805161016e8c5e840
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: 2a9121ab2e4fe069fe0a4d452cfd5e5d675049a41367787836cf03f5b63964b6c09218cd9f4ff0352035c1f62a04b0cba3b75ec1e12719fd033aa73b06d32829
         
     | 
    
        data/bin/console
    ADDED
    
    | 
         @@ -0,0 +1,14 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #!/usr/bin/env ruby
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require "bundler/setup"
         
     | 
| 
      
 4 
     | 
    
         
            +
            require "eventq_aws"
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            # You can add fixtures and/or initialization code here to make experimenting
         
     | 
| 
      
 7 
     | 
    
         
            +
            # with your gem easier. You can also use a different console, if you like.
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            # (If you use this, don't forget to add pry to your Gemfile!)
         
     | 
| 
      
 10 
     | 
    
         
            +
            # require "pry"
         
     | 
| 
      
 11 
     | 
    
         
            +
            # Pry.start
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
            require "irb"
         
     | 
| 
      
 14 
     | 
    
         
            +
            IRB.start
         
     | 
    
        data/bin/setup
    ADDED
    
    
| 
         @@ -0,0 +1,116 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module EventQ
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Amazon
         
     | 
| 
      
 3 
     | 
    
         
            +
                # Implements a general interface to raise an event
         
     | 
| 
      
 4 
     | 
    
         
            +
                # EventQ::RabbitMq::EventQClient is the sister-class which does the same for RabbitMq
         
     | 
| 
      
 5 
     | 
    
         
            +
                class EventQClient
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                  def initialize(options)
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                    if options[:client] == nil
         
     | 
| 
      
 10 
     | 
    
         
            +
                      raise ':client (QueueClient) must be specified.'.freeze
         
     | 
| 
      
 11 
     | 
    
         
            +
                    end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                    @client = options[:client]
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                    @serialization_manager = EventQ::SerializationProviders::Manager.new
         
     | 
| 
      
 16 
     | 
    
         
            +
                    @signature_manager = EventQ::SignatureProviders::Manager.new
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                    #this array is used to record known event types
         
     | 
| 
      
 19 
     | 
    
         
            +
                    @known_event_types = []
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                  end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                  def registered?(event_type)
         
     | 
| 
      
 24 
     | 
    
         
            +
                    @known_event_types.include?(event_type)
         
     | 
| 
      
 25 
     | 
    
         
            +
                  end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                  def register_event(event_type)
         
     | 
| 
      
 28 
     | 
    
         
            +
                    if registered?(event_type)
         
     | 
| 
      
 29 
     | 
    
         
            +
                      return true
         
     | 
| 
      
 30 
     | 
    
         
            +
                    end
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                    @client.create_topic_arn(event_type)
         
     | 
| 
      
 33 
     | 
    
         
            +
                    @known_event_types << event_type
         
     | 
| 
      
 34 
     | 
    
         
            +
                    true
         
     | 
| 
      
 35 
     | 
    
         
            +
                  end
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                  def publish(topic:, event:, context: {})
         
     | 
| 
      
 38 
     | 
    
         
            +
                    raise_event(topic, event, context)
         
     | 
| 
      
 39 
     | 
    
         
            +
                  end
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
                  def raise_event(event_type, event, context = {})
         
     | 
| 
      
 42 
     | 
    
         
            +
                    register_event(event_type)
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                    with_prepared_message(event_type, event, context) do |message|
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
                      response = @client.sns.publish(
         
     | 
| 
      
 47 
     | 
    
         
            +
                        topic_arn: topic_arn(event_type),
         
     | 
| 
      
 48 
     | 
    
         
            +
                        message: message,
         
     | 
| 
      
 49 
     | 
    
         
            +
                        subject: event_type
         
     | 
| 
      
 50 
     | 
    
         
            +
                      )
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
                      EventQ.logger.debug do
         
     | 
| 
      
 53 
     | 
    
         
            +
                        "[#{self.class} #raise_event] - Published to SNS with topic_arn: #{topic_arn(event_type)} | event_type: #{event_type} | Message: #{message}"
         
     | 
| 
      
 54 
     | 
    
         
            +
                      end
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
                      response
         
     | 
| 
      
 57 
     | 
    
         
            +
                    end
         
     | 
| 
      
 58 
     | 
    
         
            +
                  end
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
                  def raise_event_in_queue(event_type, event, queue, delay, context = {})
         
     | 
| 
      
 61 
     | 
    
         
            +
                    queue_url = @client.get_queue_url(queue)
         
     | 
| 
      
 62 
     | 
    
         
            +
                    with_prepared_message(event_type, event, context) do |message|
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
                      response = @client.sqs.send_message(
         
     | 
| 
      
 65 
     | 
    
         
            +
                        queue_url: queue_url,
         
     | 
| 
      
 66 
     | 
    
         
            +
                        message_body: message,
         
     | 
| 
      
 67 
     | 
    
         
            +
                        delay_seconds: delay
         
     | 
| 
      
 68 
     | 
    
         
            +
                      )
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
                      EventQ.logger.debug do
         
     | 
| 
      
 71 
     | 
    
         
            +
                        "[#{self.class} #raise_event_in_queue] - Raised event to SQS queue: #{queue_url} | event_type: #{event_type} | Message: #{message}"
         
     | 
| 
      
 72 
     | 
    
         
            +
                      end
         
     | 
| 
      
 73 
     | 
    
         
            +
             
     | 
| 
      
 74 
     | 
    
         
            +
                      response
         
     | 
| 
      
 75 
     | 
    
         
            +
                    end
         
     | 
| 
      
 76 
     | 
    
         
            +
                  end
         
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
      
 78 
     | 
    
         
            +
                  def new_message
         
     | 
| 
      
 79 
     | 
    
         
            +
                    EventQ::QueueMessage.new
         
     | 
| 
      
 80 
     | 
    
         
            +
                  end
         
     | 
| 
      
 81 
     | 
    
         
            +
             
     | 
| 
      
 82 
     | 
    
         
            +
                  private
         
     | 
| 
      
 83 
     | 
    
         
            +
             
     | 
| 
      
 84 
     | 
    
         
            +
                  def with_prepared_message(event_type, event, context)
         
     | 
| 
      
 85 
     | 
    
         
            +
                    qm = new_message
         
     | 
| 
      
 86 
     | 
    
         
            +
                    qm.content = event
         
     | 
| 
      
 87 
     | 
    
         
            +
                    qm.type = event_type
         
     | 
| 
      
 88 
     | 
    
         
            +
                    qm.context = context
         
     | 
| 
      
 89 
     | 
    
         
            +
                    qm.content_type = event.class.to_s
         
     | 
| 
      
 90 
     | 
    
         
            +
             
     | 
| 
      
 91 
     | 
    
         
            +
                    if EventQ::Configuration.signature_secret != nil
         
     | 
| 
      
 92 
     | 
    
         
            +
                      provider = @signature_manager.get_provider(EventQ::Configuration.signature_provider)
         
     | 
| 
      
 93 
     | 
    
         
            +
                      qm.signature = provider.write(message: qm, secret: EventQ::Configuration.signature_secret)
         
     | 
| 
      
 94 
     | 
    
         
            +
                    end
         
     | 
| 
      
 95 
     | 
    
         
            +
             
     | 
| 
      
 96 
     | 
    
         
            +
                    message = serialized_message(qm)
         
     | 
| 
      
 97 
     | 
    
         
            +
             
     | 
| 
      
 98 
     | 
    
         
            +
                    response = yield(message)
         
     | 
| 
      
 99 
     | 
    
         
            +
             
     | 
| 
      
 100 
     | 
    
         
            +
                    EventQ.log(:debug, "[#{self.class}] - Raised event. Message: #{message} | Type: #{event_type}.")
         
     | 
| 
      
 101 
     | 
    
         
            +
             
     | 
| 
      
 102 
     | 
    
         
            +
                    response.message_id
         
     | 
| 
      
 103 
     | 
    
         
            +
                  end
         
     | 
| 
      
 104 
     | 
    
         
            +
             
     | 
| 
      
 105 
     | 
    
         
            +
                  def serialized_message(queue_message)
         
     | 
| 
      
 106 
     | 
    
         
            +
                    serialization_provider = @serialization_manager.get_provider(EventQ::Configuration.serialization_provider)
         
     | 
| 
      
 107 
     | 
    
         
            +
             
     | 
| 
      
 108 
     | 
    
         
            +
                    serialization_provider.serialize(queue_message)
         
     | 
| 
      
 109 
     | 
    
         
            +
                  end
         
     | 
| 
      
 110 
     | 
    
         
            +
             
     | 
| 
      
 111 
     | 
    
         
            +
                  def topic_arn(event_type)
         
     | 
| 
      
 112 
     | 
    
         
            +
                    @client.get_topic_arn(event_type)
         
     | 
| 
      
 113 
     | 
    
         
            +
                  end
         
     | 
| 
      
 114 
     | 
    
         
            +
                end
         
     | 
| 
      
 115 
     | 
    
         
            +
              end
         
     | 
| 
      
 116 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,68 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module EventQ
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Amazon
         
     | 
| 
      
 3 
     | 
    
         
            +
                class QueueClient
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                  def initialize(options = {})
         
     | 
| 
      
 6 
     | 
    
         
            +
                    if options.has_key?(:aws_key)
         
     | 
| 
      
 7 
     | 
    
         
            +
                      Aws.config[:credentials] = Aws::Credentials.new(options[:aws_key], options[:aws_secret])
         
     | 
| 
      
 8 
     | 
    
         
            +
                    end
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                    if !options.has_key?(:aws_account_number)
         
     | 
| 
      
 11 
     | 
    
         
            +
                      raise ':aws_account_number option must be specified.'.freeze
         
     | 
| 
      
 12 
     | 
    
         
            +
                    end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                    @aws_account = options[:aws_account_number]
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                    if options.has_key?(:aws_region)
         
     | 
| 
      
 17 
     | 
    
         
            +
                      @aws_region = options[:aws_region]
         
     | 
| 
      
 18 
     | 
    
         
            +
                      Aws.config[:region] = @aws_region
         
     | 
| 
      
 19 
     | 
    
         
            +
                    else
         
     | 
| 
      
 20 
     | 
    
         
            +
                      @aws_region = Aws.config[:region]
         
     | 
| 
      
 21 
     | 
    
         
            +
                    end
         
     | 
| 
      
 22 
     | 
    
         
            +
                  end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                  # Returns the AWS SQS Client
         
     | 
| 
      
 25 
     | 
    
         
            +
                  def sqs
         
     | 
| 
      
 26 
     | 
    
         
            +
                    @sqs ||= Aws::SQS::Client.new
         
     | 
| 
      
 27 
     | 
    
         
            +
                  end
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                  # Returns the AWS SNS Client
         
     | 
| 
      
 30 
     | 
    
         
            +
                  def sns
         
     | 
| 
      
 31 
     | 
    
         
            +
                    @sns ||= Aws::SNS::Client.new
         
     | 
| 
      
 32 
     | 
    
         
            +
                  end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                  def get_topic_arn(event_type)
         
     | 
| 
      
 35 
     | 
    
         
            +
                    _event_type = EventQ.create_event_type(event_type)
         
     | 
| 
      
 36 
     | 
    
         
            +
                    return "arn:aws:sns:#{@aws_region}:#{@aws_account}:#{aws_safe_name(_event_type)}"
         
     | 
| 
      
 37 
     | 
    
         
            +
                  end
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                  def get_queue_arn(queue)
         
     | 
| 
      
 40 
     | 
    
         
            +
                    _queue_name = EventQ.create_queue_name(queue.name)
         
     | 
| 
      
 41 
     | 
    
         
            +
                    return "arn:aws:sqs:#{@aws_region}:#{@aws_account}:#{aws_safe_name(_queue_name)}"
         
     | 
| 
      
 42 
     | 
    
         
            +
                  end
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                  def create_topic_arn(event_type)
         
     | 
| 
      
 45 
     | 
    
         
            +
                    _event_type = EventQ.create_event_type(event_type)
         
     | 
| 
      
 46 
     | 
    
         
            +
                    response = sns.create_topic(name: aws_safe_name(_event_type))
         
     | 
| 
      
 47 
     | 
    
         
            +
                    return response.topic_arn
         
     | 
| 
      
 48 
     | 
    
         
            +
                  end
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
                  # Returns the URL of the queue. The queue will be created when it does
         
     | 
| 
      
 51 
     | 
    
         
            +
                  #
         
     | 
| 
      
 52 
     | 
    
         
            +
                  # @param queue [EventQ::Queue]
         
     | 
| 
      
 53 
     | 
    
         
            +
                  def get_queue_url(queue)
         
     | 
| 
      
 54 
     | 
    
         
            +
                    _queue_name = EventQ.create_queue_name(queue.name)
         
     | 
| 
      
 55 
     | 
    
         
            +
                    response= sqs.get_queue_url(
         
     | 
| 
      
 56 
     | 
    
         
            +
                                                 queue_name: aws_safe_name(_queue_name),
         
     | 
| 
      
 57 
     | 
    
         
            +
                                                 queue_owner_aws_account_id: @aws_account,
         
     | 
| 
      
 58 
     | 
    
         
            +
                                               )
         
     | 
| 
      
 59 
     | 
    
         
            +
                    return response.queue_url
         
     | 
| 
      
 60 
     | 
    
         
            +
                  end
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
                  def aws_safe_name(name)
         
     | 
| 
      
 63 
     | 
    
         
            +
                    return name[0..79].gsub(/[^a-zA-Z\d_\-]/,'')
         
     | 
| 
      
 64 
     | 
    
         
            +
                  end
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
                end
         
     | 
| 
      
 67 
     | 
    
         
            +
              end
         
     | 
| 
      
 68 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,98 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module EventQ
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Amazon
         
     | 
| 
      
 3 
     | 
    
         
            +
                class QueueManager
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                  VISIBILITY_TIMEOUT = 'VisibilityTimeout'.freeze
         
     | 
| 
      
 6 
     | 
    
         
            +
                  MESSAGE_RETENTION_PERIOD = 'MessageRetentionPeriod'.freeze
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                  def initialize(options)
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                    if options[:client] == nil
         
     | 
| 
      
 11 
     | 
    
         
            +
                      raise ':client (QueueClient) must be specified.'.freeze
         
     | 
| 
      
 12 
     | 
    
         
            +
                    end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                    @client = options[:client]
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                    @visibility_timeout = 300 #5 minutes
         
     | 
| 
      
 17 
     | 
    
         
            +
                    if options.key?(:visibility_timeout)
         
     | 
| 
      
 18 
     | 
    
         
            +
                      @visibility_timeout = options[:visibility_timeout]
         
     | 
| 
      
 19 
     | 
    
         
            +
                    end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                    @message_retention_period = 1209600 #14 days (max aws value)
         
     | 
| 
      
 22 
     | 
    
         
            +
                    if options.key?(:message_retention_period)
         
     | 
| 
      
 23 
     | 
    
         
            +
                      @message_retention_period = options[:message_retention_period]
         
     | 
| 
      
 24 
     | 
    
         
            +
                    end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                  end
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                  def get_queue(queue)
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                    if queue_exists?(queue)
         
     | 
| 
      
 31 
     | 
    
         
            +
                      update_queue(queue)
         
     | 
| 
      
 32 
     | 
    
         
            +
                    else
         
     | 
| 
      
 33 
     | 
    
         
            +
                      create_queue(queue)
         
     | 
| 
      
 34 
     | 
    
         
            +
                    end
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
                  end
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
                  def create_queue(queue)
         
     | 
| 
      
 39 
     | 
    
         
            +
                    _queue_name = EventQ.create_queue_name(queue.name)
         
     | 
| 
      
 40 
     | 
    
         
            +
                    response = @client.sqs.create_queue({
         
     | 
| 
      
 41 
     | 
    
         
            +
                                                            queue_name: _queue_name,
         
     | 
| 
      
 42 
     | 
    
         
            +
                                                            attributes: {
         
     | 
| 
      
 43 
     | 
    
         
            +
                                                                VISIBILITY_TIMEOUT => @visibility_timeout.to_s,
         
     | 
| 
      
 44 
     | 
    
         
            +
                                                                MESSAGE_RETENTION_PERIOD => @message_retention_period.to_s
         
     | 
| 
      
 45 
     | 
    
         
            +
                                                            }
         
     | 
| 
      
 46 
     | 
    
         
            +
                                                        })
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
                    return response.queue_url
         
     | 
| 
      
 49 
     | 
    
         
            +
                  end
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                  def drop_queue(queue)
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
                    q = get_queue(queue)
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
                    @client.sqs.delete_queue({ queue_url: q})
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
                    return true
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
                  end
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
                  def drop_topic(event_type)
         
     | 
| 
      
 62 
     | 
    
         
            +
                    topic_arn = @client.get_topic_arn(event_type)
         
     | 
| 
      
 63 
     | 
    
         
            +
                    @client.sns.delete_topic({ topic_arn: topic_arn})
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
                    return true
         
     | 
| 
      
 66 
     | 
    
         
            +
                  end
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
                  def topic_exists?(event_type)
         
     | 
| 
      
 69 
     | 
    
         
            +
                    topic_arn = @client.get_topic_arn(event_type)
         
     | 
| 
      
 70 
     | 
    
         
            +
             
     | 
| 
      
 71 
     | 
    
         
            +
                    begin
         
     | 
| 
      
 72 
     | 
    
         
            +
                    @client.sns.get_topic_attributes({ topic_arn: topic_arn })
         
     | 
| 
      
 73 
     | 
    
         
            +
                    rescue
         
     | 
| 
      
 74 
     | 
    
         
            +
                      return false
         
     | 
| 
      
 75 
     | 
    
         
            +
                    end
         
     | 
| 
      
 76 
     | 
    
         
            +
                    return true
         
     | 
| 
      
 77 
     | 
    
         
            +
                  end
         
     | 
| 
      
 78 
     | 
    
         
            +
             
     | 
| 
      
 79 
     | 
    
         
            +
                  def queue_exists?(queue)
         
     | 
| 
      
 80 
     | 
    
         
            +
                    _queue_name = EventQ.create_queue_name(queue.name)
         
     | 
| 
      
 81 
     | 
    
         
            +
                    return @client.sqs.list_queues({ queue_name_prefix: _queue_name }).queue_urls.length > 0
         
     | 
| 
      
 82 
     | 
    
         
            +
                  end
         
     | 
| 
      
 83 
     | 
    
         
            +
             
     | 
| 
      
 84 
     | 
    
         
            +
                  def update_queue(queue)
         
     | 
| 
      
 85 
     | 
    
         
            +
                    url = @client.get_queue_url(queue)
         
     | 
| 
      
 86 
     | 
    
         
            +
                    @client.sqs.set_queue_attributes({
         
     | 
| 
      
 87 
     | 
    
         
            +
                                                         queue_url: url, # required
         
     | 
| 
      
 88 
     | 
    
         
            +
                                                          attributes: {
         
     | 
| 
      
 89 
     | 
    
         
            +
                                                              VISIBILITY_TIMEOUT => @visibility_timeout.to_s,
         
     | 
| 
      
 90 
     | 
    
         
            +
                                                              MESSAGE_RETENTION_PERIOD => @message_retention_period.to_s
         
     | 
| 
      
 91 
     | 
    
         
            +
                                                          }
         
     | 
| 
      
 92 
     | 
    
         
            +
                                                      })
         
     | 
| 
      
 93 
     | 
    
         
            +
                    return url
         
     | 
| 
      
 94 
     | 
    
         
            +
                  end
         
     | 
| 
      
 95 
     | 
    
         
            +
             
     | 
| 
      
 96 
     | 
    
         
            +
                end
         
     | 
| 
      
 97 
     | 
    
         
            +
              end
         
     | 
| 
      
 98 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,386 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module EventQ
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Amazon
         
     | 
| 
      
 3 
     | 
    
         
            +
                class QueueWorker
         
     | 
| 
      
 4 
     | 
    
         
            +
                  include EventQ::WorkerId
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
                  APPROXIMATE_RECEIVE_COUNT = 'ApproximateReceiveCount'.freeze
         
     | 
| 
      
 7 
     | 
    
         
            +
                  MESSAGE = 'Message'.freeze
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                  attr_accessor :is_running
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                  def initialize
         
     | 
| 
      
 12 
     | 
    
         
            +
                    @threads = []
         
     | 
| 
      
 13 
     | 
    
         
            +
                    @forks = []
         
     | 
| 
      
 14 
     | 
    
         
            +
                    @is_running = false
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                    @on_retry_exceeded_block = nil
         
     | 
| 
      
 17 
     | 
    
         
            +
                    @on_retry_block = nil
         
     | 
| 
      
 18 
     | 
    
         
            +
                    @on_error_block = nil
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                    @hash_helper = HashKit::Helper.new
         
     | 
| 
      
 21 
     | 
    
         
            +
                    @serialization_provider_manager = EventQ::SerializationProviders::Manager.new
         
     | 
| 
      
 22 
     | 
    
         
            +
                    @signature_provider_manager = EventQ::SignatureProviders::Manager.new
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                    @last_gc_flush = Time.now
         
     | 
| 
      
 25 
     | 
    
         
            +
                    @gc_flush_interval = 10
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                    @queue_poll_wait = 10
         
     | 
| 
      
 28 
     | 
    
         
            +
                  end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                  def start(queue, options = {}, &block)
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                    EventQ.logger.info("[#{self.class}] - Preparing to start listening for messages.")
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                    configure(queue, options)
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
                    if options[:client] == nil
         
     | 
| 
      
 37 
     | 
    
         
            +
                      raise "[#{self.class}] - :client (QueueClient) must be specified."
         
     | 
| 
      
 38 
     | 
    
         
            +
                    end
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                    raise "[#{self.class}] - Worker is already running." if running?
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
                    client = options[:client]
         
     | 
| 
      
 43 
     | 
    
         
            +
                    EventQ.logger.debug do
         
     | 
| 
      
 44 
     | 
    
         
            +
                      "[#{self.class} #start] - Listening for messages on queue: #{queue.name}, Queue Url: #{client.get_queue_url(queue)}, Queue arn: #{client.get_queue_arn(queue)}"
         
     | 
| 
      
 45 
     | 
    
         
            +
                    end
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
                    EventQ.logger.info("[#{self.class}] - Listening for messages.")
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                    @forks = []
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                    if @fork_count > 1
         
     | 
| 
      
 52 
     | 
    
         
            +
                      @fork_count.times do
         
     | 
| 
      
 53 
     | 
    
         
            +
                        pid = fork do
         
     | 
| 
      
 54 
     | 
    
         
            +
                          start_process(options, queue, block)
         
     | 
| 
      
 55 
     | 
    
         
            +
                        end
         
     | 
| 
      
 56 
     | 
    
         
            +
                        @forks.push(pid)
         
     | 
| 
      
 57 
     | 
    
         
            +
                      end
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
                      if options.key?(:wait) && options[:wait] == true
         
     | 
| 
      
 60 
     | 
    
         
            +
                        @forks.each { |pid| Process.wait(pid) }
         
     | 
| 
      
 61 
     | 
    
         
            +
                      end
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
                    else
         
     | 
| 
      
 64 
     | 
    
         
            +
                      start_process(options, queue, block)
         
     | 
| 
      
 65 
     | 
    
         
            +
                    end
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
                    return true
         
     | 
| 
      
 68 
     | 
    
         
            +
                  end
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
                  def start_process(options, queue, block)
         
     | 
| 
      
 71 
     | 
    
         
            +
             
     | 
| 
      
 72 
     | 
    
         
            +
                    %w'INT TERM'.each do |sig|
         
     | 
| 
      
 73 
     | 
    
         
            +
                      Signal.trap(sig) {
         
     | 
| 
      
 74 
     | 
    
         
            +
                        stop
         
     | 
| 
      
 75 
     | 
    
         
            +
                        exit
         
     | 
| 
      
 76 
     | 
    
         
            +
                      }
         
     | 
| 
      
 77 
     | 
    
         
            +
                    end
         
     | 
| 
      
 78 
     | 
    
         
            +
             
     | 
| 
      
 79 
     | 
    
         
            +
                    @is_running = true
         
     | 
| 
      
 80 
     | 
    
         
            +
                    @threads = []
         
     | 
| 
      
 81 
     | 
    
         
            +
             
     | 
| 
      
 82 
     | 
    
         
            +
                    #loop through each thread count
         
     | 
| 
      
 83 
     | 
    
         
            +
                    @thread_count.times do
         
     | 
| 
      
 84 
     | 
    
         
            +
                      thr = Thread.new do
         
     | 
| 
      
 85 
     | 
    
         
            +
             
     | 
| 
      
 86 
     | 
    
         
            +
                        client = options[:client]
         
     | 
| 
      
 87 
     | 
    
         
            +
                        manager = EventQ::Amazon::QueueManager.new({ client: client })
         
     | 
| 
      
 88 
     | 
    
         
            +
             
     | 
| 
      
 89 
     | 
    
         
            +
                        #begin the queue loop for this thread
         
     | 
| 
      
 90 
     | 
    
         
            +
                        while true do
         
     | 
| 
      
 91 
     | 
    
         
            +
             
     | 
| 
      
 92 
     | 
    
         
            +
                          #check if the worker is still allowed to run and break out of thread loop if not
         
     | 
| 
      
 93 
     | 
    
         
            +
                          if !@is_running
         
     | 
| 
      
 94 
     | 
    
         
            +
                            break
         
     | 
| 
      
 95 
     | 
    
         
            +
                          end
         
     | 
| 
      
 96 
     | 
    
         
            +
             
     | 
| 
      
 97 
     | 
    
         
            +
                          has_message_received = thread_process_iteration(client, manager, queue, block)
         
     | 
| 
      
 98 
     | 
    
         
            +
             
     | 
| 
      
 99 
     | 
    
         
            +
                          gc_flush
         
     | 
| 
      
 100 
     | 
    
         
            +
             
     | 
| 
      
 101 
     | 
    
         
            +
                          if !has_message_received
         
     | 
| 
      
 102 
     | 
    
         
            +
                            EventQ.logger.debug { "[#{self.class}] - No message received." }
         
     | 
| 
      
 103 
     | 
    
         
            +
                            if @sleep > 0
         
     | 
| 
      
 104 
     | 
    
         
            +
                              EventQ.logger.debug { "[#{self.class}] - Sleeping for #{@sleep} seconds" }
         
     | 
| 
      
 105 
     | 
    
         
            +
                              sleep(@sleep)
         
     | 
| 
      
 106 
     | 
    
         
            +
                            end
         
     | 
| 
      
 107 
     | 
    
         
            +
                          end
         
     | 
| 
      
 108 
     | 
    
         
            +
             
     | 
| 
      
 109 
     | 
    
         
            +
                        end
         
     | 
| 
      
 110 
     | 
    
         
            +
             
     | 
| 
      
 111 
     | 
    
         
            +
                      end
         
     | 
| 
      
 112 
     | 
    
         
            +
                      @threads.push(thr)
         
     | 
| 
      
 113 
     | 
    
         
            +
             
     | 
| 
      
 114 
     | 
    
         
            +
                    end
         
     | 
| 
      
 115 
     | 
    
         
            +
             
     | 
| 
      
 116 
     | 
    
         
            +
                    if options.key?(:wait) && options[:wait] == true
         
     | 
| 
      
 117 
     | 
    
         
            +
                      @threads.each { |thr| thr.join }
         
     | 
| 
      
 118 
     | 
    
         
            +
                    end
         
     | 
| 
      
 119 
     | 
    
         
            +
             
     | 
| 
      
 120 
     | 
    
         
            +
                  end
         
     | 
| 
      
 121 
     | 
    
         
            +
             
     | 
| 
      
 122 
     | 
    
         
            +
                  def gc_flush
         
     | 
| 
      
 123 
     | 
    
         
            +
                    if Time.now - last_gc_flush > @gc_flush_interval
         
     | 
| 
      
 124 
     | 
    
         
            +
                      GC.start
         
     | 
| 
      
 125 
     | 
    
         
            +
                      @last_gc_flush = Time.now
         
     | 
| 
      
 126 
     | 
    
         
            +
                    end
         
     | 
| 
      
 127 
     | 
    
         
            +
                  end
         
     | 
| 
      
 128 
     | 
    
         
            +
             
     | 
| 
      
 129 
     | 
    
         
            +
                  def last_gc_flush
         
     | 
| 
      
 130 
     | 
    
         
            +
                    @last_gc_flush
         
     | 
| 
      
 131 
     | 
    
         
            +
                  end
         
     | 
| 
      
 132 
     | 
    
         
            +
             
     | 
| 
      
 133 
     | 
    
         
            +
                  def thread_process_iteration(client, manager, queue, block)
         
     | 
| 
      
 134 
     | 
    
         
            +
                    #get the queue
         
     | 
| 
      
 135 
     | 
    
         
            +
                    q = manager.get_queue(queue)
         
     | 
| 
      
 136 
     | 
    
         
            +
             
     | 
| 
      
 137 
     | 
    
         
            +
                    received = false
         
     | 
| 
      
 138 
     | 
    
         
            +
             
     | 
| 
      
 139 
     | 
    
         
            +
                    begin
         
     | 
| 
      
 140 
     | 
    
         
            +
             
     | 
| 
      
 141 
     | 
    
         
            +
                      #request a message from the queue
         
     | 
| 
      
 142 
     | 
    
         
            +
                      response = client.sqs.receive_message({
         
     | 
| 
      
 143 
     | 
    
         
            +
                                                                queue_url: q,
         
     | 
| 
      
 144 
     | 
    
         
            +
                                                                max_number_of_messages: 1,
         
     | 
| 
      
 145 
     | 
    
         
            +
                                                                wait_time_seconds: @queue_poll_wait,
         
     | 
| 
      
 146 
     | 
    
         
            +
                                                                attribute_names: [APPROXIMATE_RECEIVE_COUNT]
         
     | 
| 
      
 147 
     | 
    
         
            +
                                                            })
         
     | 
| 
      
 148 
     | 
    
         
            +
             
     | 
| 
      
 149 
     | 
    
         
            +
                      #check that a message was received
         
     | 
| 
      
 150 
     | 
    
         
            +
                      if response.messages.length > 0
         
     | 
| 
      
 151 
     | 
    
         
            +
                        received = true
         
     | 
| 
      
 152 
     | 
    
         
            +
                        begin
         
     | 
| 
      
 153 
     | 
    
         
            +
                          tag_processing_thread
         
     | 
| 
      
 154 
     | 
    
         
            +
                          process_message(response, client, queue, q, block)
         
     | 
| 
      
 155 
     | 
    
         
            +
                        ensure
         
     | 
| 
      
 156 
     | 
    
         
            +
                          untag_processing_thread
         
     | 
| 
      
 157 
     | 
    
         
            +
                        end
         
     | 
| 
      
 158 
     | 
    
         
            +
             
     | 
| 
      
 159 
     | 
    
         
            +
                      end
         
     | 
| 
      
 160 
     | 
    
         
            +
             
     | 
| 
      
 161 
     | 
    
         
            +
                    rescue => e
         
     | 
| 
      
 162 
     | 
    
         
            +
                      EventQ.log(:error, "[#{self.class}] - An unhandled error occurred. Error: #{e} | Backtrace: #{e.backtrace}")
         
     | 
| 
      
 163 
     | 
    
         
            +
                      call_on_error_block(error: e)
         
     | 
| 
      
 164 
     | 
    
         
            +
                    end
         
     | 
| 
      
 165 
     | 
    
         
            +
             
     | 
| 
      
 166 
     | 
    
         
            +
                    return received
         
     | 
| 
      
 167 
     | 
    
         
            +
                  end
         
     | 
| 
      
 168 
     | 
    
         
            +
             
     | 
| 
      
 169 
     | 
    
         
            +
                  def call_on_error_block(error:, message: nil)
         
     | 
| 
      
 170 
     | 
    
         
            +
                    if @on_error_block
         
     | 
| 
      
 171 
     | 
    
         
            +
                      EventQ.logger.debug { "[#{self.class}] - Executing on_error block." }
         
     | 
| 
      
 172 
     | 
    
         
            +
                      begin
         
     | 
| 
      
 173 
     | 
    
         
            +
                        @on_error_block.call(error, message)
         
     | 
| 
      
 174 
     | 
    
         
            +
                      rescue => e
         
     | 
| 
      
 175 
     | 
    
         
            +
                        EventQ.logger.error("[#{self.class}] - An error occurred executing the on_error block. Error: #{e}")
         
     | 
| 
      
 176 
     | 
    
         
            +
                      end
         
     | 
| 
      
 177 
     | 
    
         
            +
                    else
         
     | 
| 
      
 178 
     | 
    
         
            +
                      EventQ.logger.debug { "[#{self.class}] - No on_error block specified to execute." }
         
     | 
| 
      
 179 
     | 
    
         
            +
                    end
         
     | 
| 
      
 180 
     | 
    
         
            +
                  end
         
     | 
| 
      
 181 
     | 
    
         
            +
             
     | 
| 
      
 182 
     | 
    
         
            +
                  def call_on_retry_exceeded_block(message)
         
     | 
| 
      
 183 
     | 
    
         
            +
                    if @on_retry_exceeded_block != nil
         
     | 
| 
      
 184 
     | 
    
         
            +
                      EventQ.logger.debug { "[#{self.class}] - Executing on_retry_exceeded block." }
         
     | 
| 
      
 185 
     | 
    
         
            +
                      begin
         
     | 
| 
      
 186 
     | 
    
         
            +
                        @on_retry_exceeded_block.call(message)
         
     | 
| 
      
 187 
     | 
    
         
            +
                      rescue => e
         
     | 
| 
      
 188 
     | 
    
         
            +
                        EventQ.logger.error("[#{self.class}] - An error occurred executing the on_retry_exceeded block. Error: #{e}")
         
     | 
| 
      
 189 
     | 
    
         
            +
                      end
         
     | 
| 
      
 190 
     | 
    
         
            +
                    else
         
     | 
| 
      
 191 
     | 
    
         
            +
                      EventQ.logger.debug { "[#{self.class}] - No on_retry_exceeded block specified." }
         
     | 
| 
      
 192 
     | 
    
         
            +
                    end
         
     | 
| 
      
 193 
     | 
    
         
            +
                  end
         
     | 
| 
      
 194 
     | 
    
         
            +
             
     | 
| 
      
 195 
     | 
    
         
            +
                  def call_on_retry_block(message)
         
     | 
| 
      
 196 
     | 
    
         
            +
                    if @on_retry_block
         
     | 
| 
      
 197 
     | 
    
         
            +
                      EventQ.logger.debug { "[#{self.class}] - Executing on_retry block." }
         
     | 
| 
      
 198 
     | 
    
         
            +
                      begin
         
     | 
| 
      
 199 
     | 
    
         
            +
                        @on_retry_block.call(message, abort)
         
     | 
| 
      
 200 
     | 
    
         
            +
                      rescue => e
         
     | 
| 
      
 201 
     | 
    
         
            +
                        EventQ.logger.error("[#{self.class}] - An error occurred executing the on_retry block. Error: #{e}")
         
     | 
| 
      
 202 
     | 
    
         
            +
                      end
         
     | 
| 
      
 203 
     | 
    
         
            +
                    else
         
     | 
| 
      
 204 
     | 
    
         
            +
                      EventQ.logger.debug { "[#{self.class}] - No on_retry block specified." }
         
     | 
| 
      
 205 
     | 
    
         
            +
                    end
         
     | 
| 
      
 206 
     | 
    
         
            +
                  end
         
     | 
| 
      
 207 
     | 
    
         
            +
             
     | 
| 
      
 208 
     | 
    
         
            +
                  def stop
         
     | 
| 
      
 209 
     | 
    
         
            +
                    EventQ.logger.info("[#{self.class}] - Stopping.")
         
     | 
| 
      
 210 
     | 
    
         
            +
                    @is_running = false
         
     | 
| 
      
 211 
     | 
    
         
            +
                    @threads.each { |thr| thr.join }
         
     | 
| 
      
 212 
     | 
    
         
            +
                    return true
         
     | 
| 
      
 213 
     | 
    
         
            +
                  end
         
     | 
| 
      
 214 
     | 
    
         
            +
             
     | 
| 
      
 215 
     | 
    
         
            +
                  def on_retry_exceeded(&block)
         
     | 
| 
      
 216 
     | 
    
         
            +
                    @retry_exceeded_block = block
         
     | 
| 
      
 217 
     | 
    
         
            +
                  end
         
     | 
| 
      
 218 
     | 
    
         
            +
             
     | 
| 
      
 219 
     | 
    
         
            +
                  def on_retry(&block)
         
     | 
| 
      
 220 
     | 
    
         
            +
                    @on_retry_block = block
         
     | 
| 
      
 221 
     | 
    
         
            +
                    return nil
         
     | 
| 
      
 222 
     | 
    
         
            +
                  end
         
     | 
| 
      
 223 
     | 
    
         
            +
             
     | 
| 
      
 224 
     | 
    
         
            +
                  def on_error(&block)
         
     | 
| 
      
 225 
     | 
    
         
            +
                    @on_error_block = block
         
     | 
| 
      
 226 
     | 
    
         
            +
                    return nil
         
     | 
| 
      
 227 
     | 
    
         
            +
                  end
         
     | 
| 
      
 228 
     | 
    
         
            +
             
     | 
| 
      
 229 
     | 
    
         
            +
                  def running?
         
     | 
| 
      
 230 
     | 
    
         
            +
                    return @is_running
         
     | 
| 
      
 231 
     | 
    
         
            +
                  end
         
     | 
| 
      
 232 
     | 
    
         
            +
             
     | 
| 
      
 233 
     | 
    
         
            +
                  def deserialize_message(payload)
         
     | 
| 
      
 234 
     | 
    
         
            +
                    provider = @serialization_provider_manager.get_provider(EventQ::Configuration.serialization_provider)
         
     | 
| 
      
 235 
     | 
    
         
            +
                    return provider.deserialize(payload)
         
     | 
| 
      
 236 
     | 
    
         
            +
                  end
         
     | 
| 
      
 237 
     | 
    
         
            +
             
     | 
| 
      
 238 
     | 
    
         
            +
                  def serialize_message(msg)
         
     | 
| 
      
 239 
     | 
    
         
            +
                    provider = @serialization_provider_manager.get_provider(EventQ::Configuration.serialization_provider)
         
     | 
| 
      
 240 
     | 
    
         
            +
                    return provider.serialize(msg)
         
     | 
| 
      
 241 
     | 
    
         
            +
                  end
         
     | 
| 
      
 242 
     | 
    
         
            +
             
     | 
| 
      
 243 
     | 
    
         
            +
                  private
         
     | 
| 
      
 244 
     | 
    
         
            +
             
     | 
| 
      
 245 
     | 
    
         
            +
                  def process_message(response, client, queue, q, block)
         
     | 
| 
      
 246 
     | 
    
         
            +
                    msg = response.messages[0]
         
     | 
| 
      
 247 
     | 
    
         
            +
                    retry_attempts = msg.attributes[APPROXIMATE_RECEIVE_COUNT].to_i - 1
         
     | 
| 
      
 248 
     | 
    
         
            +
             
     | 
| 
      
 249 
     | 
    
         
            +
                    #deserialize the message payload
         
     | 
| 
      
 250 
     | 
    
         
            +
                    payload = JSON.load(msg.body)
         
     | 
| 
      
 251 
     | 
    
         
            +
                    message = deserialize_message(payload[MESSAGE])
         
     | 
| 
      
 252 
     | 
    
         
            +
             
     | 
| 
      
 253 
     | 
    
         
            +
                    message_args = EventQ::MessageArgs.new(type: message.type,
         
     | 
| 
      
 254 
     | 
    
         
            +
                                                           retry_attempts: retry_attempts,
         
     | 
| 
      
 255 
     | 
    
         
            +
                                                           context: message.context,
         
     | 
| 
      
 256 
     | 
    
         
            +
                                                           content_type: message.content_type)
         
     | 
| 
      
 257 
     | 
    
         
            +
             
     | 
| 
      
 258 
     | 
    
         
            +
                    EventQ.logger.info("[#{self.class}] - Message received. Retry Attempts: #{retry_attempts}")
         
     | 
| 
      
 259 
     | 
    
         
            +
             
     | 
| 
      
 260 
     | 
    
         
            +
                    @signature_provider_manager.validate_signature(message: message, queue: queue)
         
     | 
| 
      
 261 
     | 
    
         
            +
             
     | 
| 
      
 262 
     | 
    
         
            +
                    if(!EventQ::NonceManager.is_allowed?(message.id))
         
     | 
| 
      
 263 
     | 
    
         
            +
                      EventQ.logger.info("[#{self.class}] - Duplicate Message received. Dropping message.")
         
     | 
| 
      
 264 
     | 
    
         
            +
                      client.sqs.delete_message({ queue_url: q, receipt_handle: msg.receipt_handle })
         
     | 
| 
      
 265 
     | 
    
         
            +
                      return false
         
     | 
| 
      
 266 
     | 
    
         
            +
                    end
         
     | 
| 
      
 267 
     | 
    
         
            +
             
     | 
| 
      
 268 
     | 
    
         
            +
                    #begin worker block for queue message
         
     | 
| 
      
 269 
     | 
    
         
            +
                    begin
         
     | 
| 
      
 270 
     | 
    
         
            +
             
     | 
| 
      
 271 
     | 
    
         
            +
                      block.call(message.content, message_args)
         
     | 
| 
      
 272 
     | 
    
         
            +
             
     | 
| 
      
 273 
     | 
    
         
            +
                      if message_args.abort == true
         
     | 
| 
      
 274 
     | 
    
         
            +
                        EventQ.logger.info("[#{self.class}] - Message aborted.")
         
     | 
| 
      
 275 
     | 
    
         
            +
                      else
         
     | 
| 
      
 276 
     | 
    
         
            +
                        #accept the message as processed
         
     | 
| 
      
 277 
     | 
    
         
            +
                        client.sqs.delete_message({ queue_url: q, receipt_handle: msg.receipt_handle })
         
     | 
| 
      
 278 
     | 
    
         
            +
                        EventQ.logger.info("[#{self.class}] - Message acknowledged.")
         
     | 
| 
      
 279 
     | 
    
         
            +
                      end
         
     | 
| 
      
 280 
     | 
    
         
            +
             
     | 
| 
      
 281 
     | 
    
         
            +
                    rescue => e
         
     | 
| 
      
 282 
     | 
    
         
            +
                      EventQ.logger.error("[#{self.class}] - An unhandled error happened while attempting to process a queue message. Error: #{e} | Backtrace: #{e.backtrace}")
         
     | 
| 
      
 283 
     | 
    
         
            +
                      error = true
         
     | 
| 
      
 284 
     | 
    
         
            +
                      call_on_error_block(error: e, message: message)
         
     | 
| 
      
 285 
     | 
    
         
            +
                    end
         
     | 
| 
      
 286 
     | 
    
         
            +
             
     | 
| 
      
 287 
     | 
    
         
            +
                    if message_args.abort || error
         
     | 
| 
      
 288 
     | 
    
         
            +
                      EventQ::NonceManager.failed(message.id)
         
     | 
| 
      
 289 
     | 
    
         
            +
                      reject_message(queue, client, msg, q, retry_attempts, message, message_args.abort)
         
     | 
| 
      
 290 
     | 
    
         
            +
                    else
         
     | 
| 
      
 291 
     | 
    
         
            +
                      EventQ::NonceManager.complete(message.id)
         
     | 
| 
      
 292 
     | 
    
         
            +
                    end
         
     | 
| 
      
 293 
     | 
    
         
            +
             
     | 
| 
      
 294 
     | 
    
         
            +
                    return true
         
     | 
| 
      
 295 
     | 
    
         
            +
                  end
         
     | 
| 
      
 296 
     | 
    
         
            +
             
     | 
| 
      
 297 
     | 
    
         
            +
                  def reject_message(queue, client, msg, q, retry_attempts, message, abort)
         
     | 
| 
      
 298 
     | 
    
         
            +
             
     | 
| 
      
 299 
     | 
    
         
            +
                    if !queue.allow_retry || retry_attempts >= queue.max_retry_attempts
         
     | 
| 
      
 300 
     | 
    
         
            +
             
     | 
| 
      
 301 
     | 
    
         
            +
                      EventQ.logger.info("[#{self.class}] - Message rejected removing from queue. Message: #{serialize_message(message)}")
         
     | 
| 
      
 302 
     | 
    
         
            +
             
     | 
| 
      
 303 
     | 
    
         
            +
                      #remove the message from the queue so that it does not get retried again
         
     | 
| 
      
 304 
     | 
    
         
            +
                      client.sqs.delete_message({ queue_url: q, receipt_handle: msg.receipt_handle })
         
     | 
| 
      
 305 
     | 
    
         
            +
             
     | 
| 
      
 306 
     | 
    
         
            +
                      if retry_attempts >= queue.max_retry_attempts
         
     | 
| 
      
 307 
     | 
    
         
            +
             
     | 
| 
      
 308 
     | 
    
         
            +
                        EventQ.logger.info("[#{self.class}] - Message retry attempt limit exceeded.")
         
     | 
| 
      
 309 
     | 
    
         
            +
                        call_on_retry_exceeded_block(message)
         
     | 
| 
      
 310 
     | 
    
         
            +
             
     | 
| 
      
 311 
     | 
    
         
            +
                      end
         
     | 
| 
      
 312 
     | 
    
         
            +
             
     | 
| 
      
 313 
     | 
    
         
            +
                    elsif queue.allow_retry
         
     | 
| 
      
 314 
     | 
    
         
            +
             
     | 
| 
      
 315 
     | 
    
         
            +
                      retry_attempts += 1
         
     | 
| 
      
 316 
     | 
    
         
            +
             
     | 
| 
      
 317 
     | 
    
         
            +
                      EventQ.logger.info("[#{self.class}] - Message rejected requesting retry. Attempts: #{retry_attempts}")
         
     | 
| 
      
 318 
     | 
    
         
            +
             
     | 
| 
      
 319 
     | 
    
         
            +
                      if queue.allow_retry_back_off == true
         
     | 
| 
      
 320 
     | 
    
         
            +
                        EventQ.logger.debug { "[#{self.class}] - Calculating message back off retry delay. Attempts: #{retry_attempts} * Delay: #{queue.retry_delay}" }
         
     | 
| 
      
 321 
     | 
    
         
            +
                        visibility_timeout = (queue.retry_delay * retry_attempts) / 1000
         
     | 
| 
      
 322 
     | 
    
         
            +
                        if visibility_timeout > (queue.max_retry_delay / 1000)
         
     | 
| 
      
 323 
     | 
    
         
            +
                          EventQ.logger.debug { "[#{self.class}] - Max message back off retry delay reached." }
         
     | 
| 
      
 324 
     | 
    
         
            +
                          visibility_timeout = queue.max_retry_delay / 1000
         
     | 
| 
      
 325 
     | 
    
         
            +
                        end
         
     | 
| 
      
 326 
     | 
    
         
            +
                      else
         
     | 
| 
      
 327 
     | 
    
         
            +
                        EventQ.logger.debug { "[#{self.class}] - Setting fixed retry delay for message." }
         
     | 
| 
      
 328 
     | 
    
         
            +
                        visibility_timeout = queue.retry_delay / 1000
         
     | 
| 
      
 329 
     | 
    
         
            +
                      end
         
     | 
| 
      
 330 
     | 
    
         
            +
             
     | 
| 
      
 331 
     | 
    
         
            +
                      if visibility_timeout > 43200
         
     | 
| 
      
 332 
     | 
    
         
            +
                        EventQ.logger.debug { "[#{self.class}] - AWS max visibility timeout of 12 hours has been exceeded. Setting message retry delay to 12 hours." }
         
     | 
| 
      
 333 
     | 
    
         
            +
                        visibility_timeout = 43200
         
     | 
| 
      
 334 
     | 
    
         
            +
                      end
         
     | 
| 
      
 335 
     | 
    
         
            +
             
     | 
| 
      
 336 
     | 
    
         
            +
                      EventQ.logger.debug { "[#{self.class}] - Sending message for retry. Message TTL: #{visibility_timeout}" }
         
     | 
| 
      
 337 
     | 
    
         
            +
                      client.sqs.change_message_visibility({
         
     | 
| 
      
 338 
     | 
    
         
            +
                                                           queue_url: q, # required
         
     | 
| 
      
 339 
     | 
    
         
            +
                                                           receipt_handle: msg.receipt_handle, # required
         
     | 
| 
      
 340 
     | 
    
         
            +
                                                           visibility_timeout: visibility_timeout.to_s, # required
         
     | 
| 
      
 341 
     | 
    
         
            +
                                                       })
         
     | 
| 
      
 342 
     | 
    
         
            +
             
     | 
| 
      
 343 
     | 
    
         
            +
                      call_on_retry_block(message)
         
     | 
| 
      
 344 
     | 
    
         
            +
             
     | 
| 
      
 345 
     | 
    
         
            +
                    end
         
     | 
| 
      
 346 
     | 
    
         
            +
             
     | 
| 
      
 347 
     | 
    
         
            +
                  end
         
     | 
| 
      
 348 
     | 
    
         
            +
             
     | 
| 
      
 349 
     | 
    
         
            +
                  def configure(queue, options = {})
         
     | 
| 
      
 350 
     | 
    
         
            +
             
     | 
| 
      
 351 
     | 
    
         
            +
                    @queue = queue
         
     | 
| 
      
 352 
     | 
    
         
            +
             
     | 
| 
      
 353 
     | 
    
         
            +
                    #default thread count
         
     | 
| 
      
 354 
     | 
    
         
            +
                    @thread_count = 5
         
     | 
| 
      
 355 
     | 
    
         
            +
                    if options.key?(:thread_count)
         
     | 
| 
      
 356 
     | 
    
         
            +
                      @thread_count = options[:thread_count]
         
     | 
| 
      
 357 
     | 
    
         
            +
                    end
         
     | 
| 
      
 358 
     | 
    
         
            +
             
     | 
| 
      
 359 
     | 
    
         
            +
                    #default sleep time in seconds
         
     | 
| 
      
 360 
     | 
    
         
            +
                    @sleep = 5
         
     | 
| 
      
 361 
     | 
    
         
            +
                    if options.key?(:sleep)
         
     | 
| 
      
 362 
     | 
    
         
            +
                      @sleep = options[:sleep]
         
     | 
| 
      
 363 
     | 
    
         
            +
                    end
         
     | 
| 
      
 364 
     | 
    
         
            +
             
     | 
| 
      
 365 
     | 
    
         
            +
                    @fork_count = 1
         
     | 
| 
      
 366 
     | 
    
         
            +
                    if options.key?(:fork_count)
         
     | 
| 
      
 367 
     | 
    
         
            +
                      @fork_count = options[:fork_count]
         
     | 
| 
      
 368 
     | 
    
         
            +
                    end
         
     | 
| 
      
 369 
     | 
    
         
            +
             
     | 
| 
      
 370 
     | 
    
         
            +
                    if options.key?(:gc_flush_interval)
         
     | 
| 
      
 371 
     | 
    
         
            +
                      @gc_flush_interval = options[:gc_flush_interval]
         
     | 
| 
      
 372 
     | 
    
         
            +
                    end
         
     | 
| 
      
 373 
     | 
    
         
            +
             
     | 
| 
      
 374 
     | 
    
         
            +
                    if options.key?(:queue_poll_wait)
         
     | 
| 
      
 375 
     | 
    
         
            +
                      @queue_poll_wait = options[:queue_poll_wait]
         
     | 
| 
      
 376 
     | 
    
         
            +
                    end
         
     | 
| 
      
 377 
     | 
    
         
            +
             
     | 
| 
      
 378 
     | 
    
         
            +
                    EventQ.logger.info("[#{self.class}] - Configuring. Process Count: #{@fork_count} | Thread Count: #{@thread_count} | Interval Sleep: #{@sleep} | GC Flush Interval: #{@gc_flush_interval} | Queue Poll Wait: #{@queue_poll_wait}.")
         
     | 
| 
      
 379 
     | 
    
         
            +
             
     | 
| 
      
 380 
     | 
    
         
            +
                    return true
         
     | 
| 
      
 381 
     | 
    
         
            +
             
     | 
| 
      
 382 
     | 
    
         
            +
                  end
         
     | 
| 
      
 383 
     | 
    
         
            +
             
     | 
| 
      
 384 
     | 
    
         
            +
                end
         
     | 
| 
      
 385 
     | 
    
         
            +
              end
         
     | 
| 
      
 386 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,25 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module EventQ
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Amazon
         
     | 
| 
      
 3 
     | 
    
         
            +
                class StatusChecker
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                  def initialize(queue_manager:, client:)
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                    if queue_manager == nil
         
     | 
| 
      
 8 
     | 
    
         
            +
                      raise 'queue_manager  must be specified.'.freeze
         
     | 
| 
      
 9 
     | 
    
         
            +
                    end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                    @queue_manager = queue_manager
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                  end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                  def queue?(queue)
         
     | 
| 
      
 16 
     | 
    
         
            +
                    @queue_manager.queue_exists?(queue)
         
     | 
| 
      
 17 
     | 
    
         
            +
                  end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                  def event_type?(event_type)
         
     | 
| 
      
 20 
     | 
    
         
            +
                    @queue_manager.topic_exists?(event_type)
         
     | 
| 
      
 21 
     | 
    
         
            +
                  end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                end
         
     | 
| 
      
 24 
     | 
    
         
            +
              end
         
     | 
| 
      
 25 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,66 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module EventQ
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Amazon
         
     | 
| 
      
 3 
     | 
    
         
            +
                class SubscriptionManager
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                  def initialize(options)
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                    if options[:client] == nil
         
     | 
| 
      
 8 
     | 
    
         
            +
                      raise "[#{self.class}] - :client (QueueClient) must be specified."
         
     | 
| 
      
 9 
     | 
    
         
            +
                    end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                    @client = options[:client]
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                    if options[:queue_manager] == nil
         
     | 
| 
      
 14 
     | 
    
         
            +
                      raise "[#{self.class}] - :queue_manager (QueueManager) must be specified."
         
     | 
| 
      
 15 
     | 
    
         
            +
                    end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                    @manager = options[:queue_manager]
         
     | 
| 
      
 18 
     | 
    
         
            +
                  end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                  def subscribe(event_type, queue)
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                    topic_arn = @client.create_topic_arn(event_type)
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                    q = @manager.get_queue(queue)
         
     | 
| 
      
 25 
     | 
    
         
            +
                    queue_arn = @client.get_queue_arn(queue)
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                    @client.sqs.set_queue_attributes({
         
     | 
| 
      
 28 
     | 
    
         
            +
                                                         queue_url: q,
         
     | 
| 
      
 29 
     | 
    
         
            +
                                                         attributes:{
         
     | 
| 
      
 30 
     | 
    
         
            +
                                                             'Policy'.freeze => '{
         
     | 
| 
      
 31 
     | 
    
         
            +
              "Version": "2012-10-17",
         
     | 
| 
      
 32 
     | 
    
         
            +
              "Id": "SNStoSQS",
         
     | 
| 
      
 33 
     | 
    
         
            +
              "Statement": [
         
     | 
| 
      
 34 
     | 
    
         
            +
                {
         
     | 
| 
      
 35 
     | 
    
         
            +
                  "Sid":"rule1",
         
     | 
| 
      
 36 
     | 
    
         
            +
                  "Effect": "Allow",
         
     | 
| 
      
 37 
     | 
    
         
            +
                  "Principal": "*",
         
     | 
| 
      
 38 
     | 
    
         
            +
                  "Action": "sqs:*",
         
     | 
| 
      
 39 
     | 
    
         
            +
                  "Resource": "' + queue_arn + '"
         
     | 
| 
      
 40 
     | 
    
         
            +
                }
         
     | 
| 
      
 41 
     | 
    
         
            +
              ]
         
     | 
| 
      
 42 
     | 
    
         
            +
            }'
         
     | 
| 
      
 43 
     | 
    
         
            +
                                                         }
         
     | 
| 
      
 44 
     | 
    
         
            +
                                                     })
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
                    @client.sns.subscribe({
         
     | 
| 
      
 47 
     | 
    
         
            +
                                              topic_arn: topic_arn,
         
     | 
| 
      
 48 
     | 
    
         
            +
                                              protocol: 'sqs'.freeze,
         
     | 
| 
      
 49 
     | 
    
         
            +
                                              endpoint: queue_arn
         
     | 
| 
      
 50 
     | 
    
         
            +
                                          })
         
     | 
| 
      
 51 
     | 
    
         
            +
                    EventQ.logger.debug do
         
     | 
| 
      
 52 
     | 
    
         
            +
                      "[#{self.class} #subscribe] - Subscribing Queue: #{queue.name} to topic_arn: #{topic_arn}, endpoint: #{queue_arn}"
         
     | 
| 
      
 53 
     | 
    
         
            +
                    end
         
     | 
| 
      
 54 
     | 
    
         
            +
                    return true
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
                  end
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
                  def unsubscribe(queue)
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
                    raise "[#{self.class}] - Not implemented. Please unsubscribe the queue from the topic inside the AWS Management Console."
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
                  end
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
                end
         
     | 
| 
      
 65 
     | 
    
         
            +
              end
         
     | 
| 
      
 66 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,370 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'java'
         
     | 
| 
      
 2 
     | 
    
         
            +
            java_import java.util.concurrent.Executors
         
     | 
| 
      
 3 
     | 
    
         
            +
            module EventQ
         
     | 
| 
      
 4 
     | 
    
         
            +
              module Amazon
         
     | 
| 
      
 5 
     | 
    
         
            +
                class QueueWorker
         
     | 
| 
      
 6 
     | 
    
         
            +
                  include EventQ::WorkerId
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                  APPROXIMATE_RECEIVE_COUNT = 'ApproximateReceiveCount'.freeze
         
     | 
| 
      
 9 
     | 
    
         
            +
                  MESSAGE = 'Message'.freeze
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                  attr_accessor :is_running
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                  def initialize
         
     | 
| 
      
 14 
     | 
    
         
            +
                    @is_running = false
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                    @on_retry_exceeded_block = nil
         
     | 
| 
      
 17 
     | 
    
         
            +
                    @on_retry_block = nil
         
     | 
| 
      
 18 
     | 
    
         
            +
                    @on_error_block = nil
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                    @hash_helper = HashKit::Helper.new
         
     | 
| 
      
 21 
     | 
    
         
            +
                    @serialization_provider_manager = EventQ::SerializationProviders::Manager.new
         
     | 
| 
      
 22 
     | 
    
         
            +
                    @signature_provider_manager = EventQ::SignatureProviders::Manager.new
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                    @last_gc_flush = Time.now
         
     | 
| 
      
 25 
     | 
    
         
            +
                    @gc_flush_interval = 10
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                    @queue_poll_wait = 10
         
     | 
| 
      
 28 
     | 
    
         
            +
                  end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                  def start(queue, options = {}, &block)
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                    EventQ.logger.info("[#{self.class}] - Preparing to start listening for messages.")
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                    configure(queue, options)
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
                    if options[:client] == nil
         
     | 
| 
      
 37 
     | 
    
         
            +
                      raise "[#{self.class}] - :client (QueueClient) must be specified."
         
     | 
| 
      
 38 
     | 
    
         
            +
                    end
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                    raise "[#{self.class}] - Worker is already running." if running?
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
                    client = options[:client]
         
     | 
| 
      
 43 
     | 
    
         
            +
                    EventQ.logger.debug do
         
     | 
| 
      
 44 
     | 
    
         
            +
                      "[#{self.class} #start] - Listening for messages on queue: #{queue.name}, Queue Url: #{client.get_queue_url(queue)}, Queue arn: #{client.get_queue_arn(queue)}"
         
     | 
| 
      
 45 
     | 
    
         
            +
                    end
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
                    EventQ.logger.info("[#{self.class}] - Listening for messages.")
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                    start_process(options, queue, block)
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                    return true
         
     | 
| 
      
 52 
     | 
    
         
            +
                  end
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
                  def start_process(options, queue, block)
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
                    %w'INT TERM'.each do |sig|
         
     | 
| 
      
 57 
     | 
    
         
            +
                      Signal.trap(sig) {
         
     | 
| 
      
 58 
     | 
    
         
            +
                        stop
         
     | 
| 
      
 59 
     | 
    
         
            +
                        exit
         
     | 
| 
      
 60 
     | 
    
         
            +
                      }
         
     | 
| 
      
 61 
     | 
    
         
            +
                    end
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
                    @is_running = true
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
                    @executor = java.util.concurrent.Executors::newFixedThreadPool @thread_count
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
                    #loop through each thread count
         
     | 
| 
      
 68 
     | 
    
         
            +
                    @thread_count.times do
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
                      @executor.execute do
         
     | 
| 
      
 71 
     | 
    
         
            +
             
     | 
| 
      
 72 
     | 
    
         
            +
                        client = options[:client]
         
     | 
| 
      
 73 
     | 
    
         
            +
                        manager = EventQ::Amazon::QueueManager.new({ client: client })
         
     | 
| 
      
 74 
     | 
    
         
            +
             
     | 
| 
      
 75 
     | 
    
         
            +
                        #begin the queue loop for this thread
         
     | 
| 
      
 76 
     | 
    
         
            +
                        while true do
         
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
      
 78 
     | 
    
         
            +
                          #check if the worker is still allowed to run and break out of thread loop if not
         
     | 
| 
      
 79 
     | 
    
         
            +
                          unless running?
         
     | 
| 
      
 80 
     | 
    
         
            +
                            break
         
     | 
| 
      
 81 
     | 
    
         
            +
                          end
         
     | 
| 
      
 82 
     | 
    
         
            +
             
     | 
| 
      
 83 
     | 
    
         
            +
                          if @executor.is_shutdown
         
     | 
| 
      
 84 
     | 
    
         
            +
                            break
         
     | 
| 
      
 85 
     | 
    
         
            +
                          end
         
     | 
| 
      
 86 
     | 
    
         
            +
             
     | 
| 
      
 87 
     | 
    
         
            +
                          has_message_received = thread_process_iteration(client, manager, queue, block)
         
     | 
| 
      
 88 
     | 
    
         
            +
             
     | 
| 
      
 89 
     | 
    
         
            +
                          gc_flush
         
     | 
| 
      
 90 
     | 
    
         
            +
             
     | 
| 
      
 91 
     | 
    
         
            +
                          if !has_message_received
         
     | 
| 
      
 92 
     | 
    
         
            +
                            EventQ.logger.debug { "[#{self.class}] - No message received." }
         
     | 
| 
      
 93 
     | 
    
         
            +
                            if @sleep > 0
         
     | 
| 
      
 94 
     | 
    
         
            +
                              EventQ.logger.debug { "[#{self.class}] - Sleeping for #{@sleep} seconds" }
         
     | 
| 
      
 95 
     | 
    
         
            +
                              sleep(@sleep)
         
     | 
| 
      
 96 
     | 
    
         
            +
                            end
         
     | 
| 
      
 97 
     | 
    
         
            +
                          end
         
     | 
| 
      
 98 
     | 
    
         
            +
             
     | 
| 
      
 99 
     | 
    
         
            +
                        end
         
     | 
| 
      
 100 
     | 
    
         
            +
             
     | 
| 
      
 101 
     | 
    
         
            +
                      end
         
     | 
| 
      
 102 
     | 
    
         
            +
             
     | 
| 
      
 103 
     | 
    
         
            +
                    end
         
     | 
| 
      
 104 
     | 
    
         
            +
             
     | 
| 
      
 105 
     | 
    
         
            +
                    if options.key?(:wait) && options[:wait] == true
         
     | 
| 
      
 106 
     | 
    
         
            +
                      while running? do end
         
     | 
| 
      
 107 
     | 
    
         
            +
                    end
         
     | 
| 
      
 108 
     | 
    
         
            +
             
     | 
| 
      
 109 
     | 
    
         
            +
                  end
         
     | 
| 
      
 110 
     | 
    
         
            +
             
     | 
| 
      
 111 
     | 
    
         
            +
                  def gc_flush
         
     | 
| 
      
 112 
     | 
    
         
            +
                    if Time.now - last_gc_flush > @gc_flush_interval
         
     | 
| 
      
 113 
     | 
    
         
            +
                      GC.start
         
     | 
| 
      
 114 
     | 
    
         
            +
                      @last_gc_flush = Time.now
         
     | 
| 
      
 115 
     | 
    
         
            +
                    end
         
     | 
| 
      
 116 
     | 
    
         
            +
                  end
         
     | 
| 
      
 117 
     | 
    
         
            +
             
     | 
| 
      
 118 
     | 
    
         
            +
                  def last_gc_flush
         
     | 
| 
      
 119 
     | 
    
         
            +
                    @last_gc_flush
         
     | 
| 
      
 120 
     | 
    
         
            +
                  end
         
     | 
| 
      
 121 
     | 
    
         
            +
             
     | 
| 
      
 122 
     | 
    
         
            +
                  def thread_process_iteration(client, manager, queue, block)
         
     | 
| 
      
 123 
     | 
    
         
            +
                    #get the queue
         
     | 
| 
      
 124 
     | 
    
         
            +
                    q = manager.get_queue(queue)
         
     | 
| 
      
 125 
     | 
    
         
            +
             
     | 
| 
      
 126 
     | 
    
         
            +
                    received = false
         
     | 
| 
      
 127 
     | 
    
         
            +
             
     | 
| 
      
 128 
     | 
    
         
            +
                    begin
         
     | 
| 
      
 129 
     | 
    
         
            +
             
     | 
| 
      
 130 
     | 
    
         
            +
                      #request a message from the queue
         
     | 
| 
      
 131 
     | 
    
         
            +
                      response = client.sqs.receive_message({
         
     | 
| 
      
 132 
     | 
    
         
            +
                                                                queue_url: q,
         
     | 
| 
      
 133 
     | 
    
         
            +
                                                                max_number_of_messages: 1,
         
     | 
| 
      
 134 
     | 
    
         
            +
                                                                wait_time_seconds: @queue_poll_wait,
         
     | 
| 
      
 135 
     | 
    
         
            +
                                                                attribute_names: [APPROXIMATE_RECEIVE_COUNT]
         
     | 
| 
      
 136 
     | 
    
         
            +
                                                            })
         
     | 
| 
      
 137 
     | 
    
         
            +
             
     | 
| 
      
 138 
     | 
    
         
            +
                      #check that a message was received
         
     | 
| 
      
 139 
     | 
    
         
            +
                      if response.messages.length > 0
         
     | 
| 
      
 140 
     | 
    
         
            +
                        received = true
         
     | 
| 
      
 141 
     | 
    
         
            +
                        begin
         
     | 
| 
      
 142 
     | 
    
         
            +
                          tag_processing_thread
         
     | 
| 
      
 143 
     | 
    
         
            +
                          process_message(response, client, queue, q, block)
         
     | 
| 
      
 144 
     | 
    
         
            +
                        ensure
         
     | 
| 
      
 145 
     | 
    
         
            +
                          untag_processing_thread
         
     | 
| 
      
 146 
     | 
    
         
            +
                        end
         
     | 
| 
      
 147 
     | 
    
         
            +
             
     | 
| 
      
 148 
     | 
    
         
            +
                      end
         
     | 
| 
      
 149 
     | 
    
         
            +
             
     | 
| 
      
 150 
     | 
    
         
            +
                    rescue => e
         
     | 
| 
      
 151 
     | 
    
         
            +
                      EventQ.log(:error, "[#{self.class}] - An unhandled error occurred. Error: #{e} | Backtrace: #{e.backtrace}")
         
     | 
| 
      
 152 
     | 
    
         
            +
                      call_on_error_block(error: e)
         
     | 
| 
      
 153 
     | 
    
         
            +
                    end
         
     | 
| 
      
 154 
     | 
    
         
            +
             
     | 
| 
      
 155 
     | 
    
         
            +
                    return received
         
     | 
| 
      
 156 
     | 
    
         
            +
                  end
         
     | 
| 
      
 157 
     | 
    
         
            +
             
     | 
| 
      
 158 
     | 
    
         
            +
                  def call_on_error_block(error:, message: nil)
         
     | 
| 
      
 159 
     | 
    
         
            +
                    if @on_error_block
         
     | 
| 
      
 160 
     | 
    
         
            +
                      EventQ.logger.debug { "[#{self.class}] - Executing on_error block." }
         
     | 
| 
      
 161 
     | 
    
         
            +
                      begin
         
     | 
| 
      
 162 
     | 
    
         
            +
                        @on_error_block.call(error, message)
         
     | 
| 
      
 163 
     | 
    
         
            +
                      rescue => e
         
     | 
| 
      
 164 
     | 
    
         
            +
                        EventQ.logger.error("[#{self.class}] - An error occurred executing the on_error block. Error: #{e}")
         
     | 
| 
      
 165 
     | 
    
         
            +
                      end
         
     | 
| 
      
 166 
     | 
    
         
            +
                    else
         
     | 
| 
      
 167 
     | 
    
         
            +
                      EventQ.logger.debug { "[#{self.class}] - No on_error block specified to execute." }
         
     | 
| 
      
 168 
     | 
    
         
            +
                    end
         
     | 
| 
      
 169 
     | 
    
         
            +
                  end
         
     | 
| 
      
 170 
     | 
    
         
            +
             
     | 
| 
      
 171 
     | 
    
         
            +
                  def call_on_retry_exceeded_block(message)
         
     | 
| 
      
 172 
     | 
    
         
            +
                    if @on_retry_exceeded_block != nil
         
     | 
| 
      
 173 
     | 
    
         
            +
                      EventQ.logger.debug { "[#{self.class}] - Executing on_retry_exceeded block." }
         
     | 
| 
      
 174 
     | 
    
         
            +
                      begin
         
     | 
| 
      
 175 
     | 
    
         
            +
                        @on_retry_exceeded_block.call(message)
         
     | 
| 
      
 176 
     | 
    
         
            +
                      rescue => e
         
     | 
| 
      
 177 
     | 
    
         
            +
                        EventQ.logger.error("[#{self.class}] - An error occurred executing the on_retry_exceeded block. Error: #{e}")
         
     | 
| 
      
 178 
     | 
    
         
            +
                      end
         
     | 
| 
      
 179 
     | 
    
         
            +
                    else
         
     | 
| 
      
 180 
     | 
    
         
            +
                      EventQ.logger.debug { "[#{self.class}] - No on_retry_exceeded block specified." }
         
     | 
| 
      
 181 
     | 
    
         
            +
                    end
         
     | 
| 
      
 182 
     | 
    
         
            +
                  end
         
     | 
| 
      
 183 
     | 
    
         
            +
             
     | 
| 
      
 184 
     | 
    
         
            +
                  def call_on_retry_block(message)
         
     | 
| 
      
 185 
     | 
    
         
            +
                    if @on_retry_block
         
     | 
| 
      
 186 
     | 
    
         
            +
                      EventQ.logger.debug { "[#{self.class}] - Executing on_retry block." }
         
     | 
| 
      
 187 
     | 
    
         
            +
                      begin
         
     | 
| 
      
 188 
     | 
    
         
            +
                        @on_retry_block.call(message, abort)
         
     | 
| 
      
 189 
     | 
    
         
            +
                      rescue => e
         
     | 
| 
      
 190 
     | 
    
         
            +
                        EventQ.logger.error("[#{self.class}] - An error occurred executing the on_retry block. Error: #{e}")
         
     | 
| 
      
 191 
     | 
    
         
            +
                      end
         
     | 
| 
      
 192 
     | 
    
         
            +
                    else
         
     | 
| 
      
 193 
     | 
    
         
            +
                      EventQ.logger.debug { "[#{self.class}] - No on_retry block specified." }
         
     | 
| 
      
 194 
     | 
    
         
            +
                    end
         
     | 
| 
      
 195 
     | 
    
         
            +
                  end
         
     | 
| 
      
 196 
     | 
    
         
            +
             
     | 
| 
      
 197 
     | 
    
         
            +
                  def stop
         
     | 
| 
      
 198 
     | 
    
         
            +
                    EventQ.logger.info("[#{self.class}] - Stopping.")
         
     | 
| 
      
 199 
     | 
    
         
            +
                    @is_running = false
         
     | 
| 
      
 200 
     | 
    
         
            +
                    @executor.shutdown
         
     | 
| 
      
 201 
     | 
    
         
            +
                    return true
         
     | 
| 
      
 202 
     | 
    
         
            +
                  end
         
     | 
| 
      
 203 
     | 
    
         
            +
             
     | 
| 
      
 204 
     | 
    
         
            +
                  def on_retry_exceeded(&block)
         
     | 
| 
      
 205 
     | 
    
         
            +
                    @retry_exceeded_block = block
         
     | 
| 
      
 206 
     | 
    
         
            +
                  end
         
     | 
| 
      
 207 
     | 
    
         
            +
             
     | 
| 
      
 208 
     | 
    
         
            +
                  def on_retry(&block)
         
     | 
| 
      
 209 
     | 
    
         
            +
                    @on_retry_block = block
         
     | 
| 
      
 210 
     | 
    
         
            +
                    return nil
         
     | 
| 
      
 211 
     | 
    
         
            +
                  end
         
     | 
| 
      
 212 
     | 
    
         
            +
             
     | 
| 
      
 213 
     | 
    
         
            +
                  def on_error(&block)
         
     | 
| 
      
 214 
     | 
    
         
            +
                    @on_error_block = block
         
     | 
| 
      
 215 
     | 
    
         
            +
                    return nil
         
     | 
| 
      
 216 
     | 
    
         
            +
                  end
         
     | 
| 
      
 217 
     | 
    
         
            +
             
     | 
| 
      
 218 
     | 
    
         
            +
                  def running?
         
     | 
| 
      
 219 
     | 
    
         
            +
                    return @is_running
         
     | 
| 
      
 220 
     | 
    
         
            +
                  end
         
     | 
| 
      
 221 
     | 
    
         
            +
             
     | 
| 
      
 222 
     | 
    
         
            +
                  def deserialize_message(payload)
         
     | 
| 
      
 223 
     | 
    
         
            +
                    provider = @serialization_provider_manager.get_provider(EventQ::Configuration.serialization_provider)
         
     | 
| 
      
 224 
     | 
    
         
            +
                    return provider.deserialize(payload)
         
     | 
| 
      
 225 
     | 
    
         
            +
                  end
         
     | 
| 
      
 226 
     | 
    
         
            +
             
     | 
| 
      
 227 
     | 
    
         
            +
                  def serialize_message(msg)
         
     | 
| 
      
 228 
     | 
    
         
            +
                    provider = @serialization_provider_manager.get_provider(EventQ::Configuration.serialization_provider)
         
     | 
| 
      
 229 
     | 
    
         
            +
                    return provider.serialize(msg)
         
     | 
| 
      
 230 
     | 
    
         
            +
                  end
         
     | 
| 
      
 231 
     | 
    
         
            +
             
     | 
| 
      
 232 
     | 
    
         
            +
                  private
         
     | 
| 
      
 233 
     | 
    
         
            +
             
     | 
| 
      
 234 
     | 
    
         
            +
                  def process_message(response, client, queue, q, block)
         
     | 
| 
      
 235 
     | 
    
         
            +
                    msg = response.messages[0]
         
     | 
| 
      
 236 
     | 
    
         
            +
                    retry_attempts = msg.attributes[APPROXIMATE_RECEIVE_COUNT].to_i - 1
         
     | 
| 
      
 237 
     | 
    
         
            +
             
     | 
| 
      
 238 
     | 
    
         
            +
                    #deserialize the message payload
         
     | 
| 
      
 239 
     | 
    
         
            +
                    payload = JSON.load(msg.body)
         
     | 
| 
      
 240 
     | 
    
         
            +
                    message = deserialize_message(payload[MESSAGE])
         
     | 
| 
      
 241 
     | 
    
         
            +
             
     | 
| 
      
 242 
     | 
    
         
            +
                    message_args = EventQ::MessageArgs.new(type: message.type,
         
     | 
| 
      
 243 
     | 
    
         
            +
                                                           retry_attempts: retry_attempts,
         
     | 
| 
      
 244 
     | 
    
         
            +
                                                           context: message.context,
         
     | 
| 
      
 245 
     | 
    
         
            +
                                                           content_type: message.content_type)
         
     | 
| 
      
 246 
     | 
    
         
            +
             
     | 
| 
      
 247 
     | 
    
         
            +
                    EventQ.logger.info("[#{self.class}] - Message received. Retry Attempts: #{retry_attempts}")
         
     | 
| 
      
 248 
     | 
    
         
            +
             
     | 
| 
      
 249 
     | 
    
         
            +
                    @signature_provider_manager.validate_signature(message: message, queue: queue)
         
     | 
| 
      
 250 
     | 
    
         
            +
             
     | 
| 
      
 251 
     | 
    
         
            +
                    if(!EventQ::NonceManager.is_allowed?(message.id))
         
     | 
| 
      
 252 
     | 
    
         
            +
                      EventQ.logger.info("[#{self.class}] - Duplicate Message received. Dropping message.")
         
     | 
| 
      
 253 
     | 
    
         
            +
                      client.sqs.delete_message({ queue_url: q, receipt_handle: msg.receipt_handle })
         
     | 
| 
      
 254 
     | 
    
         
            +
                      return false
         
     | 
| 
      
 255 
     | 
    
         
            +
                    end
         
     | 
| 
      
 256 
     | 
    
         
            +
             
     | 
| 
      
 257 
     | 
    
         
            +
                    #begin worker block for queue message
         
     | 
| 
      
 258 
     | 
    
         
            +
                    begin
         
     | 
| 
      
 259 
     | 
    
         
            +
             
     | 
| 
      
 260 
     | 
    
         
            +
                      block.call(message.content, message_args)
         
     | 
| 
      
 261 
     | 
    
         
            +
             
     | 
| 
      
 262 
     | 
    
         
            +
                      if message_args.abort == true
         
     | 
| 
      
 263 
     | 
    
         
            +
                        EventQ.logger.info("[#{self.class}] - Message aborted.")
         
     | 
| 
      
 264 
     | 
    
         
            +
                      else
         
     | 
| 
      
 265 
     | 
    
         
            +
                        #accept the message as processed
         
     | 
| 
      
 266 
     | 
    
         
            +
                        client.sqs.delete_message({ queue_url: q, receipt_handle: msg.receipt_handle })
         
     | 
| 
      
 267 
     | 
    
         
            +
                        EventQ.logger.info("[#{self.class}] - Message acknowledged.")
         
     | 
| 
      
 268 
     | 
    
         
            +
                      end
         
     | 
| 
      
 269 
     | 
    
         
            +
             
     | 
| 
      
 270 
     | 
    
         
            +
                    rescue => e
         
     | 
| 
      
 271 
     | 
    
         
            +
                      EventQ.logger.error("[#{self.class}] - An unhandled error happened while attempting to process a queue message. Error: #{e} | Backtrace: #{e.backtrace}")
         
     | 
| 
      
 272 
     | 
    
         
            +
                      error = true
         
     | 
| 
      
 273 
     | 
    
         
            +
                      call_on_error_block(error: e, message: message)
         
     | 
| 
      
 274 
     | 
    
         
            +
                    end
         
     | 
| 
      
 275 
     | 
    
         
            +
             
     | 
| 
      
 276 
     | 
    
         
            +
                    if message_args.abort || error
         
     | 
| 
      
 277 
     | 
    
         
            +
                      EventQ::NonceManager.failed(message.id)
         
     | 
| 
      
 278 
     | 
    
         
            +
                      reject_message(queue, client, msg, q, retry_attempts, message, message_args.abort)
         
     | 
| 
      
 279 
     | 
    
         
            +
                    else
         
     | 
| 
      
 280 
     | 
    
         
            +
                      EventQ::NonceManager.complete(message.id)
         
     | 
| 
      
 281 
     | 
    
         
            +
                    end
         
     | 
| 
      
 282 
     | 
    
         
            +
             
     | 
| 
      
 283 
     | 
    
         
            +
                    return true
         
     | 
| 
      
 284 
     | 
    
         
            +
                  end
         
     | 
| 
      
 285 
     | 
    
         
            +
             
     | 
| 
      
 286 
     | 
    
         
            +
                  def reject_message(queue, client, msg, q, retry_attempts, message, abort)
         
     | 
| 
      
 287 
     | 
    
         
            +
             
     | 
| 
      
 288 
     | 
    
         
            +
                    if !queue.allow_retry || retry_attempts >= queue.max_retry_attempts
         
     | 
| 
      
 289 
     | 
    
         
            +
             
     | 
| 
      
 290 
     | 
    
         
            +
                      EventQ.logger.info("[#{self.class}] - Message rejected removing from queue. Message: #{serialize_message(message)}")
         
     | 
| 
      
 291 
     | 
    
         
            +
             
     | 
| 
      
 292 
     | 
    
         
            +
                      #remove the message from the queue so that it does not get retried again
         
     | 
| 
      
 293 
     | 
    
         
            +
                      client.sqs.delete_message({ queue_url: q, receipt_handle: msg.receipt_handle })
         
     | 
| 
      
 294 
     | 
    
         
            +
             
     | 
| 
      
 295 
     | 
    
         
            +
                      if retry_attempts >= queue.max_retry_attempts
         
     | 
| 
      
 296 
     | 
    
         
            +
             
     | 
| 
      
 297 
     | 
    
         
            +
                        EventQ.logger.info("[#{self.class}] - Message retry attempt limit exceeded.")
         
     | 
| 
      
 298 
     | 
    
         
            +
                        call_on_retry_exceeded_block(message)
         
     | 
| 
      
 299 
     | 
    
         
            +
             
     | 
| 
      
 300 
     | 
    
         
            +
                      end
         
     | 
| 
      
 301 
     | 
    
         
            +
             
     | 
| 
      
 302 
     | 
    
         
            +
                    elsif queue.allow_retry
         
     | 
| 
      
 303 
     | 
    
         
            +
             
     | 
| 
      
 304 
     | 
    
         
            +
                      retry_attempts += 1
         
     | 
| 
      
 305 
     | 
    
         
            +
             
     | 
| 
      
 306 
     | 
    
         
            +
                      EventQ.logger.info("[#{self.class}] - Message rejected requesting retry. Attempts: #{retry_attempts}")
         
     | 
| 
      
 307 
     | 
    
         
            +
             
     | 
| 
      
 308 
     | 
    
         
            +
                      if queue.allow_retry_back_off == true
         
     | 
| 
      
 309 
     | 
    
         
            +
                        EventQ.logger.debug { "[#{self.class}] - Calculating message back off retry delay. Attempts: #{retry_attempts} * Delay: #{queue.retry_delay}" }
         
     | 
| 
      
 310 
     | 
    
         
            +
                        visibility_timeout = (queue.retry_delay * retry_attempts) / 1000
         
     | 
| 
      
 311 
     | 
    
         
            +
                        if visibility_timeout > (queue.max_retry_delay / 1000)
         
     | 
| 
      
 312 
     | 
    
         
            +
                          EventQ.logger.debug { "[#{self.class}] - Max message back off retry delay reached." }
         
     | 
| 
      
 313 
     | 
    
         
            +
                          visibility_timeout = queue.max_retry_delay / 1000
         
     | 
| 
      
 314 
     | 
    
         
            +
                        end
         
     | 
| 
      
 315 
     | 
    
         
            +
                      else
         
     | 
| 
      
 316 
     | 
    
         
            +
                        EventQ.logger.debug { "[#{self.class}] - Setting fixed retry delay for message." }
         
     | 
| 
      
 317 
     | 
    
         
            +
                        visibility_timeout = queue.retry_delay / 1000
         
     | 
| 
      
 318 
     | 
    
         
            +
                      end
         
     | 
| 
      
 319 
     | 
    
         
            +
             
     | 
| 
      
 320 
     | 
    
         
            +
                      if visibility_timeout > 43200
         
     | 
| 
      
 321 
     | 
    
         
            +
                        EventQ.logger.debug { "[#{self.class}] - AWS max visibility timeout of 12 hours has been exceeded. Setting message retry delay to 12 hours." }
         
     | 
| 
      
 322 
     | 
    
         
            +
                        visibility_timeout = 43200
         
     | 
| 
      
 323 
     | 
    
         
            +
                      end
         
     | 
| 
      
 324 
     | 
    
         
            +
             
     | 
| 
      
 325 
     | 
    
         
            +
                      EventQ.logger.debug { "[#{self.class}] - Sending message for retry. Message TTL: #{visibility_timeout}" }
         
     | 
| 
      
 326 
     | 
    
         
            +
                      client.sqs.change_message_visibility({
         
     | 
| 
      
 327 
     | 
    
         
            +
                                                           queue_url: q, # required
         
     | 
| 
      
 328 
     | 
    
         
            +
                                                           receipt_handle: msg.receipt_handle, # required
         
     | 
| 
      
 329 
     | 
    
         
            +
                                                           visibility_timeout: visibility_timeout.to_s, # required
         
     | 
| 
      
 330 
     | 
    
         
            +
                                                       })
         
     | 
| 
      
 331 
     | 
    
         
            +
             
     | 
| 
      
 332 
     | 
    
         
            +
                      call_on_retry_block(message)
         
     | 
| 
      
 333 
     | 
    
         
            +
             
     | 
| 
      
 334 
     | 
    
         
            +
                    end
         
     | 
| 
      
 335 
     | 
    
         
            +
             
     | 
| 
      
 336 
     | 
    
         
            +
                  end
         
     | 
| 
      
 337 
     | 
    
         
            +
             
     | 
| 
      
 338 
     | 
    
         
            +
                  def configure(queue, options = {})
         
     | 
| 
      
 339 
     | 
    
         
            +
             
     | 
| 
      
 340 
     | 
    
         
            +
                    @queue = queue
         
     | 
| 
      
 341 
     | 
    
         
            +
             
     | 
| 
      
 342 
     | 
    
         
            +
                    #default thread count
         
     | 
| 
      
 343 
     | 
    
         
            +
                    @thread_count = 5
         
     | 
| 
      
 344 
     | 
    
         
            +
                    if options.key?(:thread_count)
         
     | 
| 
      
 345 
     | 
    
         
            +
                      @thread_count = options[:thread_count]
         
     | 
| 
      
 346 
     | 
    
         
            +
                    end
         
     | 
| 
      
 347 
     | 
    
         
            +
             
     | 
| 
      
 348 
     | 
    
         
            +
                    #default sleep time in seconds
         
     | 
| 
      
 349 
     | 
    
         
            +
                    @sleep = 5
         
     | 
| 
      
 350 
     | 
    
         
            +
                    if options.key?(:sleep)
         
     | 
| 
      
 351 
     | 
    
         
            +
                      @sleep = options[:sleep]
         
     | 
| 
      
 352 
     | 
    
         
            +
                    end
         
     | 
| 
      
 353 
     | 
    
         
            +
             
     | 
| 
      
 354 
     | 
    
         
            +
                    if options.key?(:gc_flush_interval)
         
     | 
| 
      
 355 
     | 
    
         
            +
                      @gc_flush_interval = options[:gc_flush_interval]
         
     | 
| 
      
 356 
     | 
    
         
            +
                    end
         
     | 
| 
      
 357 
     | 
    
         
            +
             
     | 
| 
      
 358 
     | 
    
         
            +
                    if options.key?(:queue_poll_wait)
         
     | 
| 
      
 359 
     | 
    
         
            +
                      @queue_poll_wait = options[:queue_poll_wait]
         
     | 
| 
      
 360 
     | 
    
         
            +
                    end
         
     | 
| 
      
 361 
     | 
    
         
            +
             
     | 
| 
      
 362 
     | 
    
         
            +
                    EventQ.logger.info("[#{self.class}] - Configuring. Thread Count: #{@thread_count} | Interval Sleep: #{@sleep} | GC Flush Interval: #{@gc_flush_interval} | Queue Poll Wait: #{@queue_poll_wait}.")
         
     | 
| 
      
 363 
     | 
    
         
            +
             
     | 
| 
      
 364 
     | 
    
         
            +
                    return true
         
     | 
| 
      
 365 
     | 
    
         
            +
             
     | 
| 
      
 366 
     | 
    
         
            +
                  end
         
     | 
| 
      
 367 
     | 
    
         
            +
             
     | 
| 
      
 368 
     | 
    
         
            +
                end
         
     | 
| 
      
 369 
     | 
    
         
            +
              end
         
     | 
| 
      
 370 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/eventq_aws.rb
    ADDED
    
    | 
         @@ -0,0 +1,37 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'aws-sdk-core'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'eventq_base'
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            require 'eventq_aws/version'
         
     | 
| 
      
 5 
     | 
    
         
            +
            require 'eventq_aws/aws_eventq_client'
         
     | 
| 
      
 6 
     | 
    
         
            +
            require 'eventq_aws/aws_queue_client'
         
     | 
| 
      
 7 
     | 
    
         
            +
            require 'eventq_aws/aws_queue_manager'
         
     | 
| 
      
 8 
     | 
    
         
            +
            require 'eventq_aws/aws_subscription_manager'
         
     | 
| 
      
 9 
     | 
    
         
            +
            require_relative 'eventq_aws/aws_status_checker'
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
            if RUBY_PLATFORM =~ /java/
         
     | 
| 
      
 12 
     | 
    
         
            +
              require 'eventq_aws/jruby/aws_queue_worker'
         
     | 
| 
      
 13 
     | 
    
         
            +
            else
         
     | 
| 
      
 14 
     | 
    
         
            +
              require 'eventq_aws/aws_queue_worker'
         
     | 
| 
      
 15 
     | 
    
         
            +
            end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
            module EventQ
         
     | 
| 
      
 18 
     | 
    
         
            +
              def self.namespace
         
     | 
| 
      
 19 
     | 
    
         
            +
                @namespace
         
     | 
| 
      
 20 
     | 
    
         
            +
              end
         
     | 
| 
      
 21 
     | 
    
         
            +
              def self.namespace=(value)
         
     | 
| 
      
 22 
     | 
    
         
            +
                @namespace = value
         
     | 
| 
      
 23 
     | 
    
         
            +
              end
         
     | 
| 
      
 24 
     | 
    
         
            +
              def self.create_event_type(event_type)
         
     | 
| 
      
 25 
     | 
    
         
            +
                if EventQ.namespace == nil
         
     | 
| 
      
 26 
     | 
    
         
            +
                  return event_type
         
     | 
| 
      
 27 
     | 
    
         
            +
                end
         
     | 
| 
      
 28 
     | 
    
         
            +
                return "#{EventQ.namespace}-#{event_type}"
         
     | 
| 
      
 29 
     | 
    
         
            +
              end
         
     | 
| 
      
 30 
     | 
    
         
            +
              def self.create_queue_name(queue_name)
         
     | 
| 
      
 31 
     | 
    
         
            +
                if EventQ.namespace == nil
         
     | 
| 
      
 32 
     | 
    
         
            +
                  return queue_name
         
     | 
| 
      
 33 
     | 
    
         
            +
                end
         
     | 
| 
      
 34 
     | 
    
         
            +
                return "#{EventQ.namespace}-#{queue_name}"
         
     | 
| 
      
 35 
     | 
    
         
            +
              end
         
     | 
| 
      
 36 
     | 
    
         
            +
            end
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
    
        metadata
    ADDED
    
    | 
         @@ -0,0 +1,125 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            --- !ruby/object:Gem::Specification
         
     | 
| 
      
 2 
     | 
    
         
            +
            name: eventq_aws
         
     | 
| 
      
 3 
     | 
    
         
            +
            version: !ruby/object:Gem::Version
         
     | 
| 
      
 4 
     | 
    
         
            +
              version: 1.14.0
         
     | 
| 
      
 5 
     | 
    
         
            +
            platform: java
         
     | 
| 
      
 6 
     | 
    
         
            +
            authors:
         
     | 
| 
      
 7 
     | 
    
         
            +
            - vaughanbrittonsage
         
     | 
| 
      
 8 
     | 
    
         
            +
            autorequire:
         
     | 
| 
      
 9 
     | 
    
         
            +
            bindir: exe
         
     | 
| 
      
 10 
     | 
    
         
            +
            cert_chain: []
         
     | 
| 
      
 11 
     | 
    
         
            +
            date: 2017-06-27 00:00:00.000000000 Z
         
     | 
| 
      
 12 
     | 
    
         
            +
            dependencies:
         
     | 
| 
      
 13 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 14 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 15 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 16 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 17 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 18 
     | 
    
         
            +
                    version: '1.11'
         
     | 
| 
      
 19 
     | 
    
         
            +
              name: bundler
         
     | 
| 
      
 20 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 21 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 22 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 23 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 24 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 25 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 26 
     | 
    
         
            +
                    version: '1.11'
         
     | 
| 
      
 27 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 28 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 29 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 30 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 31 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 32 
     | 
    
         
            +
                    version: '10.0'
         
     | 
| 
      
 33 
     | 
    
         
            +
              name: rake
         
     | 
| 
      
 34 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 35 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 36 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 37 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 38 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 39 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 40 
     | 
    
         
            +
                    version: '10.0'
         
     | 
| 
      
 41 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 42 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 43 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 44 
     | 
    
         
            +
                - - ">="
         
     | 
| 
      
 45 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 46 
     | 
    
         
            +
                    version: '0'
         
     | 
| 
      
 47 
     | 
    
         
            +
              name: rspec
         
     | 
| 
      
 48 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 49 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 50 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 51 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 52 
     | 
    
         
            +
                - - ">="
         
     | 
| 
      
 53 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 54 
     | 
    
         
            +
                    version: '0'
         
     | 
| 
      
 55 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 56 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 57 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 58 
     | 
    
         
            +
                - - ">="
         
     | 
| 
      
 59 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 60 
     | 
    
         
            +
                    version: '0'
         
     | 
| 
      
 61 
     | 
    
         
            +
              name: aws-sdk-core
         
     | 
| 
      
 62 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 63 
     | 
    
         
            +
              type: :runtime
         
     | 
| 
      
 64 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 65 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 66 
     | 
    
         
            +
                - - ">="
         
     | 
| 
      
 67 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 68 
     | 
    
         
            +
                    version: '0'
         
     | 
| 
      
 69 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 70 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 71 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 72 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 73 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 74 
     | 
    
         
            +
                    version: '1.15'
         
     | 
| 
      
 75 
     | 
    
         
            +
              name: eventq_base
         
     | 
| 
      
 76 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 77 
     | 
    
         
            +
              type: :runtime
         
     | 
| 
      
 78 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 79 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 80 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 81 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 82 
     | 
    
         
            +
                    version: '1.15'
         
     | 
| 
      
 83 
     | 
    
         
            +
            description: This is the aws implementation for EventQ
         
     | 
| 
      
 84 
     | 
    
         
            +
            email:
         
     | 
| 
      
 85 
     | 
    
         
            +
            - vaughanbritton@gmail.com
         
     | 
| 
      
 86 
     | 
    
         
            +
            executables: []
         
     | 
| 
      
 87 
     | 
    
         
            +
            extensions: []
         
     | 
| 
      
 88 
     | 
    
         
            +
            extra_rdoc_files: []
         
     | 
| 
      
 89 
     | 
    
         
            +
            files:
         
     | 
| 
      
 90 
     | 
    
         
            +
            - bin/console
         
     | 
| 
      
 91 
     | 
    
         
            +
            - bin/setup
         
     | 
| 
      
 92 
     | 
    
         
            +
            - lib/eventq_aws.rb
         
     | 
| 
      
 93 
     | 
    
         
            +
            - lib/eventq_aws/aws_eventq_client.rb
         
     | 
| 
      
 94 
     | 
    
         
            +
            - lib/eventq_aws/aws_queue_client.rb
         
     | 
| 
      
 95 
     | 
    
         
            +
            - lib/eventq_aws/aws_queue_manager.rb
         
     | 
| 
      
 96 
     | 
    
         
            +
            - lib/eventq_aws/aws_queue_worker.rb
         
     | 
| 
      
 97 
     | 
    
         
            +
            - lib/eventq_aws/aws_status_checker.rb
         
     | 
| 
      
 98 
     | 
    
         
            +
            - lib/eventq_aws/aws_subscription_manager.rb
         
     | 
| 
      
 99 
     | 
    
         
            +
            - lib/eventq_aws/jruby/aws_queue_worker.rb
         
     | 
| 
      
 100 
     | 
    
         
            +
            - lib/eventq_aws/version.rb
         
     | 
| 
      
 101 
     | 
    
         
            +
            homepage: https://github.com/vaughanbrittonsage/eventq
         
     | 
| 
      
 102 
     | 
    
         
            +
            licenses:
         
     | 
| 
      
 103 
     | 
    
         
            +
            - MIT
         
     | 
| 
      
 104 
     | 
    
         
            +
            metadata: {}
         
     | 
| 
      
 105 
     | 
    
         
            +
            post_install_message:
         
     | 
| 
      
 106 
     | 
    
         
            +
            rdoc_options: []
         
     | 
| 
      
 107 
     | 
    
         
            +
            require_paths:
         
     | 
| 
      
 108 
     | 
    
         
            +
            - lib
         
     | 
| 
      
 109 
     | 
    
         
            +
            required_ruby_version: !ruby/object:Gem::Requirement
         
     | 
| 
      
 110 
     | 
    
         
            +
              requirements:
         
     | 
| 
      
 111 
     | 
    
         
            +
              - - ">="
         
     | 
| 
      
 112 
     | 
    
         
            +
                - !ruby/object:Gem::Version
         
     | 
| 
      
 113 
     | 
    
         
            +
                  version: '0'
         
     | 
| 
      
 114 
     | 
    
         
            +
            required_rubygems_version: !ruby/object:Gem::Requirement
         
     | 
| 
      
 115 
     | 
    
         
            +
              requirements:
         
     | 
| 
      
 116 
     | 
    
         
            +
              - - ">="
         
     | 
| 
      
 117 
     | 
    
         
            +
                - !ruby/object:Gem::Version
         
     | 
| 
      
 118 
     | 
    
         
            +
                  version: '0'
         
     | 
| 
      
 119 
     | 
    
         
            +
            requirements: []
         
     | 
| 
      
 120 
     | 
    
         
            +
            rubyforge_project:
         
     | 
| 
      
 121 
     | 
    
         
            +
            rubygems_version: 2.6.11
         
     | 
| 
      
 122 
     | 
    
         
            +
            signing_key:
         
     | 
| 
      
 123 
     | 
    
         
            +
            specification_version: 4
         
     | 
| 
      
 124 
     | 
    
         
            +
            summary: This is the aws implementation for EventQ
         
     | 
| 
      
 125 
     | 
    
         
            +
            test_files: []
         
     |