import logging from datetime import datetime, timedelta from threading import Timer from time import sleep import pytz # Provides a timed cleanup of the spot list. class CleanupTimer: # Constructor def __init__(self, spots, alerts, cleanup_interval): self.spots = spots self.alerts = alerts self.cleanup_interval = cleanup_interval self.cleanup_timer = None self.last_cleanup_time = datetime.min.replace(tzinfo=pytz.UTC) self.status = "Starting" # Start the cleanup timer def start(self): self.cleanup() # Stop any threads and prepare for application shutdown def stop(self): self.cleanup_timer.cancel() # Perform cleanup and reschedule next timer def cleanup(self): try: # Perform cleanup self.spots.expire() self.alerts.expire() # Alerts can persist in the system for a while, so we want to explicitly clean up any alerts that have # definitively ended, or if they have no definite end time, then if the start time was more than 24 hours # ago. for id in list(self.alerts.iterkeys()): alert = self.alerts[id] if (alert.end_time and alert.end_time < datetime.now(pytz.UTC).timestamp()) or ( not alert.end_time and alert.start_time < (datetime.now( pytz.UTC) - timedelta(days=1)).timestamp()): self.alerts.evict(id) self.status = "OK" self.last_cleanup_time = datetime.now(pytz.UTC) except Exception as e: self.status = "Error" logging.exception("Exception in Cleanup thread") sleep(1) self.cleanup_timer = Timer(self.cleanup_interval, self.cleanup) self.cleanup_timer.start()