1
0
mirror of https://github.com/EDCD/EDMarketConnector.git synced 2025-06-05 18:03:17 +03:00

EDDN: Moving replay functionality into its own class

This commit is contained in:
Athanasius 2022-09-28 17:39:36 +01:00 committed by Athanasius
parent 072eadd893
commit 03e432034f
No known key found for this signature in database
GPG Key ID: 772697E181BB2767

View File

@ -114,7 +114,6 @@ class This:
this = This() this = This()
# This SKU is tagged on any module or ship that you must have Horizons for. # This SKU is tagged on any module or ship that you must have Horizons for.
HORIZONS_SKU = 'ELITE_HORIZONS_V_PLANETARY_LANDINGS' HORIZONS_SKU = 'ELITE_HORIZONS_V_PLANETARY_LANDINGS'
# ELITE_HORIZONS_V_COBRA_MK_IV_1000` is for the Cobra Mk IV, but # ELITE_HORIZONS_V_COBRA_MK_IV_1000` is for the Cobra Mk IV, but
@ -126,8 +125,84 @@ HORIZONS_SKU = 'ELITE_HORIZONS_V_PLANETARY_LANDINGS'
# one. # one.
# TODO: a good few of these methods are static or could be classmethods. they should be created as such. class EDDNReplay:
"""Store and retry sending of EDDN messages."""
SQLITE_DB_FILENAME = 'eddn_replay.db'
def __init__(self) -> None:
"""
Prepare the system for processing messages.
- Ensure the sqlite3 database for EDDN replays exists and has schema.
- Convert any legacy file into the database.
"""
self.db_conn = sqlite3.connect(config.app_dir_path / self.SQLITE_DB_FILENAME)
self.db = self.db_conn.cursor()
try:
self.db.execute(
"""
CREATE TABLE messages
(
id INTEGER PRIMARY KEY AUTOINCREMENT,
created TEXT NOT NULL,
cmdr TEXT NOT NULL,
edmc_version TEXT,
game_version TEXT,
game_build TEXT,
message TEXT NOT NULL
)
"""
)
self.db.execute(
"""
CREATE INDEX messages_created ON messages
(
created
)
"""
)
self.db.execute(
"""
CREATE INDEX messages_cmdr ON messages
(
cmdr
)
"""
)
except sqlite3.OperationalError as e:
if str(e) != "table messages already exists":
raise e
self.convert_legacy_file()
def convert_legacy_file(self):
"""Convert a legacy file's contents into the sqlite3 db."""
try:
for m in self.load_legacy_file():
...
except FileNotFoundError:
pass
def load_legacy_file(self) -> list[str]:
"""
Load cached journal entries from disk.
:return: Contents of the file as a list.
"""
# Try to obtain exclusive access to the journal cache
filename = config.app_dir_path / 'replay.jsonl'
# Try to open existing file
with open(filename, 'r+', buffering=1) as replay_file:
return [line.strip() for line in replay_file]
# TODO: a good few of these methods are static or could be classmethods. they should be created as such.
class EDDN: class EDDN:
"""EDDN Data export.""" """EDDN Data export."""
@ -155,19 +230,7 @@ class EDDN:
####################################################################### #######################################################################
# EDDN delayed sending/retry # EDDN delayed sending/retry
####################################################################### #######################################################################
self.replaydb = self.journal_replay_sqlite_init() self.replay = EDDNReplay()
# Kept only for converting legacy file to sqlite3
try:
replaylog = self.load_journal_replay_file()
except FileNotFoundError:
pass
finally:
# TODO: Convert `replaylog` into the database.
# Remove the file.
...
####################################################################### #######################################################################
self.fss_signals: List[Mapping[str, Any]] = [] self.fss_signals: List[Mapping[str, Any]] = []
@ -178,68 +241,6 @@ class EDDN:
else: else:
self.eddn_url = self.DEFAULT_URL self.eddn_url = self.DEFAULT_URL
def journal_replay_sqlite_init(self) -> sqlite3.Cursor:
"""
Ensure the sqlite3 database for EDDN replays exists and has schema.
:return: sqlite3 cursor for the database.
"""
self.replaydb_conn = sqlite3.connect(config.app_dir_path / 'eddn_replay.db')
replaydb = self.replaydb_conn.cursor()
try:
replaydb.execute(
"""
CREATE TABLE messages
(
id INTEGER PRIMARY KEY AUTOINCREMENT,
created TEXT NOT NULL,
cmdr TEXT NOT NULL,
edmc_version TEXT,
game_version TEXT,
game_build TEXT,
message TEXT NOT NULL
)
"""
)
replaydb.execute(
"""
CREATE INDEX messages_created ON messages
(
created
)
"""
)
replaydb.execute(
"""
CREATE INDEX messages_cmdr ON messages
(
cmdr
)
"""
)
except sqlite3.OperationalError as e:
if str(e) != "table messages already exists":
raise e
return replaydb
def load_journal_replay_file(self) -> list[str]:
"""
Load cached journal entries from disk.
Simply let any exceptions propagate up if there's an error.
:return: Contents of the file as a list.
"""
# Try to obtain exclusive access to the journal cache
filename = config.app_dir_path / 'replay.jsonl'
# Try to open existing file
with open(filename, 'r+', buffering=1) as replay_file:
return [line.strip() for line in replay_file]
def flush(self): def flush(self):
"""Flush the replay file, clearing any data currently there that is not in the replaylog list.""" """Flush the replay file, clearing any data currently there that is not in the replaylog list."""
if self.replayfile is None: if self.replayfile is None:
@ -361,6 +362,10 @@ class EDDN:
def sendreplay(self) -> None: # noqa: CCR001 def sendreplay(self) -> None: # noqa: CCR001
"""Send cached Journal lines to EDDN.""" """Send cached Journal lines to EDDN."""
# TODO: Convert to using the sqlite3 db
# **IF** this is moved to a thread worker then we need to ensure
# that we're operating sqlite3 in a thread-safe manner,
# Ref: <https://ricardoanderegg.com/posts/python-sqlite-thread-safety/>
if not self.replayfile: if not self.replayfile:
return # Probably closing app return # Probably closing app
@ -806,7 +811,7 @@ class EDDN:
:param entry: The full journal event dictionary (due to checks in this function). :param entry: The full journal event dictionary (due to checks in this function).
:param msg: The EDDN message body to be sent. :param msg: The EDDN message body to be sent.
""" """
if self.replayfile or self.load_journal_replay_file(): if self.replayfile or self.journal_replay_load_file():
# Store the entry # Store the entry
self.replaylog.append(json.dumps([cmdr, msg])) self.replaylog.append(json.dumps([cmdr, msg]))
self.replayfile.write(f'{self.replaylog[-1]}\n') # type: ignore self.replayfile.write(f'{self.replaylog[-1]}\n') # type: ignore