Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
2 / 2
CRAP
100.00% covered (success)
100.00%
1 / 1
RecoverableSigningJob
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
2 / 2
3
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 executeSigning
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
2
1<?php
2
3declare(strict_types=1);
4/**
5 * SPDX-FileCopyrightText: 2026 LibreCode coop and contributors
6 * SPDX-License-Identifier: AGPL-3.0-or-later
7 */
8
9namespace OCA\Libresign\BackgroundJob;
10
11use OCA\Libresign\Service\SigningAttemptGuard;
12use OCP\AppFramework\Utility\ITimeFactory;
13use OCP\BackgroundJob\IJobList;
14use OCP\BackgroundJob\Job;
15
16/**
17 * Unlike QueuedJob, retain the job until the coordinator returns.
18 * A crash leaves it reserved for Nextcloud's normal recovery window.
19 */
20abstract class RecoverableSigningJob extends Job {
21    public function __construct(
22        ITimeFactory $time,
23        private IJobList $jobList,
24        private SigningAttemptGuard $attemptGuard,
25    ) {
26        parent::__construct($time);
27    }
28
29    protected function executeSigning(array $argument, callable $sign, callable $discardCredentials): void {
30        // Nextcloud may use one service object for several job IDs. Preserve our
31        // reservation ID before any other IJobList call changes that object.
32        $jobId = $this->getId();
33        $executed = $this->attemptGuard->execute($argument, $jobId, $sign);
34        if (!$executed) {
35            $discardCredentials();
36        }
37        // Remove only after a controlled return, never before signing starts.
38        $this->jobList->removeById($jobId);
39    }
40}