From 93283c27f6c3b14b67760cdec30b7942bb3ca1fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Ke=C3=9Fler?= Date: Wed, 22 Nov 2023 23:50:20 +0100 Subject: [PATCH] Handle existing values in DB insertion --- database.py | 6 +++--- fetch_games.py | 28 ++++++++++++++-------------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/database.py b/database.py index 1a0af3c..b68021a 100644 --- a/database.py +++ b/database.py @@ -7,7 +7,7 @@ import requests import unidecode import constants -from config import read_db_config, read_config +from config import config_manager from log_setup import logger @@ -16,7 +16,7 @@ class DBConnectionManager: self._conn = None def connect(self): - config = read_db_config() + config = config_manager.get_db_config() logger.debug("Establishing database connection with dbname={}, user={}, password={}".format( config.db_name, config.db_user, config.db_pass )) @@ -79,7 +79,7 @@ def fetch_and_initialize_variants(): return variants = json.loads(response.text) - config = read_config() + config = config_manager.get_config() for variant in variants: variant_id = variant['id'] diff --git a/fetch_games.py b/fetch_games.py index 8ab3f64..f39add5 100644 --- a/fetch_games.py +++ b/fetch_games.py @@ -33,8 +33,9 @@ class GameInfo: self.user_ids = user_ids self.normalized_usernames = normalized_usernames + def fetch_games_for_player(username: str, latest_game_id: int): - logger.verbose("Fetching games for username {}".format(username)) + logger.verbose("Fetching games for username {} more recent than id {}".format(username, latest_game_id)) url = "https://hanab.live/api/v1/history-full/{}?start={}".format(username, latest_game_id + 1) response = session.get(url) if not response.status_code == 200: @@ -145,32 +146,31 @@ def store_new_games(games: Dict[int, GameInfo]): latest_game_ids[normalized_username] = game.game_id # Do the insertions + # Notice that on conflict we can just do nothing: In that case, we already have the game in the DB for some reason + # (for example, because we forced a download refresh) psycopg2.extras.execute_values( cur, "INSERT INTO games (id, num_players, variant_id, seed, score, num_turns) " - "VALUES %s", + "VALUES %s " + "ON CONFLICT (id) DO NOTHING", games_vals ) psycopg2.extras.execute_values( cur, "INSERT INTO game_participants (game_id, user_id) " - "VALUES %s", + "VALUES %s " + "ON CONFLICT (game_id, user_id) DO NOTHING", game_participants_vals ) + # Here, we want to update on insertion conflict psycopg2.extras.execute_values( cur, "INSERT INTO downloads (normalized_username, latest_game_id) " - "VALUES %s", + "VALUES %s " + "ON CONFLICT (normalized_username) " + "DO UPDATE SET (normalized_username, latest_game_id) = (EXCLUDED.normalized_username, EXCLUDED.latest_game_id)", latest_game_ids.items() ) + # We only commit after performing all insertions. This guarantees that the download table is always in sync + # with the actual games stored in the database. conn.commit() - """ - cur.execute("INSERT INTO games (id, num_players, variant_id, seed, score, num_turns) " - "VALUES %s"" - ) - game_participant_args = b", ".join(game_participants_vals) - cur.execute("INSERT INTO game_participants (game_id, user_id, seat) " - "VALUES {}".format(game_participants_vals)) - - conn.commit() -"""