@@ -193,8 +193,8 @@ def get_engine(cls):
193193 if (DataBase .wadas_db .type == DataBase .DBTypes .SQLITE )
194194 else create_engine (
195195 DataBase .wadas_db .get_connection_string (),
196- pool_recycle = 1800 , # Recycle connection every 30 minutes
197- pool_pre_ping = True , # Check if connection is still valid
196+ pool_recycle = 300 , # Recycle connection every 5 minutes (under MariaDB wait_timeout)
197+ pool_pre_ping = True , # Check if connection is still valid before use
198198 )
199199 )
200200 return DataBase .wadas_db_engine
@@ -237,12 +237,18 @@ def create_session(cls, retry_count=0):
237237 if engine := cls .get_engine ():
238238 # If db is not SQLite, check engine status (SQLite has no pre-existing sessions)
239239 if DataBase .wadas_db .type != DataBase .DBTypes .SQLITE :
240- with engine .connect () as connection :
241- if connection .invalidated :
242- logger .warning ("Connection invalidated, disposing engine..." )
243- engine .dispose ()
244- DataBase .wadas_db_engine = None # Force new engine
245- engine = cls .get_engine ()
240+ try :
241+ with engine .connect () as connection :
242+ if connection .invalidated :
243+ logger .warning ("Connection invalidated, disposing engine..." )
244+ engine .dispose ()
245+ DataBase .wadas_db_engine = None # Force new engine
246+ engine = cls .get_engine ()
247+ except (InterfaceError , SQLAlchemyOperationalError , mariadbOperationalerror ):
248+ logger .warning ("Pre-ping connection check failed, disposing engine..." )
249+ engine .dispose ()
250+ DataBase .wadas_db_engine = None
251+ engine = cls .get_engine ()
246252
247253 Session = sessionmaker (bind = engine )
248254 return Session ()
@@ -277,6 +283,8 @@ def get_db_uuid(cls):
277283 return result [0 ] if result else None
278284 except Exception :
279285 return None
286+ finally :
287+ session .close ()
280288 else :
281289 return None
282290
@@ -290,6 +298,8 @@ def get_db_version(cls):
290298 return result [0 ] if result else None
291299 except Exception :
292300 return None
301+ finally :
302+ session .close ()
293303 else :
294304 return None
295305
@@ -767,36 +777,40 @@ def remove_actuator_from_camera(cls, camera, actuator):
767777
768778 if cls .get_instance ():
769779 logger .debug ("Removing actuator %s from camera %s in db." , actuator .id , camera .id )
770- if cls .create_session ():
771- # Retrieve camera and actuator db instances
772- camera_db_id = cls .get_camera_id (camera .id )
773- actuator_db_id = cls .get_actuator_id (actuator .id )
774-
775- stmt = delete (camera_actuator_association ).where (
776- and_ (
777- camera_actuator_association .c .actuator_id == actuator_db_id ,
778- camera_actuator_association .c .camera_id == camera_db_id ,
779- )
780+ # Retrieve camera and actuator db instances
781+ camera_db_id = cls .get_camera_id (camera .id )
782+ actuator_db_id = cls .get_actuator_id (actuator .id )
783+
784+ stmt = delete (camera_actuator_association ).where (
785+ and_ (
786+ camera_actuator_association .c .actuator_id == actuator_db_id ,
787+ camera_actuator_association .c .camera_id == camera_db_id ,
780788 )
781- cls .run_query (stmt )
782- else :
783- logger .debug ("Could not create db session, skipping actuator association insert." )
789+ )
790+ cls .run_query (stmt )
791+ else :
792+ logger .debug ("Could not create db session, skipping actuator association insert." )
784793
785794 @classmethod
786795 def get_camera_id (cls , camera_id ):
787796 """Method to return camera database id (primary key)"""
788797
789798 if session := cls .create_session ():
790- return (
791- session .query (ORMCamera .db_id )
792- .filter (
793- and_ (
794- ORMCamera .camera_id == camera_id ,
795- ORMCamera .deletion_date .is_ (None ), # Avoid to return id of deleted camera
799+ try :
800+ return (
801+ session .query (ORMCamera .db_id )
802+ .filter (
803+ and_ (
804+ ORMCamera .camera_id == camera_id ,
805+ ORMCamera .deletion_date .is_ (
806+ None
807+ ), # Avoid to return id of deleted camera
808+ )
796809 )
797- )
798- .scalar ()
799- ) # Use scalar() to retrieve the value directly
810+ .scalar ()
811+ ) # Use scalar() to retrieve the value directly
812+ finally :
813+ session .close ()
800814 else :
801815 logger .debug (
802816 "Could not get camera id %s since session has not been created." , camera_id
@@ -808,16 +822,21 @@ def get_actuator_id(cls, actuator_id):
808822 """Method to return actuator database id (primary key)"""
809823
810824 if session := cls .create_session ():
811- return (
812- session .query (ORMActuator .db_id )
813- .filter (
814- and_ (
815- ORMActuator .actuator_id == actuator_id ,
816- ORMActuator .deletion_date .is_ (None ), # Avoid to return id of deleted camera
825+ try :
826+ return (
827+ session .query (ORMActuator .db_id )
828+ .filter (
829+ and_ (
830+ ORMActuator .actuator_id == actuator_id ,
831+ ORMActuator .deletion_date .is_ (
832+ None
833+ ), # Avoid to return id of deleted camera
834+ )
817835 )
836+ .scalar ()
818837 )
819- . scalar ()
820- )
838+ finally :
839+ session . close ( )
821840 else :
822841 logger .debug (
823842 "Could not get actuator id %s since session has not been created." , actuator_id
@@ -836,16 +855,19 @@ def get_detection_event_id(cls, detection_event: DetectionEvent):
836855 return None
837856
838857 if session := cls .create_session ():
839- return (
840- session .query (ORMDetectionEvent .db_id )
841- .filter (
842- and_ (
843- ORMDetectionEvent .camera_id == camera_db_id ,
844- ORMDetectionEvent .time_stamp == detection_event .time_stamp ,
858+ try :
859+ return (
860+ session .query (ORMDetectionEvent .db_id )
861+ .filter (
862+ and_ (
863+ ORMDetectionEvent .camera_id == camera_db_id ,
864+ ORMDetectionEvent .time_stamp == detection_event .time_stamp ,
865+ )
845866 )
846- )
847- .scalar ()
848- ) # Use scalar() to retrieve the value directly
867+ .scalar ()
868+ ) # Use scalar() to retrieve the value directly
869+ finally :
870+ session .close ()
849871 else :
850872 logger .error (
851873 "Could not retrieve detection event id as connection could not be created."
@@ -1379,7 +1401,7 @@ def create_database(self):
13791401 # Connect to MySQL server to check DB connection, credentials and db existence
13801402 test_engine = create_engine (
13811403 f"mysql+pymysql://{ self .username } :{ self .get_password ()} @{ self .host } :{ self .port } " ,
1382- pool_recycle = 1800 ,
1404+ pool_recycle = 300 ,
13831405 pool_pre_ping = True ,
13841406 )
13851407
@@ -1439,7 +1461,7 @@ def create_database(self):
14391461 temp_engine = create_engine (
14401462 f"mysql+pymysql://{ self .username } :{ self .get_password ()} "
14411463 f"@{ self .host } :{ self .port } " ,
1442- pool_recycle = 1800 ,
1464+ pool_recycle = 300 ,
14431465 pool_pre_ping = True ,
14441466 )
14451467
@@ -1463,7 +1485,7 @@ def create_database(self):
14631485
14641486 # Recreate engine with correct database
14651487 DataBase .wadas_db_engine = create_engine (
1466- self .get_connection_string (), pool_recycle = 1800 , pool_pre_ping = True
1488+ self .get_connection_string (), pool_recycle = 300 , pool_pre_ping = True
14671489 )
14681490
14691491 # Create tables
@@ -1564,9 +1586,7 @@ def get_connection_string(self, create=False):
15641586 if not self .database_name and not create :
15651587 raise ValueError ("Database name is required for MariaDB." )
15661588
1567- base_string = (
1568- f"mariadb+mariadbconnector://{ self .username } :{ password } @{ self .host } :{ self .port } "
1569- )
1589+ base_string = f"mariadb+pymysql://{ self .username } :{ password } @{ self .host } :{ self .port } "
15701590 return base_string if create else f"{ base_string } /{ self .database_name } "
15711591
15721592 def create_database (self ):
@@ -1578,7 +1598,7 @@ def create_database(self):
15781598 try :
15791599 # Connect to MariaDB server to check DB connection, credentials and db existence
15801600 test_engine = create_engine (
1581- self .get_connection_string (create = True ), pool_recycle = 1800 , pool_pre_ping = True
1601+ self .get_connection_string (create = True ), pool_recycle = 300 , pool_pre_ping = True
15821602 )
15831603
15841604 with test_engine .connect () as conn :
@@ -1635,7 +1655,7 @@ def create_database(self):
16351655 try :
16361656 # Connect without specifying the database
16371657 temp_engine = create_engine (
1638- self .get_connection_string (create = True ), pool_recycle = 1800 , pool_pre_ping = True
1658+ self .get_connection_string (create = True ), pool_recycle = 300 , pool_pre_ping = True
16391659 )
16401660
16411661 with temp_engine .connect () as conn :
@@ -1658,7 +1678,7 @@ def create_database(self):
16581678
16591679 # Recreate engine with correct database
16601680 DataBase .wadas_db_engine = create_engine (
1661- self .get_connection_string (create = False ), pool_recycle = 1800 , pool_pre_ping = True
1681+ self .get_connection_string (create = False ), pool_recycle = 300 , pool_pre_ping = True
16621682 )
16631683
16641684 # Create tables
0 commit comments