2424
2525import json
2626import logging
27+ import os
2728import random
2829import time
2930import zipfile
@@ -274,19 +275,33 @@ def refresh_has_metakg():
274275 smartapi .save ()
275276
276277
278+ def get_lock_pid ():
279+ """Read PID from lock file if it exists"""
280+ lock_file_path = ".lock"
281+ if os .path .exists (lock_file_path ):
282+ try :
283+ with open (lock_file_path , "r" ) as f :
284+ pid = f .read ().strip ()
285+ return int (pid ) if pid .isdigit () else None
286+ except Exception as e :
287+ logging .warning (f"Could not read PID from { lock_file_path } : { e } " )
288+ return None
289+ return None
290+
291+
277292restore = restore_from_file
278293backup = backup_to_file
279294
280295refresh = refresh_document
281296check = check_uptime
282297
283- # only one process should perform backup routines
284- _lock = FileLock (".lock" , timeout = 0 )
285-
286298
287299def routine (no_backup = False , format = "zip" ):
288300 logger = logging .getLogger ("routine" )
289301
302+ # only one process should perform backup routines
303+ _lock = FileLock (".lock" , timeout = 0 )
304+
290305 # Add jitter: random delay between 100 and 500 milliseconds (adjust range as needed)
291306 jitter_ms = random .uniform (100 , 500 ) # Jitter in milliseconds
292307 jitter_seconds = jitter_ms / 1000 # Convert milliseconds to seconds
@@ -300,7 +315,11 @@ def routine(no_backup=False, format="zip"):
300315 # it won't block here
301316 lock_acquired = _lock .acquire ()
302317 if lock_acquired :
303- logger .info ("Schedule lock acquired successfully." )
318+ # Write PID to the lock file
319+ current_pid = os .getpid ()
320+ with open (".lock" , "w" ) as lock_file :
321+ lock_file .write (str (current_pid ))
322+ logger .info (f"Schedule lock acquired successfully. PID { current_pid } written to lock file." )
304323 if not no_backup :
305324 logger .info (f"backup_to_s3(format={ format } )" )
306325 backup_to_s3 (format = format )
@@ -317,7 +336,11 @@ def routine(no_backup=False, format="zip"):
317336 else :
318337 logger .warning ("Schedule lock acquired by another process. No need to run it in this process." )
319338 except Timeout :
320- logger .warning ("Schedule lock acquired by another process. No need to run it in this process." )
339+ existing_pid = get_lock_pid ()
340+ if existing_pid :
341+ logger .warning (f"Schedule lock acquired by another process (PID: { existing_pid } ). No need to run it in this process." )
342+ else :
343+ logger .warning ("Schedule lock acquired by another process. No need to run it in this process." )
321344 except Exception as e :
322345 logger .error (f"An error occurred during the routine: { e } " )
323346 logger .error ("Stack trace:" , exc_info = True )
@@ -326,6 +349,20 @@ def routine(no_backup=False, format="zip"):
326349 _lock .release ()
327350 logger .info ("Schedule lock released successfully." )
328351
352+ # Try to delete the .lock file manually if it still exists
353+ lock_file_path = ".lock"
354+ if os .path .exists (lock_file_path ):
355+ try :
356+ # Log the PID that was in the lock file before deletion
357+ existing_pid = get_lock_pid ()
358+ os .remove (lock_file_path )
359+ if existing_pid :
360+ logger .info (f".lock file manually deleted (contained PID: { existing_pid } )." )
361+ else :
362+ logger .info (".lock file manually deleted." )
363+ except Exception as e :
364+ logger .warning (f"Could not delete .lock file: { e } " )
365+
329366
330367if __name__ == "__main__" :
331368 restore_from_s3 ()
0 commit comments