1
0
mirror of https://github.com/EDCD/EDMarketConnector.git synced 2025-04-17 17:42:20 +03:00

Convert monitor.event_queue to a queue.Queue.

* We now use event_queue.empty() to see if it is indeed empty.
* Changed AppWindow.journal_event() to also use .empty() rather than
  `while True`.  Keeping the `'if not entry'` check just in case.
  This prevents it from calling monitor.get_entry() when the prior run
  through the loop has just emptied the queue.  Thus we'll only log when
  it genuinely IS unexpectedly empty.
* During *game* Shutdown we can send the synthetic 'Shutdown' event
  through, and then find and append the actual game 'Shutdown' event
  (i.e. this wasn't a crash, which is what the synthetic event is meant
  to react to).  But AppWindow.journal_event() loop picks up both events
  in one call, so the second <<JournalEvent>> sends it working on an
  empty queue.
  Thus we log in monitor.get_entry() only if the queue is empty *and*
  the game is still running.
* NB: Also adds 'Component' to the OTHER place montitor.state is
  initialised.
This commit is contained in:
Athanasius 2021-04-02 12:19:40 +01:00
parent 672c0d3d49
commit 3933dea479
2 changed files with 55 additions and 49 deletions

View File

@ -891,7 +891,7 @@ class AppWindow(object):
logger.debug('monitor.thread is None, assuming shutdown and returning') logger.debug('monitor.thread is None, assuming shutdown and returning')
return return
while True: while not monitor.event_queue.empty():
entry = monitor.get_entry() entry = monitor.get_entry()
if not entry: if not entry:
# This is expected due to some monitor.py code that appends `None` # This is expected due to some monitor.py code that appends `None`

View File

@ -1,6 +1,7 @@
"""Monitor for new Journal files and contents of latest.""" """Monitor for new Journal files and contents of latest."""
import json import json
import queue
import re import re
import threading import threading
from calendar import timegm from calendar import timegm
@ -78,7 +79,8 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below
self.observer: Optional['Observer'] = None self.observer: Optional['Observer'] = None
self.observed = None # a watchdog ObservedWatch, or None if polling self.observed = None # a watchdog ObservedWatch, or None if polling
self.thread: Optional[threading.Thread] = None self.thread: Optional[threading.Thread] = None
self.event_queue: List = [] # For communicating journal entries back to main thread # For communicating journal entries back to main thread
self.event_queue: queue.Queue = queue.Queue(maxsize=0)
# On startup we might be: # On startup we might be:
# 1) Looking at an old journal file because the game isn't running or the user has exited to the main menu. # 1) Looking at an old journal file because the game isn't running or the user has exited to the main menu.
@ -342,11 +344,11 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below
entry['StationType'] = self.stationtype entry['StationType'] = self.stationtype
entry['MarketID'] = self.station_marketid entry['MarketID'] = self.station_marketid
self.event_queue.append(json.dumps(entry, separators=(', ', ':'))) self.event_queue.put(json.dumps(entry, separators=(', ', ':')))
else: else:
# Generate null event to update the display (with possibly out-of-date info) # Generate null event to update the display (with possibly out-of-date info)
self.event_queue.append(None) self.event_queue.put(None)
self.live = False self.live = False
# Watchdog thread -- there is a way to get this by using self.observer.emitters and checking for an attribute: # Watchdog thread -- there is a way to get this by using self.observer.emitters and checking for an attribute:
@ -396,12 +398,13 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below
return # Terminate return # Terminate
if b'"event":"Location"' in line: if b'"event":"Location"' in line:
logger.trace('Found "Location" event, appending to event_queue') logger.trace('Found "Location" event, adding to event_queue')
self.event_queue.append(line) self.event_queue.put(line)
if self.event_queue: if not self.event_queue.empty():
if not config.shutting_down: if not config.shutting_down:
# logger.trace('Sending <<JournalEvent>>')
self.root.event_generate('<<JournalEvent>>', when="tail") self.root.event_generate('<<JournalEvent>>', when="tail")
log_pos = loghandle.tell() log_pos = loghandle.tell()
@ -420,11 +423,12 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below
if not self.game_running(): if not self.game_running():
logger.info('Detected exit from game, synthesising ShutDown event') logger.info('Detected exit from game, synthesising ShutDown event')
timestamp = strftime('%Y-%m-%dT%H:%M:%SZ', gmtime()) timestamp = strftime('%Y-%m-%dT%H:%M:%SZ', gmtime())
self.event_queue.append( self.event_queue.put(
f'{{ "timestamp":"{timestamp}", "event":"ShutDown" }}' f'{{ "timestamp":"{timestamp}", "event":"ShutDown" }}'
) )
if not config.shutting_down: if not config.shutting_down:
# logger.trace('Sending <<JournalEvent>>')
self.root.event_generate('<<JournalEvent>>', when="tail") self.root.event_generate('<<JournalEvent>>', when="tail")
self.game_was_running = False self.game_was_running = False
@ -482,6 +486,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below
'Raw': defaultdict(int), 'Raw': defaultdict(int),
'Manufactured': defaultdict(int), 'Manufactured': defaultdict(int),
'Encoded': defaultdict(int), 'Encoded': defaultdict(int),
'Component': defaultdict(int),
'Engineers': {}, 'Engineers': {},
'Rank': {}, 'Rank': {},
'Reputation': {}, 'Reputation': {},
@ -975,54 +980,55 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below
logger.debug('Called whilst self.thread is None, returning') logger.debug('Called whilst self.thread is None, returning')
return None return None
if not self.event_queue: # logger.trace('Begin')
logger.trace('Called with no event_queue') if self.event_queue.empty() and self.game_running():
logger.error('event_queue is empty whilst game_running, this should not happen, returning')
return None return None
else: # logger.trace('event_queue NOT empty')
entry = self.parse_entry(self.event_queue.pop(0)) entry = self.parse_entry(self.event_queue.get_nowait())
if entry['event'] == 'Location':
logger.trace('"Location" event')
if not self.live and entry['event'] not in (None, 'Fileheader'):
# Game not running locally, but Journal has been updated
self.live = True
if self.station:
entry = OrderedDict([
('timestamp', strftime('%Y-%m-%dT%H:%M:%SZ', gmtime())),
('event', 'StartUp'),
('Docked', True),
('MarketID', self.station_marketid),
('StationName', self.station),
('StationType', self.stationtype),
('StarSystem', self.system),
('StarPos', self.coordinates),
('SystemAddress', self.systemaddress),
])
else:
entry = OrderedDict([
('timestamp', strftime('%Y-%m-%dT%H:%M:%SZ', gmtime())),
('event', 'StartUp'),
('Docked', False),
('StarSystem', self.system),
('StarPos', self.coordinates),
('SystemAddress', self.systemaddress),
])
if entry['event'] == 'Location': if entry['event'] == 'Location':
logger.trace('"Location" event') logger.trace('Appending "Location" event to event_queue')
if not self.live and entry['event'] not in (None, 'Fileheader'): self.event_queue.put(json.dumps(entry, separators=(', ', ':')))
# Game not running locally, but Journal has been updated
self.live = True
if self.station:
entry = OrderedDict([
('timestamp', strftime('%Y-%m-%dT%H:%M:%SZ', gmtime())),
('event', 'StartUp'),
('Docked', True),
('MarketID', self.station_marketid),
('StationName', self.station),
('StationType', self.stationtype),
('StarSystem', self.system),
('StarPos', self.coordinates),
('SystemAddress', self.systemaddress),
])
else: elif self.live and entry['event'] == 'Music' and entry.get('MusicTrack') == 'MainMenu':
entry = OrderedDict([ ts = strftime('%Y-%m-%dT%H:%M:%SZ', gmtime())
('timestamp', strftime('%Y-%m-%dT%H:%M:%SZ', gmtime())), self.event_queue.put(
('event', 'StartUp'), f'{{ "timestamp":"{ts}", "event":"ShutDown" }}'
('Docked', False), )
('StarSystem', self.system),
('StarPos', self.coordinates),
('SystemAddress', self.systemaddress),
])
if entry['event'] == 'Location': return entry
logger.trace('Appending "Location" event to event_queue')
self.event_queue.append(json.dumps(entry, separators=(', ', ':')))
elif self.live and entry['event'] == 'Music' and entry.get('MusicTrack') == 'MainMenu':
ts = strftime('%Y-%m-%dT%H:%M:%SZ', gmtime())
self.event_queue.append(
f'{{ "timestamp":"{ts}", "event":"ShutDown" }}'
)
return entry
def game_running(self) -> bool: # noqa: CCR001 def game_running(self) -> bool: # noqa: CCR001
""" """