mirror of
https://github.com/Casvt/MIND.git
synced 2026-02-19 11:54:46 -05:00
Refactored reminder_handler.py
This commit is contained in:
5
MIND.py
5
MIND.py
@@ -89,8 +89,7 @@ def _main(
|
||||
|
||||
settings = s.get_settings()
|
||||
|
||||
reminder_handler = ReminderHandler()
|
||||
reminder_handler.find_next_reminder()
|
||||
ReminderHandler.set_reminder_timer()
|
||||
|
||||
DatabaseBackupHandler.set_backup_timer()
|
||||
|
||||
@@ -106,7 +105,7 @@ def _main(
|
||||
# =================
|
||||
|
||||
finally:
|
||||
reminder_handler.stop_handling()
|
||||
ReminderHandler.stop_reminder_timer()
|
||||
DatabaseBackupHandler.stop_backup_timer()
|
||||
tz_change_handler.stop_detector_timer()
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ from datetime import datetime
|
||||
from typing import TYPE_CHECKING, Union
|
||||
|
||||
from backend.base.definitions import Constants, RepeatQuantity, SendResult
|
||||
from backend.base.helpers import Singleton, find_next_time, when_not_none
|
||||
from backend.base.helpers import find_next_time, when_not_none
|
||||
from backend.base.logging import LOGGER
|
||||
from backend.implementations.reminders import Reminder
|
||||
from backend.internals.db_models import UserlessRemindersDB
|
||||
@@ -16,48 +16,43 @@ if TYPE_CHECKING:
|
||||
from threading import Timer
|
||||
|
||||
|
||||
class ReminderHandler(metaclass=Singleton):
|
||||
class ReminderHandler:
|
||||
"""
|
||||
Handle set reminders. This class is a singleton.
|
||||
Handling of the reminders such that they are sent at their scheduled time.
|
||||
"""
|
||||
|
||||
def __init__(self) -> None:
|
||||
"Create instance of handler"
|
||||
self.thread: Union[Timer, None] = None
|
||||
self.time: Union[int, None] = None
|
||||
self.reminder_db = UserlessRemindersDB()
|
||||
return
|
||||
reminder_timer: Union[Timer, None] = None
|
||||
next_trigger_time: Union[int, None] = None
|
||||
reminder_db = UserlessRemindersDB()
|
||||
|
||||
def __trigger_reminders(self, time: int) -> None:
|
||||
@classmethod
|
||||
def _trigger_reminders(cls, time: int) -> None:
|
||||
"""Trigger all reminders that are set for a certain time.
|
||||
|
||||
Args:
|
||||
time (int): The time of the reminders to trigger.
|
||||
"""
|
||||
for reminder in self.reminder_db.fetch(time):
|
||||
for reminder in cls.reminder_db.fetch(time):
|
||||
try:
|
||||
user_id = self.reminder_db.reminder_id_to_user_id(
|
||||
user_id = cls.reminder_db.reminder_id_to_user_id(
|
||||
reminder.id
|
||||
)
|
||||
result = Reminder(user_id, reminder.id).trigger_reminder()
|
||||
|
||||
self.thread = None
|
||||
self.time = None
|
||||
|
||||
if result == SendResult.CONNECTION_ERROR:
|
||||
# Retry sending the notification in a few minutes
|
||||
self.reminder_db.update(
|
||||
cls.reminder_db.shift(
|
||||
reminder.id,
|
||||
time + Constants.CONNECTION_ERROR_TIMEOUT
|
||||
Constants.CONNECTION_ERROR_TIMEOUT
|
||||
)
|
||||
|
||||
elif (
|
||||
elif not any((
|
||||
reminder.repeat_quantity,
|
||||
reminder.weekdays,
|
||||
reminder.cron_schedule
|
||||
) == (None, None, None):
|
||||
)):
|
||||
# Delete the reminder from the database
|
||||
self.reminder_db.delete(reminder.id)
|
||||
cls.reminder_db.delete(reminder.id)
|
||||
|
||||
else:
|
||||
# Set next time
|
||||
@@ -72,7 +67,7 @@ class ReminderHandler(metaclass=Singleton):
|
||||
reminder.cron_schedule
|
||||
)
|
||||
|
||||
self.reminder_db.update(reminder.id, new_time)
|
||||
cls.reminder_db.update(reminder.id, new_time)
|
||||
|
||||
except Exception:
|
||||
# If the notification fails, we don't want to crash the whole program
|
||||
@@ -83,48 +78,55 @@ class ReminderHandler(metaclass=Singleton):
|
||||
)
|
||||
|
||||
finally:
|
||||
self.find_next_reminder()
|
||||
cls.reminder_timer = None
|
||||
cls.next_trigger_time = None
|
||||
cls.set_reminder_timer()
|
||||
|
||||
return
|
||||
|
||||
def find_next_reminder(self, time: Union[int, None] = None) -> None:
|
||||
"""Determine when the soonest reminder is and set the timer to that time.
|
||||
@classmethod
|
||||
def set_reminder_timer(cls, time: Union[int, None] = None) -> None:
|
||||
"""Update the timer for sending the soonest upcoming reminder. Start one
|
||||
if it hasn't already. Replace it if it does already exist, in case the
|
||||
time the soonest reminder triggers has changed.
|
||||
|
||||
Args:
|
||||
time (Union[int, None], optional): The timestamp to check for.
|
||||
Otherwise check soonest in database.
|
||||
time (Union[int, None], optional): Check whether the given timestamp
|
||||
changes anything to the situation. If not given, the soonest
|
||||
timestamp in the database is checked.
|
||||
|
||||
Defaults to None.
|
||||
"""
|
||||
if time is None:
|
||||
time = self.reminder_db.get_soonest_time()
|
||||
time = cls.reminder_db.get_soonest_time()
|
||||
if not time:
|
||||
return
|
||||
|
||||
if (
|
||||
self.thread is None
|
||||
cls.reminder_timer is None
|
||||
or (
|
||||
self.time is not None
|
||||
and time < self.time
|
||||
cls.next_trigger_time is not None
|
||||
and time < cls.next_trigger_time
|
||||
)
|
||||
):
|
||||
if self.thread is not None:
|
||||
self.thread.cancel()
|
||||
if cls.reminder_timer is not None:
|
||||
cls.reminder_timer.cancel()
|
||||
|
||||
delta_t = time - datetime.utcnow().timestamp()
|
||||
self.thread = Server().get_db_timer_thread(
|
||||
cls.reminder_timer = Server().get_db_timer_thread(
|
||||
delta_t,
|
||||
self.__trigger_reminders,
|
||||
cls._trigger_reminders,
|
||||
"ReminderHandler",
|
||||
args=(time,)
|
||||
)
|
||||
self.thread.start()
|
||||
self.time = time
|
||||
cls.reminder_timer.start()
|
||||
cls.next_trigger_time = time
|
||||
|
||||
return
|
||||
|
||||
def stop_handling(self) -> None:
|
||||
"""Stop the timer if it's active
|
||||
"""
|
||||
if self.thread is not None:
|
||||
self.thread.cancel()
|
||||
@classmethod
|
||||
def stop_reminder_timer(cls) -> None:
|
||||
"If the reminder timer is running, stop it"
|
||||
if cls.reminder_timer is not None:
|
||||
cls.reminder_timer.cancel()
|
||||
return
|
||||
|
||||
@@ -73,7 +73,7 @@ class TimezoneChangeHandler(metaclass=Singleton):
|
||||
offset=shift_delta
|
||||
)
|
||||
settings.update({"measured_timezone": current_timezone})
|
||||
ReminderHandler().find_next_reminder()
|
||||
ReminderHandler.set_reminder_timer()
|
||||
LOGGER.info(
|
||||
"Detected timezone/DST change (%s to %s), shifted reminders",
|
||||
measured_timezone, current_timezone
|
||||
|
||||
@@ -244,7 +244,7 @@ class Reminder:
|
||||
data["enabled"]
|
||||
)
|
||||
|
||||
ReminderHandler().find_next_reminder(next_time)
|
||||
ReminderHandler.set_reminder_timer(next_time)
|
||||
return self.get()
|
||||
|
||||
def delete(self) -> None:
|
||||
@@ -253,7 +253,7 @@ class Reminder:
|
||||
|
||||
LOGGER.info(f'Deleting reminder {self.id}')
|
||||
self.reminder_db.delete(self.id)
|
||||
ReminderHandler().find_next_reminder()
|
||||
ReminderHandler.set_reminder_timer()
|
||||
return
|
||||
|
||||
|
||||
@@ -456,7 +456,7 @@ class Reminders:
|
||||
enabled
|
||||
)
|
||||
|
||||
ReminderHandler().find_next_reminder(time)
|
||||
ReminderHandler.set_reminder_timer(time)
|
||||
|
||||
return self.get_one(new_id)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user