1+ import logging
2+
3+ from django .core .management import call_command
4+ from framework .celery_tasks import app as celery_app
5+ from osf .models import Registration
6+ from osf .management .commands .force_archive import archive , DEFAULT_PERMISSIBLE_ADDONS
7+ from scripts .stuck_registration_audit import analyze_failed_registration_nodes
8+
9+ logger = logging .getLogger (__name__ )
10+
11+
12+ @celery_app .task (name = 'scripts.enhanced_stuck_registration_audit' )
13+ def enhanced_stuck_registration_audit ():
14+ logger .info ('Starting enhanced stuck registration audit' )
15+
16+ try :
17+ logger .info ('Processing pending manual restart approvals' )
18+ call_command ('process_manual_restart_approvals' , dry_run = False , hours_back = 72 )
19+ except Exception as e :
20+ logger .error (f"Error processing manual restart approvals: { e } " )
21+
22+ logger .info ('Analyzing failed registrations' )
23+ failed_registrations = analyze_failed_registration_nodes ()
24+
25+ if not failed_registrations :
26+ logger .info ('No failed registrations found' )
27+ return 'No failed registrations found'
28+
29+ logger .info (f"Found { len (failed_registrations )} failed registrations" )
30+
31+ auto_retryable = []
32+ needs_manual_intervention = []
33+
34+ for reg_info in failed_registrations :
35+ registration_id = reg_info ['registration' ]
36+
37+ try :
38+ registration = Registration .objects .get (_id = registration_id )
39+
40+ if should_auto_retry (reg_info , registration ):
41+ auto_retryable .append (registration )
42+ logger .info (f"Registration { registration_id } eligible for auto-retry" )
43+ else :
44+ needs_manual_intervention .append (reg_info )
45+ logger .info (f"Registration { registration_id } needs manual intervention" )
46+
47+ except Registration .DoesNotExist :
48+ logger .warning (f"Registration { registration_id } not found" )
49+ needs_manual_intervention .append (reg_info )
50+ continue
51+
52+ successfully_retried = []
53+ failed_auto_retries = []
54+
55+ for reg in auto_retryable :
56+ try :
57+ logger .info (f"Attempting auto-retry for stuck registration { reg ._id } " )
58+
59+ archive (
60+ reg ,
61+ permissible_addons = DEFAULT_PERMISSIBLE_ADDONS ,
62+ allow_unconfigured = True ,
63+ skip_collisions = True
64+ )
65+
66+ successfully_retried .append (reg ._id )
67+ logger .info (f"Successfully auto-retried registration { reg ._id } " )
68+
69+ except Exception as e :
70+ logger .error (f"Auto-retry failed for registration { reg ._id } : { e } " )
71+ failed_auto_retries .append ({
72+ 'registration' : reg ._id ,
73+ 'auto_retry_error' : str (e ),
74+ 'original_info' : next (info for info in failed_registrations if info ['registration' ] == reg ._id )
75+ })
76+
77+ needs_manual_intervention .extend (failed_auto_retries )
78+
79+ logger .info (f"Auto-retry results: { len (successfully_retried )} successful, { len (failed_auto_retries )} failed" )
80+
81+ summary = {
82+ 'total_failed' : len (failed_registrations ),
83+ 'auto_retried_success' : len (successfully_retried ),
84+ 'auto_retried_failed' : len (failed_auto_retries ),
85+ 'needs_manual' : len (needs_manual_intervention ),
86+ 'successfully_retried_ids' : successfully_retried
87+ }
88+
89+ logger .info (f"Enhanced audit completed: { summary } " )
90+ return summary
91+
92+
93+ def should_auto_retry (reg_info , registration ):
94+ if not reg_info .get ('can_be_reset' , False ):
95+ return False
96+
97+ addon_list = reg_info .get ('addon_list' , [])
98+ complex_addons = set (addon_list ) - {'osfstorage' , 'wiki' }
99+ if complex_addons :
100+ logger .info (f"Registration { registration ._id } has complex addons: { complex_addons } " )
101+ return False
102+
103+ logs_after_reg = reg_info .get ('logs_on_original_after_registration_date' , [])
104+ if logs_after_reg :
105+ logger .info (f"Registration { registration ._id } has post-registration logs: { logs_after_reg } " )
106+ return False
107+
108+ successful_after = reg_info .get ('succeeded_registrations_after_failed' , [])
109+ if successful_after :
110+ logger .info (f"Registration { registration ._id } has successful registrations after failure: { successful_after } " )
111+ return False
112+
113+ import django .utils .timezone as timezone
114+ from datetime import timedelta
115+ if registration .registered_date :
116+ age = timezone .now () - registration .registered_date
117+ if age > timedelta (days = 30 ):
118+ logger .info (f"Registration { registration ._id } is too old ({ age .days } days)" )
119+ return False
120+ return True
121+
122+ @celery_app .task (name = 'scripts.manual_restart_approval_batch' )
123+ def manual_restart_approval_batch ():
124+ logger .info ('Running manual restart approval batch task' )
125+
126+ try :
127+ from scripts .check_manual_restart_approval import check_manual_restart_approvals_batch
128+ result = check_manual_restart_approvals_batch .delay (hours_back = 24 )
129+ return f"Queued manual restart approval batch task: { result .id } "
130+ except Exception as e :
131+ logger .error (f"Error running manual restart approval batch: { e } " )
132+ raise
133+
134+
135+ if __name__ == '__main__' :
136+ result = enhanced_stuck_registration_audit ()
137+ print (f"Audit completed: { result } " )
0 commit comments