22
33import logging
44from datetime import datetime , timedelta
5- from typing import TYPE_CHECKING , Literal
5+ from typing import TYPE_CHECKING , Literal , TypeAlias
66
77from django .contrib .auth import get_user_model
88from django .utils import timezone
1313 from reactpy_django .models import Config
1414
1515CLEAN_NEEDED_BY : datetime = datetime (year = 1 , month = 1 , day = 1 , tzinfo = timezone .now ().tzinfo )
16+ CleaningArgs : TypeAlias = Literal ["all" , "sessions" , "auth_sync" , "user_data" ]
1617
1718
18- def clean (
19- * args : Literal ["all" , "sessions" , "user_data" ],
20- immediate : bool = False ,
21- verbosity : int = 1 ,
22- ):
19+ def clean (* args : CleaningArgs , immediate : bool = False , verbosity : int = 1 ):
2320 from reactpy_django .config import (
21+ REACTPY_CLEAN_AUTH_SYNC ,
2422 REACTPY_CLEAN_SESSIONS ,
2523 REACTPY_CLEAN_USER_DATA ,
2624 )
2725 from reactpy_django .models import Config
2826
2927 config = Config .load ()
30- if immediate or is_clean_needed (config ):
28+ if immediate or clean_is_needed (config ):
3129 config .cleaned_at = timezone .now ()
3230 config .save ()
3331 sessions = REACTPY_CLEAN_SESSIONS
32+ auth_sync = REACTPY_CLEAN_AUTH_SYNC
3433 user_data = REACTPY_CLEAN_USER_DATA
3534
3635 if args :
3736 sessions = any (value in args for value in ("sessions" , "all" ))
37+ auth_sync = any (value in args for value in ("auth_sync" , "all" ))
3838 user_data = any (value in args for value in ("user_data" , "all" ))
3939
4040 if sessions :
41- clean_sessions (verbosity )
41+ clean_component_sessions (verbosity )
42+ if auth_sync :
43+ clean_auth_synchronizer (verbosity )
4244 if user_data :
4345 clean_user_data (verbosity )
4446
4547
46- def clean_sessions (verbosity : int = 1 ):
48+ def clean_component_sessions (verbosity : int = 1 ):
4749 """Deletes expired component sessions from the database.
4850 As a performance optimization, this is only run once every REACTPY_SESSION_MAX_AGE seconds.
4951 """
@@ -67,6 +69,25 @@ def clean_sessions(verbosity: int = 1):
6769 inspect_clean_duration (start_time , "component sessions" , verbosity )
6870
6971
72+ def clean_auth_synchronizer (verbosity : int = 1 ):
73+ from reactpy_django .config import DJANGO_DEBUG , REACTPY_AUTH_SYNC_TIMEOUT
74+ from reactpy_django .models import SynchronizeSession
75+
76+ if verbosity >= 2 :
77+ _logger .info ("Cleaning ReactPy auth sync data..." )
78+ start_time = timezone .now ()
79+ expiration_date = timezone .now () - timedelta (seconds = REACTPY_AUTH_SYNC_TIMEOUT )
80+ synchronizer_objects = SynchronizeSession .objects .filter (created_at__lte = expiration_date )
81+
82+ if verbosity >= 2 :
83+ _logger .info ("Deleting %d expired auth sync objects..." , synchronizer_objects .count ())
84+
85+ synchronizer_objects .delete ()
86+
87+ if DJANGO_DEBUG or verbosity >= 2 :
88+ inspect_clean_duration (start_time , "auth sync" , verbosity )
89+
90+
7091def clean_user_data (verbosity : int = 1 ):
7192 """Delete any user data that is not associated with an existing `User`.
7293 This is a safety measure to ensure that we don't have any orphaned data in the database.
@@ -101,7 +122,7 @@ def clean_user_data(verbosity: int = 1):
101122 inspect_clean_duration (start_time , "user data" , verbosity )
102123
103124
104- def is_clean_needed (config : Config | None = None ) -> bool :
125+ def clean_is_needed (config : Config | None = None ) -> bool :
105126 """Check if a clean is needed. This function avoids unnecessary database reads by caching the
106127 CLEAN_NEEDED_BY date."""
107128 from reactpy_django .config import REACTPY_CLEAN_INTERVAL
0 commit comments