public Map<String, StepRuntimeState> getStepStates(
      String workflowId, long workflowInstanceId, long workflowRunId, List<String> stepIds) {
    return withMetricLogError(
        () ->
            withRetryableTransaction(
                conn -> {
                  try (PreparedStatement stmt =
                      conn.prepareStatement(GET_STEP_LAST_ATTEMPT_STATE_QUERY)) {
                    int idx = 0;
                    stmt.setString(++idx, workflowId);
                    stmt.setLong(++idx, workflowInstanceId);
                    stmt.setLong(++idx, workflowRunId);
                    stmt.setArray(
                        ++idx, conn.createArrayOf(ARRAY_TYPE_NAME, stepIds.toArray(new String[0])));
                    try (ResultSet result = stmt.executeQuery()) {
                      return getStringStepRuntimeStateMap(result);
                    }
                  }
                }),
        "getStepStates",
        "Failed to get steps [{}] latest attempt stats for [{}][{}][{}]",
        stepIds,
        workflowId,
        workflowInstanceId,
        workflowRunId);
  }
@Test
  public void testGetStepStates() {
    Map<String, StepRuntimeState> stats =
        stepDao.getStepStates(TEST_WORKFLOW_ID, 1, 1, Arrays.asList("job1", "job2"));
    assertEquals(singletonMap(si.getStepId(), si.getRuntimeState()), stats);
  }