From 5539f3be16b1ca286a47c0741966e8cddf94c80a Mon Sep 17 00:00:00 2001 From: Florian Bezannier Date: Sat, 13 Sep 2025 15:57:07 +0200 Subject: [PATCH] fix: db lock #1069 --- .../psacc/application/battery_charge_curve.py | 3 - psa_car_controller/psacc/repository/db.py | 89 +++++++++++-------- psa_car_controller/web/figures.py | 1 + 3 files changed, 54 insertions(+), 39 deletions(-) diff --git a/psa_car_controller/psacc/application/battery_charge_curve.py b/psa_car_controller/psacc/application/battery_charge_curve.py index 72ee5f0..bfde39f 100644 --- a/psa_car_controller/psacc/application/battery_charge_curve.py +++ b/psa_car_controller/psacc/application/battery_charge_curve.py @@ -5,7 +5,6 @@ from typing import List from psa_car_controller.psacc.model.battery_curve import BatteryCurveDto from psa_car_controller.psacc.model.car import Car from psa_car_controller.psacc.model.charge import Charge -from psa_car_controller.psacc.repository.db import Database DEFAULT_KM_BY_KW = 5.3 MINIMUM_AUTONOMY_FOR_GOOD_RESULT = 20 @@ -21,8 +20,6 @@ class BatteryChargeCurve: -> 'List[BatteryChargeCurve]': # pylint: disable=too-many-locals start_date = charge.start_at stop_at = charge.stop_at - conn = Database.get_db() - conn.close() battery_curves = [] if len(battery_curves_dto) > 0 and battery_curves_dto[-1].level > 0 and battery_curves_dto[-1].autonomy > 0: battery_capacity = battery_curves_dto[-1].level * car.battery_power / 100 diff --git a/psa_car_controller/psacc/repository/db.py b/psa_car_controller/psacc/repository/db.py index cd9a63a..2d32ddd 100644 --- a/psa_car_controller/psacc/repository/db.py +++ b/psa_car_controller/psacc/repository/db.py @@ -132,7 +132,7 @@ class Database: @staticmethod def check_db_access() -> bool: try: - Database.get_db() + Database.get_db().close() return True except sqlite3.OperationalError: logger.fatal("Can't access to db file check permission") @@ -253,31 +253,42 @@ class Database: if mileage == 0: # fix a bug of the api logger.error("The api return a wrong mileage for %s : %f", vin, mileage) else: - conn = Database.get_db() - if conn.execute("SELECT Timestamp from position where Timestamp=?", (date,)).fetchone() is None: - temp = get_temp(latitude, longitude, weather_api) - if level_fuel and level_fuel == 0: # fix fuel level not provided when car is off - try: - level_fuel = conn.execute( - "SELECT level_fuel FROM position WHERE level_fuel>0 AND VIN=? ORDER BY Timestamp DESC " - "LIMIT 1", - (vin,)).fetchone()[0] - logger.info("level_fuel fixed with last real value %f for %s", level_fuel, vin) - except TypeError: - level_fuel = None - logger.info("level_fuel unfixed for %s", vin) + try: + conn = Database.get_db() + if conn.execute("SELECT Timestamp from position where Timestamp=?", (date,)).fetchone() is None: + temp = get_temp(latitude, longitude, weather_api) + if level_fuel and level_fuel == 0: # fix fuel level not provided when car is off + try: + level_fuel = conn.execute( + "SELECT level_fuel FROM position WHERE level_fuel>0 AND VIN=? ORDER BY Timestamp DESC " + "LIMIT 1", + (vin,)).fetchone()[0] + logger.info("level_fuel fixed with last real value %f for %s", level_fuel, vin) + except TypeError: + level_fuel = None + logger.info("level_fuel unfixed for %s", vin) - conn.execute("INSERT INTO position(Timestamp,VIN,longitude,latitude,altitude,mileage,level,level_fuel," - "moving,temperature) VALUES(?,?,?,?,?,?,?,?,?,?)", - (date, vin, longitude, latitude, altitude, mileage, level, level_fuel, moving, temp)) + conn.execute( + "INSERT INTO position(Timestamp,VIN,longitude,latitude,altitude,mileage,level,level_fuel," + "moving,temperature) VALUES(?,?,?,?,?,?,?,?,?,?)", + (date, + vin, + longitude, + latitude, + altitude, + mileage, + level, + level_fuel, + moving, + temp)) - conn.commit() - logger.info("new position recorded for %s", vin) - Database.clean_position(conn) + conn.commit() + logger.info("new position recorded for %s", vin) + Database.clean_position(conn) + return True + logger.debug("position already saved") + finally: conn.close() - return True - conn.close() - logger.debug("position already saved") return False @staticmethod @@ -296,6 +307,7 @@ class Database: for row in res: dates.append(row[0]) levels.append(row[1]) + conn.close() return BatterySoh(vin, dates, levels) @staticmethod @@ -308,10 +320,13 @@ class Database: @staticmethod def get_last_charge(vin) -> Charge: - conn = Database.get_db() - res = conn.execute("SELECT * FROM battery WHERE VIN=? ORDER BY start_at DESC limit 1", (vin,)).fetchone() - if res: - return Charge(**dict_key_to_lower_case(**res)) + try: + conn = Database.get_db() + res = conn.execute("SELECT * FROM battery WHERE VIN=? ORDER BY start_at DESC limit 1", (vin,)).fetchone() + if res: + return Charge(**dict_key_to_lower_case(**res)) + finally: + conn.close() return None @staticmethod @@ -342,12 +357,14 @@ class Database: def update_charge(charge: Charge): # we don't need to update mileage, since it should be inserted at beginning of charge, # maybe in future this will be supported - conn = Database.get_db() - res = conn.execute( - "UPDATE battery set stop_at=?, end_level=?, co2=?, kw=?, price=? WHERE start_at=? and VIN=?", - (charge.stop_at, charge.end_level, charge.co2, charge.kw, charge.price, charge.start_at, - charge.vin)).rowcount - if res == 0: - logger.error("Can't find battery row to update") - conn.commit() - conn.close() + try: + conn = Database.get_db() + res = conn.execute( + "UPDATE battery set stop_at=?, end_level=?, co2=?, kw=?, price=? WHERE start_at=? and VIN=?", + (charge.stop_at, charge.end_level, charge.co2, charge.kw, charge.price, charge.start_at, + charge.vin)).rowcount + if res == 0: + logger.error("Can't find battery row to update") + conn.commit() + finally: + conn.close() diff --git a/psa_car_controller/web/figures.py b/psa_car_controller/web/figures.py index cc1db39..e8d7436 100644 --- a/psa_car_controller/web/figures.py +++ b/psa_car_controller/web/figures.py @@ -209,6 +209,7 @@ def get_battery_curve_fig(row: dict, car: Car): battery_curves_dict = list(map(lambda bc: bc.__dict__, battery_curves)) fig = px.line(battery_curves_dict, x="level", y="speed") fig.update_layout(xaxis_title="Battery %", yaxis_title="Charging speed in kW") + conn.close() return html.Div(Graph(figure=fig))