# Path: il2fb/ds/airbridge/typing.py

# 
# Path: il2fb/ds/airbridge/typing.py



import logging
import threading
from typing import Callable
from il2fb.commons.events import Event, EventParsingException
from il2fb.commons.structures import BaseStructure
from il2fb.ds.airbridge.typing import EventHandler
from il2fb.ds.airbridge.typing import StringOrNoneProducer, StringHandler
            LOG.error("game log worker has terminated")
            raise
        else:
            LOG.info("game log worker has finished")

    def _run(self) -> None:
        while True:
            try:
                string = self._string_producer()
            except Exception:
                LOG.exception("failed to get game log string")
                continue

            if string is None:
                break

            try:
                event = self._string_parser(string)
                if event is not None:
                    self._handle_event(event)
            except EventParsingException:
                self._handle_not_parsed_string(string)
            except Exception:
                LOG.exception(f"failed to parse game log string (s={string})")

    def _handle_event(self, event: Event) -> None:
        with self._events_subscribers_lock:
            for subscriber in self._events_subscribers:
                try:
                    subscriber(event)

# Path: il2fb/ds/airbridge/typing.py

# 
# Path: il2fb/ds/airbridge/typing.py



# Path: il2fb/ds/airbridge/dedicated_server/game_log.py
import logging
import threading
from typing import Callable
from il2fb.commons.events import Event, EventParsingException
from il2fb.commons.structures import BaseStructure
from il2fb.ds.airbridge.typing import EventHandler
from il2fb.ds.airbridge.typing import StringOrNoneProducer, StringHandler

            LOG.error("game log worker has terminated")
            raise
        else:
            LOG.info("game log worker has finished")

    def _run(self) -> None:
        while True:
            try:
                string = self._string_producer()
            except Exception:
                LOG.exception("failed to get game log string")
                continue

            if string is None:
                break

            try:
                event = self._string_parser(string)
                if event is not None:
                    self._handle_event(event)
            except EventParsingException:
                self._handle_not_parsed_string(string)
            except Exception:
                LOG.exception(f"failed to parse game log string (s={string})")

    def _handle_event(self, event: Event) -> None:
        with self._events_subscribers_lock:
            for subscriber in self._events_subscribers:
                try:
                    subscriber(event)

                except Exception: