Compare commits

...

2 Commits

Author SHA1 Message Date
pdxlocations b889711f63 ignore 2025-03-08 22:32:23 -08:00
pdxlocations 361da1c078 db optimizations 2025-03-08 22:31:28 -08:00
2 changed files with 72 additions and 42 deletions
+4 -1
View File
@@ -7,4 +7,7 @@ client.db
client.log client.log
settings.log settings.log
config.json config.json
default_config.log default_config.log
client.db-shm
client.db-wal
client.db.bk
+68 -41
View File
@@ -1,17 +1,42 @@
import sqlite3 import sqlite3
import time import time
import logging import logging
import re
from datetime import datetime from datetime import datetime
from utilities.utils import decimal_to_hex from utilities.utils import decimal_to_hex
import ui.default_config as config import ui.default_config as config
import globals import globals
def get_db_connection():
"""Get a SQLite connection with optimized PRAGMA settings."""
db_connection = sqlite3.connect(config.db_file_path, check_same_thread=False)
db_cursor = db_connection.cursor()
# Check if journal_mode is already set to WAL
db_cursor.execute("PRAGMA journal_mode;")
current_journal_mode = db_cursor.fetchone()[0]
if current_journal_mode != "wal":
db_cursor.execute("PRAGMA journal_mode=WAL;")
# Apply remaining PRAGMA settings (these are fine to execute every time)
db_cursor.executescript("""
PRAGMA synchronous=NORMAL;
PRAGMA cache_size=-64000;
PRAGMA temp_store=MEMORY;
PRAGMA foreign_keys=ON;
""")
return db_connection
def get_table_name(channel): def get_table_name(channel):
# Construct the table name """Returns a properly formatted and safe table name."""
table_name = f"{str(globals.myNodeNum)}_{channel}_messages" safe_channel = re.sub(r'[^a-zA-Z0-9_]', '', str(channel))
quoted_table_name = f'"{table_name}"' # Quote the table name becuase we begin with numerics and contain spaces table_name = f"{globals.myNodeNum}_{safe_channel}_messages"
return quoted_table_name return f'"{table_name}"'
def save_message_to_db(channel, user_id, message_text): def save_message_to_db(channel, user_id, message_text):
@@ -27,7 +52,7 @@ def save_message_to_db(channel, user_id, message_text):
''' '''
ensure_table_exists(quoted_table_name, schema) ensure_table_exists(quoted_table_name, schema)
with sqlite3.connect(config.db_file_path) as db_connection: with get_db_connection() as db_connection:
db_cursor = db_connection.cursor() db_cursor = db_connection.cursor()
timestamp = int(time.time()) timestamp = int(time.time())
@@ -49,7 +74,7 @@ def save_message_to_db(channel, user_id, message_text):
def update_ack_nak(channel, timestamp, message, ack): def update_ack_nak(channel, timestamp, message, ack):
try: try:
with sqlite3.connect(config.db_file_path) as db_connection: with get_db_connection() as db_connection:
db_cursor = db_connection.cursor() db_cursor = db_connection.cursor()
update_query = f""" update_query = f"""
UPDATE {get_table_name(channel)} UPDATE {get_table_name(channel)}
@@ -72,7 +97,7 @@ def update_ack_nak(channel, timestamp, message, ack):
def load_messages_from_db(): def load_messages_from_db():
"""Load messages from the database for all channels and update globals.all_messages and globals.channel_list.""" """Load messages from the database for all channels and update globals.all_messages and globals.channel_list."""
try: try:
with sqlite3.connect(config.db_file_path) as db_connection: with get_db_connection() as db_connection:
db_cursor = db_connection.cursor() db_cursor = db_connection.cursor()
query = "SELECT name FROM sqlite_master WHERE type='table' AND name LIKE ?" query = "SELECT name FROM sqlite_master WHERE type='table' AND name LIKE ?"
@@ -196,7 +221,7 @@ def update_node_info_in_db(user_id, long_name=None, short_name=None, hw_model=No
try: try:
ensure_node_table_exists() # Ensure the table exists before any operation ensure_node_table_exists() # Ensure the table exists before any operation
with sqlite3.connect(config.db_file_path) as db_connection: with get_db_connection() as db_connection:
db_cursor = db_connection.cursor() db_cursor = db_connection.cursor()
table_name = f'"{globals.myNodeNum}_nodedb"' # Quote in case of numeric names table_name = f'"{globals.myNodeNum}_nodedb"' # Quote in case of numeric names
@@ -223,16 +248,16 @@ def update_node_info_in_db(user_id, long_name=None, short_name=None, hw_model=No
# Upsert logic # Upsert logic
upsert_query = f''' upsert_query = f'''
INSERT INTO {table_name} (user_id, long_name, short_name, hw_model, is_licensed, role, public_key, chat_archived) INSERT INTO {table_name} (user_id, long_name, short_name, hw_model, is_licensed, role, public_key, chat_archived)
VALUES (?, ?, ?, ?, ?, ?, ?, ?) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
ON CONFLICT(user_id) DO UPDATE SET ON CONFLICT(user_id) DO UPDATE SET
long_name = excluded.long_name, long_name = excluded.long_name,
short_name = excluded.short_name, short_name = excluded.short_name,
hw_model = excluded.hw_model, hw_model = excluded.hw_model,
is_licensed = excluded.is_licensed, is_licensed = excluded.is_licensed,
role = excluded.role, role = excluded.role,
public_key = excluded.public_key, public_key = excluded.public_key,
chat_archived = excluded.chat_archived chat_archived = COALESCE(excluded.chat_archived, chat_archived);
''' '''
db_cursor.execute(upsert_query, (user_id, long_name, short_name, hw_model, is_licensed, role, public_key, chat_archived)) db_cursor.execute(upsert_query, (user_id, long_name, short_name, hw_model, is_licensed, role, public_key, chat_archived))
db_connection.commit() db_connection.commit()
@@ -262,7 +287,7 @@ def ensure_node_table_exists():
def ensure_table_exists(table_name, schema): def ensure_table_exists(table_name, schema):
"""Ensure the given table exists in the database.""" """Ensure the given table exists in the database."""
try: try:
with sqlite3.connect(config.db_file_path) as db_connection: with get_db_connection() as db_connection:
db_cursor = db_connection.cursor() db_cursor = db_connection.cursor()
create_table_query = f"CREATE TABLE IF NOT EXISTS {table_name} ({schema})" create_table_query = f"CREATE TABLE IF NOT EXISTS {table_name} ({schema})"
db_cursor.execute(create_table_query) db_cursor.execute(create_table_query)
@@ -273,31 +298,32 @@ def ensure_table_exists(table_name, schema):
logging.error(f"Unexpected error in ensure_table_exists({table_name}): {e}") logging.error(f"Unexpected error in ensure_table_exists({table_name}): {e}")
name_cache = {}
def get_name_from_database(user_id, type="long"): def get_name_from_database(user_id, type="long"):
""" """Retrieve a user's name from the node database with caching."""
Retrieve a user's name (long or short) from the node database. # Check if we already cached both long and short names
if user_id in name_cache and type in name_cache[user_id]:
:param user_id: The user ID to look up. return name_cache[user_id][type]
:param type: "long" for long name, "short" for short name.
:return: The retrieved name or the hex of the user id
"""
try: try:
with sqlite3.connect(config.db_file_path) as db_connection: with get_db_connection() as db_connection:
db_cursor = db_connection.cursor() db_cursor = db_connection.cursor()
# Construct table name
table_name = f"{str(globals.myNodeNum)}_nodedb" table_name = f"{str(globals.myNodeNum)}_nodedb"
nodeinfo_table = f'"{table_name}"' # Quote table name for safety nodeinfo_table = f'"{table_name}"'
# Determine the correct column to fetch
column_name = "long_name" if type == "long" else "short_name"
# Query the database # Fetch both long and short names in one query
query = f"SELECT {column_name} FROM {nodeinfo_table} WHERE user_id = ?" db_cursor.execute(f"SELECT long_name, short_name FROM {nodeinfo_table} WHERE user_id = ?", (user_id,))
db_cursor.execute(query, (user_id,))
result = db_cursor.fetchone() result = db_cursor.fetchone()
return result[0] if result else decimal_to_hex(user_id) if result:
long_name, short_name = result or ("Unknown", "Unknown") # Handle empty result
name_cache[user_id] = {"long": long_name, "short": short_name}
return name_cache[user_id][type]
# If no result, store a fallback value in the cache to avoid future DB queries
name_cache[user_id] = {"long": decimal_to_hex(user_id), "short": decimal_to_hex(user_id)}
return name_cache[user_id][type]
except sqlite3.Error as e: except sqlite3.Error as e:
logging.error(f"SQLite error in get_name_from_database: {e}") logging.error(f"SQLite error in get_name_from_database: {e}")
@@ -306,10 +332,12 @@ def get_name_from_database(user_id, type="long"):
except Exception as e: except Exception as e:
logging.error(f"Unexpected error in get_name_from_database: {e}") logging.error(f"Unexpected error in get_name_from_database: {e}")
return "Unknown" return "Unknown"
def is_chat_archived(user_id): def is_chat_archived(user_id):
"""Check if a chat is archived, returning 0 (False) if not found."""
try: try:
with sqlite3.connect(config.db_file_path) as db_connection: with get_db_connection() as db_connection:
db_cursor = db_connection.cursor() db_cursor = db_connection.cursor()
table_name = f"{str(globals.myNodeNum)}_nodedb" table_name = f"{str(globals.myNodeNum)}_nodedb"
nodeinfo_table = f'"{table_name}"' nodeinfo_table = f'"{table_name}"'
@@ -321,9 +349,8 @@ def is_chat_archived(user_id):
except sqlite3.Error as e: except sqlite3.Error as e:
logging.error(f"SQLite error in is_chat_archived: {e}") logging.error(f"SQLite error in is_chat_archived: {e}")
return "Unknown" return 0
except Exception as e: except Exception as e:
logging.error(f"Unexpected error in is_chat_archived: {e}") logging.error(f"Unexpected error in is_chat_archived: {e}")
return "Unknown" return 0