public int[] startBatchWithRunStrategy(
      @NotNull String workflowId,
      @NotNull RunStrategy runStrategy,
      List<WorkflowInstance> instances) {
    if (instances == null || instances.isEmpty()) {
      return new int[0];
    }
    return withMetricLogError(
        () -> {
          Set<String> uuids =
              instances.stream().map(WorkflowInstance::getWorkflowUuid).collect(Collectors.toSet());

          return withRetryableTransaction(
              conn -> {
                final long nextInstanceId = getLatestInstanceId(conn, workflowId) + 1;
                if (dedupAndCheckIfAllDuplicated(conn, workflowId, uuids)) {
                  return new int[instances.size()];
                }
                long lastAssignedInstanceId =
                    completeInstancesInit(conn, nextInstanceId, uuids, instances);
                int[] res;
                switch (runStrategy.getRule()) {
                  case SEQUENTIAL:
                  case PARALLEL:
                  case STRICT_SEQUENTIAL:
                    res = enqueueInstances(conn, workflowId, instances);
                    break;
                  case FIRST_ONLY:
                    res = startFirstOnlyInstances(conn, workflowId, instances);
                    break;
                  case LAST_ONLY:
                    res = startLastOnlyInstances(conn, workflowId, instances);
                    break;
                  default:
                    throw new MaestroInternalError(
                        "When startBatch, run strategy [%s] is not supported.", runStrategy);
                }
                if (lastAssignedInstanceId >= nextInstanceId) {
                  updateLatestInstanceId(conn, workflowId, lastAssignedInstanceId);
                }
                return res;
              });
        },
        "startBatchWithRunStrategy",
        "Failed to start [{}] workflow instances for [{}] with run strategy [{}]",
        instances.size(),
        workflowId,
        runStrategy);
  }
@Test
  public void testStartBatchRunStrategyWithFirstOnly() throws Exception {
    List<WorkflowInstance> batch = prepareBatch();
    int[] res =
        runStrategyDao.startBatchWithRunStrategy(
            TEST_WORKFLOW_ID, RunStrategy.create("FIRST_ONLY"), batch);
    assertArrayEquals(new int[] {1, 0, -1}, res);
    assertEquals(1, batch.get(0).getWorkflowInstanceId());
    assertEquals(0, batch.get(1).getWorkflowInstanceId());
    assertEquals(2, batch.get(2).getWorkflowInstanceId());

    WorkflowInstance previous = dao.getWorkflowInstanceRun(TEST_WORKFLOW_ID, 1, 1);
    WorkflowInstance latestRun = dao.getLatestWorkflowInstanceRun(TEST_WORKFLOW_ID, 2);
    assertEquals(1, previous.getWorkflowInstanceId());
    assertEquals("wfi1-uuid", previous.getWorkflowUuid());
    assertEquals(WorkflowInstance.Status.CREATED, previous.getStatus());
    assertEquals(2, latestRun.getWorkflowInstanceId());
    assertEquals("wfi3-uuid", latestRun.getWorkflowUuid());
    assertEquals(WorkflowInstance.Status.STOPPED, latestRun.getStatus());
    verifyPublish(0, 0, 0, 1, 1);

    MaestroTestHelper.removeWorkflowInstance(dataSource, TEST_WORKFLOW_ID, 2);
  }