feat: grade open answers through a grader registry in the background

- graders registry collected at boot from every HasGraders plugin,
  manual first; a duplicate or reserved code fails boot
- grading job on queue quizzes_grading with three attempts; a stale
  or reviewed answer is never touched; the last failure marks it failed
- learning answers enqueue at once, tests at close; a grade
  recalculates a finished attempt and fires AnswerGradedEvent after
  commit
This commit is contained in:
Jakub Zych
2026-11-09 17:51:55 +01:00
parent 297780cb8e
commit 80ea79ee3e
12 changed files with 942 additions and 24 deletions

View File

@@ -259,13 +259,9 @@ func (h *Handlers) service(w http.ResponseWriter) (*classes.Service, bool) {
if h.Service != nil {
return h.Service(gdb), true
}
var scoring classes.ScoringConfig
grace := classes.DefaultTestGrace
if h.App != nil {
scoring = classes.ScoringConfigFrom(h.App.Config)
grace = classes.TestGraceFrom(h.App.Config)
}
return &classes.Service{DB: gdb, Scoring: scoring, Grace: grace}, true
// The scoring and grace come from the config as before; ForApp adds
// the grader registry, the job queue and the event bus.
return classes.ForApp(h.App, gdb), true
}
// input decodes a JSON body (an empty body is {}) and validates it. It