11using Microsoft . EntityFrameworkCore ;
2- using OpenShock . Common ;
32using OpenShock . Common . Constants ;
43using OpenShock . Common . OpenShockDb ;
54using OpenShock . Cron . Attributes ;
65
76namespace OpenShock . Cron . Jobs ;
87
98/// <summary>
10- /// Deletes shocker control logs older than the retention period and enforces a maximum log count
9+ /// Deletes shocker control logs by enforcing a maximum log count per user
1110/// </summary>
1211[ CronJob ( "0 0 * * *" ) ] // Every day at midnight (https://crontab.guru/)
1312public sealed class ClearOldShockerControlLogs
@@ -26,35 +25,30 @@ public ClearOldShockerControlLogs(OpenShockContext db, ILogger<ClearOldShockerCo
2625 _logger = logger ;
2726 }
2827
29- public async Task Execute ( )
28+ public async Task < int > Execute ( )
3029 {
31- var userLogsCounts = await _db . ShockerControlLogs
32- . GroupBy ( log => log . Shocker . DeviceNavigation . Owner )
33- . Select ( group => new
34- {
35- UserId = group . Key ,
36- CountToDelete = Math . Max ( 0 , group . Count ( ) - HardLimits . MaxShockerControlLogsPerUser ) ,
37- DeleteBeforeDate = group
38- . OrderByDescending ( log => log . CreatedOn )
39- . Skip ( HardLimits . MaxShockerControlLogsPerUser )
40- . Select ( log => log . CreatedOn )
41- . FirstOrDefault ( )
42- } )
43- . Where ( result => result . CountToDelete > 0 )
44- . ToArrayAsync ( ) ;
30+ var deletedUserLimits = await _db . Database . ExecuteSqlAsync (
31+ $ """
32+ WITH ranked_logs AS (
33+ SELECT
34+ l.id,
35+ ROW_NUMBER() OVER (PARTITION BY u.id ORDER BY l.created_on DESC) AS rn
36+ FROM shocker_control_logs l
37+ JOIN shockers s ON s.id = l.shocker_id
38+ JOIN devices d ON d.id = s.device
39+ JOIN users u ON d.owner = u.id
40+ )
41+ DELETE FROM shocker_control_logs
42+ WHERE id IN (
43+ SELECT id
44+ FROM ranked_logs
45+ WHERE rn > { HardLimits . MaxShockerControlLogsPerUser }
46+ );
47+ """ ) ;
4548
46- if ( userLogsCounts . Length != 0 )
47- {
48- _logger . LogInformation ( "A total of {totalLogsToDelete} logs will be deleted to enforce per-user limits." , userLogsCounts . Sum ( x => x . CountToDelete ) ) ;
49-
50- foreach ( var userLogCount in userLogsCounts )
51- {
52- await _db . ShockerControlLogs
53- . Where ( log => log . Shocker . DeviceNavigation . Owner == userLogCount . UserId && log . CreatedOn < userLogCount . DeleteBeforeDate )
54- . ExecuteDeleteAsync ( ) ;
55- }
56- }
49+ _logger . LogInformation ( "Deleted {deletedUserLimits} shocker control logs exceeding the per-user limit" ,
50+ deletedUserLimits ) ;
5751
58- _logger . LogInformation ( "Done!" ) ;
52+ return deletedUserLimits ;
5953 }
6054}
0 commit comments