@@ -102,6 +102,9 @@ class DBConnectionManager(type):
102102 instances : Dict [int , DBConnection ] = {}
103103
104104 def __call__ (cls , ** kwargs : Any ) -> DBConnection :
105+ if kwargs .get ('db_file' ):
106+ return super ().__call__ (** kwargs )
107+
105108 thread_id = current_thread_id ()
106109
107110 if (
@@ -126,23 +129,32 @@ def close_connection_of_thread(cls) -> None:
126129
127130
128131class DBConnection (Connection , metaclass = DBConnectionManager ):
129- file = ''
132+ default_file = ''
130133
131134 def __init__ (
132135 self , * ,
136+ db_file : Union [str , None ] = None ,
133137 timeout : float = Constants .DB_TIMEOUT
134138 ) -> None :
135139 """Create a connection with a database
136140
137141 Args:
142+ db_file (Union[str, None], optional): The database file to connect
143+ to. If `None`, the default file will be used. If something else
144+ than the default file is given, then a new connection will
145+ always be returned.
146+ Defaults to None.
147+
138148 timeout (float, optional): How long to wait before giving up
139149 on a command.
140150 Defaults to Constants.DB_TIMEOUT.
141151 """
142152 self .closed = False
153+ self .db_file = db_file or self .default_file
154+
143155 LOGGER .debug (f'Creating connection { self } ' )
144156 super ().__init__ (
145- self .file ,
157+ self .db_file ,
146158 timeout = timeout ,
147159 detect_types = PARSE_DECLTYPES
148160 )
@@ -164,20 +176,40 @@ def cursor( # type: ignore
164176 KapowarrCursor: The database cursor.
165177 """
166178 if not hasattr (g , 'cursors' ):
167- g .cursors = []
179+ g .cursors = {}
180+
181+ if self .db_file not in g .cursors :
182+ g .cursors [self .db_file ] = []
168183
169- if not g .cursors :
184+ if not g .cursors [ self . db_file ] :
170185 c = KapowarrCursor (self )
171186 c .row_factory = Row
172- g .cursors .append (c )
187+ g .cursors [ self . db_file ] .append (c )
173188
174189 if not force_new :
175- return g .cursors [0 ]
190+ return g .cursors [self . db_file ][ 0 ]
176191 else :
177192 c = KapowarrCursor (self )
178193 c .row_factory = Row
179- g .cursors .append (c )
180- return g .cursors [- 1 ]
194+ g .cursors [self .db_file ].append (c )
195+ return g .cursors [self .db_file ][- 1 ]
196+
197+ def create_backup (self , filepath : str ) -> None :
198+ """Create a backup of the current database.
199+
200+ Args:
201+ filepath (str): What the filepath of the backup will be.
202+ """
203+ self .execute (
204+ "VACUUM INTO ?;" ,
205+ (filepath ,)
206+ )
207+ return
208+
209+ def merge_wal_files (self ) -> None :
210+ "Merge the WAL files into the main database file"
211+ self .execute ("PRAGMA wal_checkpoint(TRUNCATE);" )
212+ return
181213
182214 def close (self ) -> None :
183215 """Close the database connection"""
@@ -204,6 +236,8 @@ def set_db_location(
204236 Raises:
205237 ValueError: Value of `db_folder` exists but is not a folder.
206238 """
239+ from backend .internals .settings import SettingsValues
240+
207241 if db_folder :
208242 if exists (db_folder ) and not isdir (db_folder ):
209243 raise ValueError ('Database location is not a folder' )
@@ -217,7 +251,8 @@ def set_db_location(
217251
218252 create_folder (dirname (db_file_location ))
219253
220- DBConnection .file = db_file_location
254+ DBConnection .default_file = db_file_location
255+ SettingsValues .db_backup_folder = dirname (db_file_location )
221256
222257 return
223258
@@ -278,13 +313,14 @@ def close_db(e: Union[BaseException, None] = None) -> None:
278313
279314 try :
280315 cursors = g .cursors
281- db : DBConnection = cursors [0 ].connection
282- for c in cursors :
283- c .close ()
316+ for cursors in g .cursors .values ():
317+ db : DBConnection = cursors [0 ].connection
318+ for c in cursors :
319+ c .close ()
320+ db .commit ()
321+ if not current_thread ().name .startswith ('waitress-' ):
322+ DBConnectionManager .close_connection_of_thread ()
284323 delattr (g , 'cursors' )
285- db .commit ()
286- if not current_thread ().name .startswith ('waitress-' ):
287- DBConnectionManager .close_connection_of_thread ()
288324
289325 except ProgrammingError :
290326 pass
0 commit comments