Skip to content

Commit 68de5bd

Browse files
authored
Merge pull request #9 from itk-dev/feature/queue-submission-relation-cleanup
Feature/queue submission relation cleanup
2 parents c4b327e + e98e0cd commit 68de5bd

File tree

8 files changed

+175
-18
lines changed

8 files changed

+175
-18
lines changed

config/install/views.view.os2forms_failed_jobs.yml

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,7 @@ display:
313313
element_wrapper_type: ''
314314
element_wrapper_class: ''
315315
element_default_classes: true
316-
empty: aaa
316+
empty: Queued/Waiting
317317
hide_empty: false
318318
empty_zero: false
319319
hide_alter_empty: true
@@ -582,7 +582,7 @@ display:
582582
exclude: false
583583
alter:
584584
alter_text: true
585-
text: "{% if state == 'Queued' %}\r\n{{ state }}\r\n{% else %}\r\n{{ retry_operation }}\r\n{% endif %}"
585+
text: "{% if state == 'Error' or state == 'Fejl' %}\r\n{{ retry_operation }}\r\n{% else %}\r\n{{ state }}\r\n{% endif %}"
586586
make_link: false
587587
path: ''
588588
absolute: false
@@ -615,7 +615,7 @@ display:
615615
element_wrapper_type: ''
616616
element_wrapper_class: ''
617617
element_default_classes: true
618-
empty: aaa
618+
empty: Queued/Waiting
619619
hide_empty: false
620620
empty_zero: false
621621
hide_alter_empty: false
@@ -801,6 +801,45 @@ display:
801801
default_group: All
802802
default_group_multiple: { }
803803
group_items: { }
804+
webform_submission_serial_exists:
805+
id: webform_submission_serial_exists
806+
table: advancedqueue
807+
field: webform_submission_serial_exists
808+
relationship: none
809+
group_type: group
810+
admin_label: ''
811+
plugin_id: advancedqueue_job_submission_exists
812+
operator: '!='
813+
value: '0'
814+
group: 1
815+
exposed: false
816+
expose:
817+
operator_id: ''
818+
label: ''
819+
description: ''
820+
use_operator: false
821+
operator: ''
822+
operator_limit_selection: false
823+
operator_list: { }
824+
identifier: ''
825+
required: false
826+
remember: false
827+
multiple: false
828+
remember_roles:
829+
authenticated: authenticated
830+
placeholder: ''
831+
is_grouped: false
832+
group_info:
833+
label: ''
834+
description: ''
835+
identifier: ''
836+
optional: true
837+
widget: select
838+
multiple: false
839+
remember: false
840+
default_group: All
841+
default_group_multiple: { }
842+
group_items: { }
804843
style:
805844
type: table
806845
row:

os2forms_failed_jobs.module

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
* Hooks related to os2forms failed jobs module.
66
*/
77

8+
use Drupal\os2forms_failed_jobs\Helper\Helper;
9+
use Drupal\webform\WebformSubmissionInterface;
10+
811
/**
912
* Implements hook_views_data().
1013
*
@@ -70,3 +73,10 @@ function os2forms_failed_jobs_views_data(): array {
7073

7174
return $data;
7275
}
76+
77+
/**
78+
* Implements hook_ENTITY_TYPE_delete().
79+
*/
80+
function os2forms_failed_jobs_webform_submission_delete(WebformSubmissionInterface $submission): void {
81+
Drupal::service(Helper::class)->cleanUp($submission);
82+
}

src/Commands/Os2formsFailedJobsCommands.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,14 @@ public function import(): void {
3636
$this->helper->handleImport();
3737
}
3838

39+
/**
40+
* Remove entries from os2forms_failed_jobs_queue_submission_relation.
41+
*
42+
* @command os2forms_failed_jobs:remove-detached-relations
43+
*/
44+
public function removeDetachedRelations(): void {
45+
$relations = $this->helper->getDetachedQueueSubmissionRelations();
46+
$this->helper->removeRelations($relations);
47+
}
48+
3949
}

src/Controller/Controller.php

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,9 +92,16 @@ public function jobMessage(): array {
9292
$jobId = $this->requestStack->getCurrentRequest()->get('job_id');
9393
$job = $this->helper->getJobFromId($jobId);
9494

95+
if (empty($job)) {
96+
$message = $this->t('Job not found');
97+
}
98+
else {
99+
$message = $job->getMessage();
100+
}
101+
95102
$renderArray['content'] = [
96103
'#type' => 'markup',
97-
'#markup' => '<p>' . $job->getMessage() . '</p>',
104+
'#markup' => '<p>' . $message . '</p>',
98105
];
99106

100107
return $renderArray;

src/Form/RetryJob.php

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,11 @@ public function getFormId(): string {
5757
*/
5858
public function getQuestion(): TranslatableMarkup {
5959
$job = $this->helper->getJobFromId((string) $this->jobId);
60+
61+
if (empty($job)) {
62+
return $this->t('Job not found');
63+
}
64+
6065
$webformId = $this->helper->getWebformIdFromQueue($job->getId());
6166

6267
return $this->t('Are you sure you want to retry queue job related to Webform: @webformId, Submission id: @serialId', [
@@ -94,22 +99,22 @@ public function buildForm(array $form, FormStateInterface $form_state, int $job_
9499
*/
95100
public function submitForm(array &$form, FormStateInterface $form_state): void {
96101
$job = $this->helper->getJobFromId((string) $this->jobId);
97-
$queue_id = $job->getQueueId();
102+
if (!empty($job)) {
103+
$queue_id = $job->getQueueId();
98104

99-
$queue_storage = $this->entityTypeManager->getStorage('advancedqueue_queue');
100-
/** @var \Drupal\advancedqueue\Entity\QueueInterface $queue */
101-
$queue = $queue_storage->load($queue_id);
105+
$queue_storage = $this->entityTypeManager->getStorage('advancedqueue_queue');
106+
/** @var \Drupal\advancedqueue\Entity\QueueInterface $queue */
107+
$queue = $queue_storage->load($queue_id);
102108

103-
$queue_backend = $queue->getBackend();
104-
if ($queue_backend instanceof Database) {
105-
$job = $this->helper->getJobFromId((string) $this->jobId);
109+
$queue_backend = $queue->getBackend();
110+
if ($queue_backend instanceof Database) {
111+
if ($job->getState() != Job::STATE_FAILURE) {
112+
throw new \InvalidArgumentException('Only failed jobs can be retried.');
113+
}
106114

107-
if ($job->getState() != Job::STATE_FAILURE) {
108-
throw new \InvalidArgumentException('Only failed jobs can be retried.');
115+
$queue_backend->retryJob($job);
116+
$form_state->setRedirectUrl($this->getCancelUrl());
109117
}
110-
111-
$queue_backend->retryJob($job);
112-
$form_state->setRedirectUrl($this->getCancelUrl());
113118
}
114119
}
115120

src/Helper/Helper.php

Lines changed: 82 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
use Drupal\Core\Entity\EntityInterface;
1010
use Drupal\Core\Entity\EntityTypeManager;
1111
use Drupal\Core\Logger\LoggerChannelFactory;
12+
use Drupal\webform\WebformSubmissionInterface;
1213

1314
/**
1415
* Helper for managing failed jobs.
@@ -37,15 +38,18 @@ public function __construct(
3738
* @param string $jobId
3839
* The job id.
3940
*
40-
* @return \Drupal\advancedqueue\Job
41+
* @return \Drupal\advancedqueue\Job|null
4142
* A list of attributes related to a job.
4243
*/
43-
public function getJobFromId(string $jobId): Job {
44+
public function getJobFromId(string $jobId): Job|NULL {
4445
$query = $this->connection->select('advancedqueue', 'a');
4546
$query->fields('a');
4647
$query->condition('job_id', $jobId, '=');
4748
$definition = $query->execute()->fetchAssoc();
4849

50+
if (empty($definition)) {
51+
return NULL;
52+
}
4953
// Match Job constructor id.
5054
$definition['id'] = $definition['job_id'];
5155

@@ -66,6 +70,9 @@ public function getJobFromId(string $jobId): Job {
6670
*/
6771
public function getSubmissionIdFromJob(string $jobId): ?int {
6872
$job = $this->getJobFromId($jobId);
73+
if (empty($job)) {
74+
return NULL;
75+
}
6976
$payload = $job->getPayload();
7077

7178
return $payload['submissionId'] ?? $payload['submission']['id'] ?? NULL;
@@ -257,6 +264,64 @@ public function getDataFromJob(Job $job): ?array {
257264
}
258265
}
259266

267+
/**
268+
* Get a list of queue submission relations without existing submission.
269+
*
270+
* @param string|null $submissionId
271+
* A specific webform submission id.
272+
*
273+
* @return array
274+
* A list of queue submission relations.
275+
*
276+
* @phpstan-return array<string, mixed>
277+
*/
278+
public function getDetachedQueueSubmissionRelations(string $submissionId = NULL): array {
279+
$query = $this->connection->select('os2forms_failed_jobs_queue_submission_relation', 'o');
280+
$query->fields('o', ['job_id', 'submission_id']);
281+
if ($submissionId) {
282+
$query->condition('submission_id', $submissionId, '=');
283+
}
284+
285+
return $query->execute()->fetchAll();
286+
}
287+
288+
/**
289+
* Remove a list relations.
290+
*
291+
* @param array $entries
292+
* List of entries with job_id and submission_id.
293+
*
294+
* @phpstan-param array<string, mixed> $entries
295+
*/
296+
public function removeRelations(array $entries): void {
297+
foreach ($entries as $entry) {
298+
try {
299+
$submission = $this->entityTypeManager->getStorage('webform_submission')
300+
->getQuery()
301+
->accessCheck(FALSE)
302+
->condition('sid', $entry->submission_id)
303+
->execute();
304+
if (empty($submission)) {
305+
$this->removeQueueSubmissionRelation($entry->submission_id);
306+
}
307+
}
308+
catch (InvalidPluginDefinitionException | PluginNotFoundException $e) {
309+
}
310+
311+
}
312+
}
313+
314+
/**
315+
* Cleanup relations.
316+
*
317+
* @param \Drupal\webform\WebformSubmissionInterface|null $submission
318+
* A webform submission.
319+
*/
320+
public function cleanUp(WebformSubmissionInterface $submission = NULL): void {
321+
$relations = $this->getDetachedQueueSubmissionRelations($submission?->id());
322+
$this->removeRelations($relations);
323+
}
324+
260325
/**
261326
* Get all entries from the advancedqueue table.
262327
*
@@ -331,4 +396,19 @@ private function getAllRelations(): array {
331396
return $query->execute()->fetchAllAssoc('job_id');
332397
}
333398

399+
/**
400+
* Delete advanced queue submission relation.
401+
*
402+
* @param string $submissionId
403+
* The advanced queue submission id.
404+
*/
405+
private function removeQueueSubmissionRelation(string $submissionId): void {
406+
// Delete os2forms_failed_jobs_queue_submission_relation.
407+
if ($this->connection->schema()->tableExists('os2forms_failed_jobs_queue_submission_relation')) {
408+
$this->connection->delete('os2forms_failed_jobs_queue_submission_relation')
409+
->condition('submission_id', $submissionId)
410+
->execute();
411+
}
412+
}
413+
334414
}

src/Plugin/Action/RetryJob.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,9 @@ public static function create(ContainerInterface $container, $configuration, $pl
8686
*/
8787
public function execute(string $jobId = NULL): void {
8888
$job = $this->helper->getJobFromId($jobId);
89+
if (empty($job)) {
90+
return;
91+
}
8992
$queue_id = $job->getQueueId();
9093

9194
$queue_storage = $this->entityTypeManager->getStorage('advancedqueue_queue');

src/Plugin/views/field/AdvancedQueueBulkForm.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,9 @@ public function viewsFormSubmit(&$form, FormStateInterface $form_state): void {
169169
foreach ($selected as $bulk_form_key) {
170170
// Skip execution if the user did not have access.
171171
$job = $this->helper->getJobFromId($bulk_form_key);
172+
if (empty($job)) {
173+
return;
174+
}
172175
if ('failure' !== $job->getState()) {
173176
$this->messenger->addError($this->t('Element with webform submission id: @webform_submit_id already has state: @state', [
174177
'@webform_submit_id' => $this->helper->getSubmissionSerialIdFromJob($bulk_form_key),

0 commit comments

Comments
 (0)