Class JudgeJobTransactions

java.lang.Object
dev.dokimos.server.service.JudgeJobTransactions

@Component public class JudgeJobTransactions extends Object
The transactional steps of the judge worker, each in its own committed transaction so the worker can make the LLM HTTP call between them without holding a database transaction open. Splitting these out of the worker also makes REQUIRES_NEW boundaries effective, since self-invocation would otherwise bypass the proxy.
  • Constructor Details

  • Method Details

    • recoverStaleClaims

      @Transactional(propagation=REQUIRES_NEW) public int recoverStaleClaims(Instant cutoff)
      Returns jobs orphaned by a crashed worker (claimed before the cutoff and never finished) to PENDING so the next poll can reclaim them. The attempt count is left as-is, so the retry ceiling still bounds reclaims.
      Parameters:
      cutoff - jobs claimed before this instant are requeued
      Returns:
      the number of jobs requeued
    • claimNextJob

      @Transactional(propagation=REQUIRES_NEW) public Optional<EvalJob> claimNextJob(int maxAttempts)
      Claims the oldest pending job below the retry ceiling: locks its row, marks it CLAIMED, stamps the claim time, and increments the attempt count. Commits before returning so the lock is not held during the HTTP work that follows.
      Parameters:
      maxAttempts - the retry ceiling
      Returns:
      the claimed job, or empty if none is available
    • loadUnevaluatedPage

      @Transactional(readOnly=true, propagation=REQUIRES_NEW) public List<JudgeJobTransactions.ItemSnapshot> loadUnevaluatedPage(UUID runId, String evaluatorName, UUID afterId, int pageSize)
      Reads a seek-keyed page of items that have no result yet for the job's evaluator. Returns plain snapshots so the worker can score them after the transaction closes without touching detached entities.
      Parameters:
      runId - the run whose items to scan
      evaluatorName - the evaluator whose results gate the scan
      afterId - the seek cursor; the all-zero UUID for the first page
      pageSize - the maximum number of items to return
      Returns:
      the next page of unevaluated item snapshots, ordered by id
    • persistPage

      @Transactional(propagation=REQUIRES_NEW) public void persistPage(UUID jobId, List<JudgeJobTransactions.ScoredResult> results, UUID lastItemId)
      Persists a page of eval results and advances the job's seek cursor in one transaction.
      Parameters:
      jobId - the job being processed
      results - the eval results to attach to their item results
      lastItemId - the id of the last item scored in this page
    • markSucceeded

      @Transactional(propagation=REQUIRES_NEW) public void markSucceeded(UUID jobId, UUID runId)
      Marks the job SUCCEEDED and finalizes its run (re-materializes counts, moves the run to SUCCESS).
      Parameters:
      jobId - the job that finished scoring
      runId - the run to finalize
    • recordFailure

      @Transactional(propagation=REQUIRES_NEW) public void recordFailure(UUID jobId, String error, boolean retryable, int maxAttempts)
      Records a failure. When the failure is retryable and the attempt ceiling has not been reached, the job is returned to PENDING for a later poll; otherwise it is marked FAILED.
      Parameters:
      jobId - the job that failed
      error - the error message to record
      retryable - whether the failure is worth retrying
      maxAttempts - the retry ceiling