# frozen_string_literal: true require 'json' require 'tacview_client' require_relative 'datastore' require_relative 'event_queue' require_relative 'event_processor' module TacScribe # Main entry-point into Tac Scribe. Instantiate this class to start # processing events. class Daemon def initialize(db_host:, db_port:, db_name:, db_user:, db_password:, tacview_host:, tacview_port:, tacview_password:, tacview_client_name:, verbose_logging:, thread_count:, populate_airfields:) Datastore.instance.configure do |config| config.host = db_host config.port = db_port config.database = db_name config.username = db_user config.password = db_password end Datastore.instance.connect @event_queue = EventQueue.new verbose_logging: verbose_logging @populate_airfields = populate_airfields @thread_count = thread_count @processing_threads = [] @client = TacviewClient::Client.new( host: tacview_host, port: tacview_port, password: tacview_password, processor: @event_queue, client_name: tacview_client_name ) end # Starts processing and reconnects if the client was disconnected. # Because connecting to Tacview always gives an initial unit dump # we truncate the table each time we reconnect. This will make sure # there are no ghost units hanging around after server restart # for example def start_processing loop do kill_processing_threads @event_queue.events.clear Datastore.instance.truncate_table start_processing_threads populate_airfields if @populate_airfields @client.connect sleep 30 # Rescuing reliably from Net::HTTP is a complete bear so rescue # StandardError. It ain't pretty but it is reliable. We will puts # the exception just in case # https://stackoverflow.com/questions/5370697/what-s-the-best-way-to-handle-exceptions-from-nethttp rescue StandardError => e puts e.message puts e.backtrace next end end def kill_processing_threads @processing_threads.each do |thr| thr.kill thr.join end end def start_processing_threads @thread_count.times do @processing_threads << Thread.new do EventProcessor.new(datastore: Datastore.instance, event_queue: @event_queue).start end end end def populate_airfields json = File.read(File.join(File.dirname(__FILE__), '../../data/airfields.json')) airfields = JSON.parse(json) airfields.each_with_index do |airfield, i| @event_queue.update_object({ object_id: (45_000_000 + i).to_s, latitude: BigDecimal(airfield['lat'].to_s), longitude: BigDecimal(airfield['lon'].to_s), altitude: BigDecimal(airfield['alt'].to_s), type: 'Ground+Static+Aerodrome', name: airfield['name'], coalition: 2 }) end end end end