# Copyright (c) 2021 Contrast Security, Inc. See https://www.contrastsecurity.com/enduser-terms-0317a for more details. # frozen_string_literal: true require 'contrast/components/interface' require 'contrast/agent/worker_thread' module Contrast module Api module Communication # Top level gateway to messaging with speedracer class MessagingQueue < Contrast::Agent::WorkerThread include Contrast::Components::Interface access_component :agent, :analysis, :logging, :settings attr_reader :queue, :speedracer def initialize @queue = Queue.new @speedracer = Contrast::Api::Communication::Speedracer.new super end # Use this to bypass the messaging queue and leave response processing to the caller def send_event_immediately event if AGENT.disabled? logger.warn('Attempted to send event immediately with Agent disabled', caller: caller, event: event) return end speedracer.return_response(event) end # Use this to add a message to the queue and process the response internally def send_event_eventually event if AGENT.disabled? logger.warn('Attempted to queue event with Agent disabled', caller: caller, event: event) return end logger.debug('Enqueued event for sending', event_type: event.cs__class) queue << event if event end def start_thread! speedracer.ensure_startup! return if running? @queue ||= Queue.new @_thread = Contrast::Agent::Thread.new do loop do event = queue.pop begin logger.debug('Dequeued event for sending', event_type: event.cs__class) speedracer.process_internally(event) rescue StandardError => e logger.error('Could not send message to service from messaging queue thread.', e) end end end logger.debug('Started background sending thread.') end def stop! return unless running? super @queue&.clear @queue&.close @queue = nil end end end end end