public TimelineEvent deleteWorkflow(String workflowId, User author) {
    if (IdHelper.isInlineWorkflowId(workflowId)) {
      throw new MaestroUnprocessableEntityException(
          "Cannot delete an inline foreach workflow [%s], please delete its parent concrete workflow instead.",
          workflowId);
    }

    final int nonTerminalCnt = Arrays.stream(getIndexedInstanceCount(workflowId, false)).sum();
    Checks.checkTrue(
        nonTerminalCnt == 0,
        "Cannot delete the workflow [%s] "
            + "because there are still [%s] number of queued or running workflow instances."
            + "Please delete it after taking care of them, e.g. stopping all of them.",
        workflowId,
        nonTerminalCnt);

    TimelineEvent info =
        TimelineLogEvent.info(
            "The workflow is deleted by [%s]. "
                + "All associated workflow data (e.g. versions and instances) will be deleted shortly.",
            author.getName());

    final String infoString = toJson(info);
    Long res =
        withRetryableStatement(
            DELETE_MAESTRO_WORKFLOW_QUERY,
            stmt -> {
              int idx = 0;
              stmt.setString(++idx, workflowId);
              stmt.setString(++idx, workflowId);
              stmt.setString(++idx, infoString);
              try (ResultSet result =
                  stmt.executeQuery()) { // unnecessary, to avoid PMD false positive
                if (result.next()) {
                  long internalId = result.getLong(1);
                  Checks.checkTrue(
                      !result.next(),
                      "Aborting the deletion as there is already a deletion task in progress for workflow [%s]",
                      workflowId);
                  publisher.publishOrThrow(
                      DeleteWorkflowJobEvent.create(workflowId, internalId, author),
                      "Failed to publish maestro delete job event for workflow: " + workflowId);
                  return internalId;
                }
                return null;
              }
            });
    if (res == null) {
      throw new MaestroNotFoundException(
          "No workflow is deleted because workflow [%s] is non-existing or has queued or running instances.",
          workflowId);
    }
    LOG.info(
        "User [{}] deleted workflow [{}] with a unique internalId [{}]. Send a delete job event to remove data",
        author.getName(),
        workflowId,
        res);
    return info;
  }
@Test
  public void testDeleteWorkflow() throws Exception {
    WorkflowDefinition wfd = loadWorkflow(TEST_WORKFLOW_ID1);
    workflowDao.addWorkflowDefinition(wfd, wfd.getPropertiesSnapshot().extractProperties());
    WorkflowDefinition def = workflowDao.getWorkflowDefinition(TEST_WORKFLOW_ID1, "latest");
    assertNotNull(wfd.getInternalId());
    assertNotNull(def.getInternalId());
    assertEquals(wfd.getInternalId(), def.getInternalId());
    assertEquals(wfd.getWorkflow(), def.getWorkflow());
    workflowDao.deleteWorkflow(TEST_WORKFLOW_ID1, User.create("tester"));
    verify(publisher, times(1)).publishOrThrow(any(DeleteWorkflowJobEvent.class), any());
    reset(publisher);
    AssertHelper.assertThrows(
        "The workflow should have been deleted",
        MaestroNotFoundException.class,
        "has not been created yet or has been deleted",
        () -> workflowDao.getWorkflowDefinition(TEST_WORKFLOW_ID1, "latest"));
  }