1010
1111import jakarta .transaction .Transactional ;
1212import lombok .extern .slf4j .Slf4j ;
13- import org .springframework .scheduling .annotation .Scheduled ;
14- import org .springframework .stereotype .Component ;
13+ import org .springframework .beans .factory .annotation .Value ;
14+ import org .springframework .http .HttpStatus ;
15+ import org .springframework .http .ResponseEntity ;
16+ import org .springframework .web .bind .annotation .PostMapping ;
17+ import org .springframework .web .bind .annotation .RequestHeader ;
18+ import org .springframework .web .bind .annotation .RequestMapping ;
19+ import org .springframework .web .bind .annotation .RestController ;
20+ import org .springframework .web .server .ResponseStatusException ;
1521
1622import java .time .LocalDateTime ;
1723import java .util .List ;
1824
19- @ Component
25+ @ RestController
26+ @ RequestMapping ("/api/cron" )
2027@ Slf4j
2128public class JobScheduler {
2229
@@ -28,6 +35,9 @@ public class JobScheduler {
2835
2936 private final PasswordResetTokenRepository passwordTokenRepo ;
3037 private final VerificationTokenRepository verificationTokenRepo ;
38+
39+ @ Value ("${app.cron.secret}" )
40+ private String expectedCronSecret ;
3141
3242 public JobScheduler (JobService jobService ,
3343 UserRepository userRepository ,
@@ -44,66 +54,77 @@ public JobScheduler(JobService jobService,
4454 }
4555
4656 /**
47- * Daily Maintenance: Rejects stale applications (>60 days) .
48- * Runs at Midnight UTC .
57+ * Daily Maintenance Endpoint: Replaces all internal @Scheduled jobs .
58+ * Validates the X-Cron-Secret header and executes jobs sequentially .
4959 */
50- @ Scheduled (cron = "0 0 0 * * *" )
51- public void runStaleJobCleanup () {
52- log .info ("Maintenance: Starting stale job cleanup..." );
60+ @ PostMapping ("/daily-maintenance" )
61+ @ Transactional
62+ public ResponseEntity <String > runDailyMaintenance (@ RequestHeader (value = "X-Cron-Secret" , required = false ) String cronSecret ) {
63+ if (cronSecret == null || !cronSecret .equals (expectedCronSecret )) {
64+ log .warn ("Unauthorized access attempt to daily-maintenance cron endpoint" );
65+ throw new ResponseStatusException (HttpStatus .UNAUTHORIZED , "Invalid cron secret" );
66+ }
67+
68+ log .info ("Starting Daily Maintenance cron jobs..." );
69+
70+ try {
71+ runStaleJobCleanup ();
72+ renewGmailWatches ();
73+ runSystemCleanup ();
74+ processScheduledDeletions ();
75+
76+ log .info ("Daily Maintenance cron jobs completed successfully." );
77+ return ResponseEntity .ok ("Maintenance completed successfully." );
78+ } catch (Exception e ) {
79+ log .error ("Error during daily maintenance execution: {}" , e .getMessage (), e );
80+ throw new ResponseStatusException (HttpStatus .INTERNAL_SERVER_ERROR , "Maintenance failed" );
81+ }
82+ }
83+
84+ private void runStaleJobCleanup () {
85+ log .info ("Maintenance Step 1: Starting stale job cleanup..." );
5386 try {
5487 jobService .cleanupStaleApplications ();
55- log .info ("Maintenance: Stale job cleanup completed." );
88+ log .info ("Maintenance Step 1 : Stale job cleanup completed." );
5689 } catch (Exception e ) {
57- log .error ("Maintenance Error: Stale job cleanup failed: {}" , e .getMessage ());
90+ log .error ("Maintenance Step 1 Error: Stale job cleanup failed: {}" , e .getMessage ());
5891 }
5992 }
6093
61- /**
62- * Gmail Security: Renews the 7-day watch lease every 5 days.
63- */
64- @ Scheduled (cron = "0 30 0 */5 * *" )
65- public void renewGmailWatches () {
66- log .info ("Gmail Sync: Starting bulk watch renewal..." );
94+ private void renewGmailWatches () {
95+ log .info ("Maintenance Step 2: Starting bulk watch renewal..." );
6796
6897 List <User > users = userRepository .findByGmailConnectedTrue ();
6998
7099 if (users .isEmpty ()) {
71- log .info ("Gmail Sync : No connected users found for renewal." );
100+ log .info ("Maintenance Step 2 : No connected users found for renewal." );
72101 return ;
73102 }
74103
75104 users .parallelStream ().forEach (user -> {
76105 try {
77106 gmailIntegrationService .renewWatch (user );
78107 } catch (Exception e ) {
79- log .error ("Gmail Sync Error: Renewal failed for {}: {}" , user .getEmail (), e .getMessage ());
108+ log .error ("Maintenance Step 2 Error: Renewal failed for {}: {}" , user .getEmail (), e .getMessage ());
80109 }
81110 });
82111
83- log .info ("Gmail Sync : Finished bulk watch renewal for {} users." , users .size ());
112+ log .info ("Maintenance Step 2 : Finished bulk watch renewal for {} users." , users .size ());
84113 }
85114
86- @ Scheduled (cron = "0 0 1 * * *" )
87- @ Transactional
88- public void runSystemCleanup () {
89- log .info ("Starting system-wide security cleanup..." );
115+ private void runSystemCleanup () {
116+ log .info ("Maintenance Step 3: Starting system-wide security cleanup..." );
90117 LocalDateTime now = LocalDateTime .now ();
91118
92119 passwordTokenRepo .deleteAllExpired (now );
93-
94120 verificationTokenRepo .deleteAllExpired (now );
95-
96121 userRepository .deleteUnverifiedUsers (now .minusDays (3 ));
97122
98- log .info ("System cleanup completed. Database pruned of expired security entries." );
123+ log .info ("Maintenance Step 3: System cleanup completed. Database pruned of expired security entries." );
99124 }
100125
101- /*
102- * Scheduled task to process user deletions after the 3-day grace period.
103- */
104- @ Scheduled (cron = "0 30 1 * * *" )
105- public void processScheduledDeletions () {
106- log .info ("Starting scheduled user deletion cleanup..." );
126+ private void processScheduledDeletions () {
127+ log .info ("Maintenance Step 4: Starting scheduled user deletion cleanup..." );
107128
108129 List <User > usersToDelete = userRepository .findAllByPendingDeletionTrueAndDeletionRequestedAtBefore (
109130 LocalDateTime .now ().minusDays (3 )
@@ -113,10 +134,10 @@ public void processScheduledDeletions() {
113134 try {
114135 userDeletionService .deleteUserCompletely (user .getEmail ());
115136 } catch (Exception e ) {
116- log .error ("Failed to delete user: {}" , user .getEmail (), e );
137+ log .error ("Maintenance Step 4 Error: Failed to delete user: {}" , user .getEmail (), e );
117138 }
118139 }
119140
120- log .info ("Scheduled deletion cleanup completed. Deleted {} users." , usersToDelete .size ());
141+ log .info ("Maintenance Step 4: Scheduled deletion cleanup completed. Deleted {} users." , usersToDelete .size ());
121142 }
122143}
0 commit comments