code: package io.paradoxical.cassieq.workers;
  
  import com.godaddy.logging.Logger;
  import com.google.inject.Inject;
  import com.google.inject.assistedinject.Assisted;
  import io.paradoxical.cassieq.dataAccess.DeletionJob;
  import io.paradoxical.cassieq.dataAccess.exceptions.QueueAlreadyDeletingException;
  import io.paradoxical.cassieq.dataAccess.interfaces.QueueRepository;
  import io.paradoxical.cassieq.exceptions.QueueNotFoundException;
  import io.paradoxical.cassieq.factories.DataContextFactory;
  import io.paradoxical.cassieq.factories.MessageDeleterJobProcessorFactory;
  import io.paradoxical.cassieq.model.QueueDefinition;
  import io.paradoxical.cassieq.model.QueueName;
  import io.paradoxical.cassieq.model.accounts.AccountName;
  import io.paradoxical.cassieq.workers.repair.RepairWorkerManager;
  
  import java.util.Optional;
  
  import static com.godaddy.logging.LoggerFactory.getLogger;
  
  public class QueueDeleter {
      private static final Logger logger = getLogger(QueueDeleter.class);
  
      private final DataContextFactory dataContextFactory;
      private final MessageDeleterJobProcessorFactory messageDeleterJobProcessorFactory;
      private final RepairWorkerManager repairWorkerManager;
      private final AccountName accountName;
  
      @Inject
      public QueueDeleter(
              DataContextFactory dataContextFactory,
              MessageDeleterJobProcessorFactory messageDeleterJobProcessorFactory,
              RepairWorkerManager repairWorkerManager,
              @Assisted AccountName accountName) {
          this.dataContextFactory = dataContextFactory;
          this.messageDeleterJobProcessorFactory = messageDeleterJobProcessorFactory;
          this.repairWorkerManager = repairWorkerManager;
          this.accountName = accountName;
      }
  
      public void delete(QueueName queueName) throws QueueAlreadyDeletingException, QueueNotFoundException {
          final QueueRepository queueRepository = dataContextFactory.forAccount(accountName);
  
          final Optional<QueueDefinition> optionalDefinition = queueRepository.getActiveQueue(queueName);
  
          if (!optionalDefinition.isPresent()) {
              throw new QueueNotFoundException("Delete", queueName);
          }
  
  
          final QueueDefinition queueDefinition = optionalDefinition.get();
  
          logger.with(queueDefinition).debug("Attempting to delete queue");
  
          // This should be the first thing. this way the pointers below can't be modified further.
          final Optional<DeletionJob> deletionJob = queueRepository.tryMarkForDeletion(queueDefinition);
  
          if (!deletionJob.isPresent()) {
              throw new QueueAlreadyDeletingException(queueDefinition);
          }
  
          // delegate actual work to another processor that handles the job
          // this can be used to spin up deletion jobs after the fact
          messageDeleterJobProcessorFactory.createDeletionProcessor(deletionJob.get()).start();
  
          repairWorkerManager.notifyChanges();
      }
  
      public interface Factory {
          QueueDeleter create(AccountName accountName);
      }
  }
  