@@ -338,6 +338,44 @@ class CourseService(
338
338
submissionRepository.saveAndFlush(submission)
339
339
}
340
340
341
+ // only necessary once to prune existing data in already-deployed ACCESS
342
+ fun globalPruneSubmissions () {
343
+ evaluationRepository.findAll().forEach { if (it != null ) {pruneSubmissions(it) } }
344
+ }
345
+
346
+ fun pruneSubmissions (evaluation : Evaluation ) {
347
+ // keep all GRADE submissions, but prune RUN and TEST submissions
348
+ listOf (Command .RUN , Command .TEST , Command .GRADE ).map { command ->
349
+ Pair (command, evaluation.submissions.filter { it.command == command }.sortedByDescending { it.ordinalNum })
350
+ }.filter { it.second.isNotEmpty() }.forEach { (command, submissions) ->
351
+ val latest = submissions.first().ordinalNum!!
352
+ // always keep the latest 5
353
+ val keepOrdinalNums = submissions.take(5 ).map { it.ordinalNum!! }.toMutableSet()
354
+ // always keep the (latest) best GRADE submission
355
+ if (command == Command .GRADE ) {
356
+ val best = submissions.maxWith(compareBy<Submission > { it.points }.thenBy { it.ordinalNum })
357
+ keepOrdinalNums.add(best.ordinalNum!! )
358
+ }
359
+ // keep increasingly fewer submissions the older they are (none older than 100 submissions ago)
360
+ var low = 5
361
+ listOf (10 , 15 , 25 , 50 , 75 , 100 ).forEach { high ->
362
+ // find oldest in current low < distance_to_latest <= high bracket
363
+ val highestOrdinalNum = submissions.lastOrNull {
364
+ val distance = latest - it.ordinalNum!!
365
+ distance in low.. < high
366
+ }?.ordinalNum
367
+ if (highestOrdinalNum != null ) {
368
+ keepOrdinalNums.add(highestOrdinalNum)
369
+ }
370
+ low = high
371
+ }
372
+ val prune = submissions.filter { ! keepOrdinalNums.contains(it.ordinalNum!! ) }
373
+ evaluation.submissions.removeAll(prune)
374
+ submissionRepository.deleteAll(prune)
375
+ logger.debug { " -->> Pruning ${evaluation.userId} /${evaluation.task?.assignment?.slug} /${evaluation.task?.slug} [${command} ]: ${prune.map{it.ordinalNum}} " }
376
+ }
377
+ }
378
+
341
379
@Caching(evict = [
342
380
CacheEvict (value = [" getStudent" ], key = " #courseSlug + '-' + #submissionDTO.userId" ),
343
381
CacheEvict (value = [" getStudentWithPoints" ], key = " #courseSlug + '-' + #submissionDTO.userId" ),
@@ -366,6 +404,7 @@ class CourseService(
366
404
)
367
405
}
368
406
val submission = submissionRepository.saveAndFlush(newSubmission)
407
+ pruneSubmissions(evaluation)
369
408
submissionDTO.files.stream().filter { fileDTO -> fileDTO.content != null }
370
409
.forEach { fileDTO: SubmissionFileDTO -> createSubmissionFile(submission, fileDTO) }
371
410
submission.valid = ! submission.isGraded
0 commit comments