diff --git a/notifier/database/drivers/base.py b/notifier/database/drivers/base.py index 2a56c67..8b42ef4 100644 --- a/notifier/database/drivers/base.py +++ b/notifier/database/drivers/base.py @@ -93,7 +93,9 @@ def count_user_configs(self) -> int: """Count the number of subscribed users.""" @abstractmethod - def get_notifiable_users(self, frequency: str) -> List[str]: + def get_notifiable_users( + self, frequency: str, post_lower_timestamp_limit: int + ) -> List[str]: """Get the list of IDs for users subscribed to the given channel frequency who have at least one notification waiting for them. """ diff --git a/notifier/database/drivers/mysql.py b/notifier/database/drivers/mysql.py index 8d71532..1d0c413 100644 --- a/notifier/database/drivers/mysql.py +++ b/notifier/database/drivers/mysql.py @@ -332,9 +332,14 @@ def count_user_configs(self) -> int: )["count"], ) - def get_notifiable_users(self, frequency: str) -> List[str]: + def get_notifiable_users( + self, frequency: str, post_lower_timestamp_limit: int + ) -> List[str]: logger.debug("Caching post context...") - self.execute_named("cache_post_context") + self.execute_named( + "cache_post_context", + {"post_lower_timestamp_limit": post_lower_timestamp_limit}, + ) logger.debug("Retrieving notifiable users users...") user_ids = [ cast(str, row["user_id"]) diff --git a/notifier/database/queries/cache_post_context.sql b/notifier/database/queries/cache_post_context.sql index aaa1ea7..e5abd9e 100644 --- a/notifier/database/queries/cache_post_context.sql +++ b/notifier/database/queries/cache_post_context.sql @@ -20,5 +20,8 @@ WITH cte AS ( WHERE -- Remove deleted threads/posts thread.is_deleted = 0 AND post.is_deleted = 0 + + -- Remove posts from before the notification service started + AND post.posted_timestamp > %(post_lower_timestamp_limit)s ) SELECT * FROM cte \ No newline at end of file diff --git a/notifier/notify.py b/notifier/notify.py index 155d44b..58902f2 100644 --- a/notifier/notify.py +++ b/notifier/notify.py @@ -241,7 +241,7 @@ def notify_channel( # Filter the users only to those with notifications waiting logger.debug("Filtering users without notifications waiting...") user_count_pre_filter = len(user_configs) - notifiable_user_ids = database.get_notifiable_users(channel) + notifiable_user_ids = database.get_notifiable_users(channel, config["service_start_timestamp"]) user_configs = [ user for user in user_configs if user["user_id"] in notifiable_user_ids ] diff --git a/tests/test_database.py b/tests/test_database.py index 6d27bac..df7a3a3 100644 --- a/tests/test_database.py +++ b/tests/test_database.py @@ -456,7 +456,7 @@ def check_timestamp(n: int) -> None: @pytest.mark.needs_database -def test_get_notifiable_users(sample_database: BaseDatabaseDriver) -> None: +def test_get_notifiable_users(sample_database: MySqlDriver) -> None: """Test that the notifiable users list returns the correct set of users. The notifiable users utility lists directly from the database the set of @@ -627,15 +627,18 @@ def test_get_notifiable_users(sample_database: BaseDatabaseDriver) -> None: for post in sample_posts: sample_database.store_post(post) - users_expected_to_have_notifications = { + assert set(sample_database.get_notifiable_users("hourly", 0)) == { "1", # UserR1 from base sample DB "51", # T5U-!P-Sub "53", # T5U-Starter "55", # T5U-Poster } - users_with_notifications = sample_database.get_notifiable_users("hourly") + with sample_database.transaction() as cursor: + cursor.execute("DROP TABLE post_with_context") - assert ( - set(users_with_notifications) == users_expected_to_have_notifications - ) + assert set(sample_database.get_notifiable_users("hourly", 99)) == { + "51", # T5U-!P-Sub + "53", # T5U-Starter + "55", # T5U-Poster + }