tapis_job-1.4.1-alpha1/src/Controller/JobCancelController.php
src/Controller/JobCancelController.php
<?php
namespace Drupal\tapis_job\Controller;
use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Session\AccountProxyInterface;
use Drupal\Core\Url;
use Drupal\tapis_app\DrupalIds as AppDrupalIds;
use Drupal\tapis_job\TapisProvider\TapisJobProviderInterface;
use Drupal\tapis_tenant\TapisProvider\TapisSiteTenantProviderInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Drupal\Core\State\StateInterface;
/**
* Cancel a job when users click the 'terminate job' button on the job
*/
class JobCancelController extends ControllerBase {
/**
* The Tapis site tenant provider.
*
* @var \Drupal\tapis_tenant\TapisProvider\TapisSiteTenantProviderInterface
*/
protected TapisSiteTenantProviderInterface $tapisSiteTenantProvider;
/**
* The entity type manager.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected $entityTypeManager;
/**
* The Tapis job provider.
*
* @var \Drupal\tapis_job\TapisProvider\TapisJobProviderInterface
*/
protected TapisJobProviderInterface $tapisJobProvider;
/**
* The state service.
*
* @var \Drupal\Core\State\StateInterface
*/
protected StateInterface $state;
/**
* The current user.
*
* @var \Drupal\Core\Session\AccountProxyInterface
*/
protected $currentUser;
/**
* Constructs a new JobCancelController object.
*
* @param \Drupal\tapis_tenant\TapisProvider\TapisSiteTenantProviderInterface $tapisSiteTenantProvider
* The Tapis site tenant provider.
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager
* The entity type manager.
* @param \Drupal\tapis_job\TapisProvider\TapisJobProviderInterface $tapisJobProvider
* The Tapis job provider.
* @param \Drupal\Core\State\StateInterface $state
* The state service.
* @param \Drupal\Core\Session\AccountProxyInterface $currentUser
* The current user.
*/
public function __construct(TapisSiteTenantProviderInterface $tapisSiteTenantProvider,
EntityTypeManagerInterface $entityTypeManager,
TapisJobProviderInterface $tapisJobProvider,
StateInterface $state,
AccountProxyInterface $currentUser) {
$this->tapisSiteTenantProvider = $tapisSiteTenantProvider;
$this->entityTypeManager = $entityTypeManager;
$this->tapisJobProvider = $tapisJobProvider;
$this->state = $state;
$this->currentUser = $currentUser;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get("tapis_tenant.tapis_site_tenant_provider"),
$container->get('entity_type.manager'),
$container->get('tapis_job.tapis_job_provider'),
$container->get('state'),
$container->get("current_user"),
);
}
/**
* Terminate a job and redirects to the job view page.
*
* @param \Symfony\Component\HttpFoundation\Request $request
* The current request object.
* @param int $tapis_job
* The job ID.
*
* @return \Symfony\Component\HttpFoundation\RedirectResponse
* A redirect response to the job view page.
*
* @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
* @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
* @throws \Drupal\Core\Entity\EntityStorageException
*/
public function cancelJob(Request $request, int $tapis_job): RedirectResponse {
// Load the job entity.
/** @var \Drupal\tapis_job\TapisJobInterface $job */
$job = $this->entityTypeManager->getStorage('tapis_job')->load($tapis_job);
if (!$job) {
$this->messenger()->addError($this->t('The job does not exist.'));
return $this->redirectJobViewPage($tapis_job);
}
// Always update the local entity.
$job->setStatus("Terminating");
$job->save();
// Clear the entity cache so that the updated status is visible to all.
$this->entityTypeManager->getStorage('tapis_job')->resetCache([$job->id()]);
$tenantId = $job->getTenantId();
$tenantInfo = $this->tapisSiteTenantProvider->getTenantInfo($tenantId);
$tapisTenantId = $tenantInfo['tapis_id'];
// Persist a cancellation flag using the state API.
$terminatingId = $tapisTenantId . '.' . $this->currentUser->id() . '.tapis_job.' . $job->id() . '.terminating';
$this->state->set($terminatingId, TRUE);
$jobOwnerId = $job->getOwnerId();
// Check if the tenant is in maintenance mode.
if ($this->tapisSiteTenantProvider->isTenantInMaintenanceMode($tenantId)) {
$this->messenger()
->addError($this->t('This job cannot be terminated because its site is in maintenance mode.'));
return $this->redirectJobViewPage($tapis_job);
}
// Cancel the job using the job provider.
$this->tapisJobProvider->cancelJob($tenantId, $job->getTapisUUID(), $jobOwnerId);
$app = $job->getApp();
$appType = $app->get(AppDrupalIds::APP_TYPE)->getValue()[0]['value'] ?? '';
if (in_array($appType, ["web", "vnc"])) {
$this->tapisJobProvider->deleteAllAccessLinksForJob($job->id());
}
$this->messenger()
->addStatus(($this->t('The job was successfully terminated; however, it may take some time to update the job status.')));
return $this->redirectJobViewPage($tapis_job);
}
/**
* Redirects to the job view page.
*
* @param int $tapis_job_id
* The job ID.
*
* @return \Symfony\Component\HttpFoundation\RedirectResponse
* A redirect response to the job view page.
*/
private function redirectJobViewPage(int $tapis_job_id): RedirectResponse {
return new RedirectResponse(Url::fromRoute('entity.tapis_job.canonical', ['tapis_job' => $tapis_job_id])->toString());
}
}
