public WorkflowTestBase(DecisionContext decisionContext) {
   this.decisionContext = decisionContext;
   workflowContext = (TestWorkflowContext) decisionContext.getWorkflowContext();
   workflowClock = (TestWorkflowClock) decisionContext.getWorkflowClock();
   WorkflowExecution we = new WorkflowExecution();
   we.setWorkflowId("testWorkflowId");
   we.setRunId("testRunId");
   workflowContext.setWorkflowExecution(we);
   WorkflowType wt = new WorkflowType();
   wt.setName("testWorkflow");
   wt.setVersion("0.0");
   workflowContext.setWorkflowType(wt);
 }
 @Override
 protected void doFinally() throws Throwable {
   if (!failed) {
     continueAsNew.set(childContext.getWorkflowContext().getContinueAsNewOnCompletion());
     if (continueAsNew.get() == null && executeResult.isReady()) {
       result.set(executeResult.get());
     }
   } else {
     continueAsNew.set(null);
   }
   workflowExecutions.remove(this.childExecution.getWorkflowId());
 }
 public void continueAsNewOnCompletion(ContinueAsNewWorkflowExecutionParameters parameters) {
   DecisionContext decisionContext = decisionContextProvider.getDecisionContext();
   decisionContext.getWorkflowContext().setContinueAsNewOnCompletion(parameters);
 }
  private void startChildWorkflow(
      final StartChildWorkflowExecutionParameters parameters,
      final Settable<StartChildWorkflowReply> reply,
      final Settable<String> result) {
    String workflowId = parameters.getWorkflowId();
    WorkflowType workflowType = parameters.getWorkflowType();
    WorkflowExecution childExecution = new WorkflowExecution();
    final String runId = UUID.randomUUID().toString();
    // TODO: Validate parameters against registration options to find missing timeouts or other
    // options
    try {
      DecisionContext parentDecisionContext = decisionContextProvider.getDecisionContext();
      if (workflowId == null) {
        workflowId =
            decisionContextProvider.getDecisionContext().getWorkflowClient().generateUniqueId();
      }
      childExecution.setWorkflowId(workflowId);
      childExecution.setRunId(runId);

      final GenericActivityClient activityClient = parentDecisionContext.getActivityClient();
      final WorkflowClock workflowClock = parentDecisionContext.getWorkflowClock();
      WorkflowDefinitionFactory factory;
      if (factoryFactory == null) {
        throw new IllegalStateException("required property factoryFactory is null");
      }
      factory = factoryFactory.getWorkflowDefinitionFactory(workflowType);
      if (factory == null) {
        String cause =
            StartChildWorkflowExecutionFailedCause.WORKFLOW_TYPE_DOES_NOT_EXIST.toString();
        throw new StartChildWorkflowFailedException(0, childExecution, workflowType, cause);
      }
      TestWorkflowContext workflowContext = new TestWorkflowContext();
      workflowContext.setWorkflowExecution(childExecution);
      workflowContext.setWorkflowType(parameters.getWorkflowType());
      workflowContext.setParentWorkflowExecution(
          parentDecisionContext.getWorkflowContext().getWorkflowExecution());
      workflowContext.setTagList(parameters.getTagList());
      workflowContext.setTaskList(parameters.getTaskList());
      DecisionContext context =
          new TestDecisionContext(
              activityClient, TestGenericWorkflowClient.this, workflowClock, workflowContext);
      // this, parameters, childExecution, workflowClock, activityClient);
      final WorkflowDefinition childWorkflowDefinition = factory.getWorkflowDefinition(context);
      final ChildWorkflowTryCatchFinally tryCatch =
          new ChildWorkflowTryCatchFinally(
              parameters, childExecution, childWorkflowDefinition, context, result);
      workflowContext.setRootTryCatch(tryCatch);
      ChildWorkflowTryCatchFinally currentRun = workflowExecutions.get(workflowId);
      if (currentRun != null) {
        String cause = StartChildWorkflowExecutionFailedCause.WORKFLOW_ALREADY_RUNNING.toString();
        throw new StartChildWorkflowFailedException(0, childExecution, workflowType, cause);
      }
      workflowExecutions.put(workflowId, tryCatch);
      continueAsNewWorkflowExecution(tryCatch, result);
    } catch (StartChildWorkflowFailedException e) {
      throw e;
    } catch (Throwable e) {
      // This cause is chosen to represent internal error for sub-workflow creation
      String cause = StartChildWorkflowExecutionFailedCause.OPEN_CHILDREN_LIMIT_EXCEEDED.toString();
      StartChildWorkflowFailedException failure =
          new StartChildWorkflowFailedException(0, childExecution, workflowType, cause);
      failure.initCause(e);
      throw failure;
    } finally {
      reply.set(new StartChildWorkflowReplyImpl(result, runId));
    }
  }
Example #5
0
public class NonTxWorkflowImpl implements NonTxWorkflow {
  DecisionContextProvider contextProvider = new DecisionContextProviderImpl();
  DecisionContextProvider provider = new DecisionContextProviderImpl();
  DecisionContext context = provider.getDecisionContext();
  private WorkflowClock clock = context.getWorkflowClock();
  private final int confirmationPeriod = 3500;
  BitcoindActivitiesClient bcdClient = new BitcoindActivitiesClientImpl();
  MessagingActivitiesClient msgClient = new MessagingActivitiesClientImpl();

  @Override
  public void executeCommand(final DataSet data) {
    new TryCatch() {
      @Override
      protected void doTry() throws Throwable {
        if (data.getAction() == Action.DEPOSIT_REQ) {
          Promise<String> bcAddress = bcdClient.getNewAddress(data.getCn());
          respondDepositReq(bcAddress, data);
        } else if (data.getAction() == Action.SIGNUP) {
          Promise<Void> done = msgClient.sendMessage(data);
          createAddress(done, data);
        } else if (data.getAction() == Action.GW_DEPOSIT_REQ) {
          Promise<String> bcAddress = bcdClient.getNewAddress(data.getCn());
          respondDataReq(bcAddress, data);
        } else if (data.getAction() == Action.BALANCE) {
          Promise<BigDecimal> balance = bcdClient.getAccountBalance(data.getCn());
          Promise<BigDecimal> fee = msgClient.readAccountFee(data.getCn());
          respondBalance(balance, fee, data);
        } else if (data.getAction() == Action.GW_BALANCE) {
          Promise<BigDecimal> balance = bcdClient.getAccountBalance(data.getCn());
          cacheBalance(balance, data);
        } else if (data.getAction() == Action.TRANSACTION) {
          Promise<List<Transaction>> transactions = bcdClient.getAccountTransactions(data.getCn());
          respondTransactions(transactions, data);
        } else if (data.getAction() == Action.VOICE) {
          final Settable<DataSet> confirm = new Settable<>();
          final Promise<Action> response =
              msgClient.phoneConfirmation(
                  data,
                  contextProvider
                      .getDecisionContext()
                      .getWorkflowContext()
                      .getWorkflowExecution()
                      .getWorkflowId());
          final OrPromise confirmOrTimer =
              new OrPromise(startDaemonTimer(confirmationPeriod), response);
          new TryCatch() {
            @Override
            protected void doTry() throws Throwable {
              setConfirm(confirm, confirmOrTimer, response, data);
            }

            @Override
            protected void doCatch(Throwable e) throws Throwable {
              data.setAction(Action.TIMEOUT);
              msgClient.sendMessage(data);
              cancel(e);
            }
          };
          handleVoice(confirm);
        } else if (data.getAction() == Action.DEPOSIT_CONF
            || data.getAction() == Action.DEPOSIT_NOT) {
          Withdrawal w = (Withdrawal) data.getPayload();
          Promise<BigDecimal> balance = null;
          if (w.getBalance() == null) {
            balance = bcdClient.getAccountBalance(data.getCn());
          }
          Promise<BigDecimal> fee = null;
          if (w.getFee() == null) {
            fee = msgClient.readAccountFee(data.getCn());
          }
          if (data.getTo() == null) {
            respondDepositConfMessage(balance, fee, msgClient.readMessageAddress(data));
          } else {
            Settable<DataSet> ds = new Settable<>();
            respondDepositConfMessage(balance, fee, ds);
            ds.set(data);
          }
        } else {
          throw new RuntimeException("unknown action");
        }
      }

      @Override
      protected void doCatch(Throwable e) throws Throwable {
        data.setAction(Action.UNAVAILABLE);
        msgClient.sendMessage(data);
        e.printStackTrace();
        cancel(e);
      }
    };
  }

  @Asynchronous
  public void handleVoice(Promise<DataSet> rsp) {
    msgClient.sendMessage(rsp.get());
  }

  @Asynchronous
  public void setConfirm(
      @NoWait Settable<DataSet> account,
      OrPromise trigger,
      Promise<Action> isConfirmed,
      DataSet data)
      throws Throwable {
    if (isConfirmed.isReady()) {
      if (null != isConfirmed.get() && isConfirmed.get() != Action.WITHDRAWAL_REQ) {
        data.setAction(isConfirmed.get());
      }
      account.set(data);
    } else {
      throw new Throwable("user did not confirm transaction.");
    }
  }

  @Asynchronous
  public void createAddress(Promise<Void> done, DataSet data) {
    Promise<String> bcAddress = bcdClient.getNewAddress(data.getCn());
    respondDataReq(bcAddress, data);
  }

  @Asynchronous(daemon = true)
  private Promise<Void> startDaemonTimer(int seconds) {
    Promise<Void> timer = clock.createTimer(seconds);
    return timer;
  }

  @Asynchronous
  public void respondDepositReq(Promise<String> bcAddress, DataSet data) {
    data.setPayload(
        new PaymentAddress().setAddress(bcAddress.get()).setAddressType(PaymentType.BTC));
    msgClient.sendMessage(data);
  }

  @Asynchronous
  public void respondDataReq(Promise<String> bcAddress, DataSet data) {
    data.setPayload(
        new PaymentAddress().setAddress(bcAddress.get()).setAddressType(PaymentType.BTC));
    msgClient.putAddressCache(data);
  }

  @Asynchronous
  public void respondBalance(Promise<BigDecimal> balance, Promise<BigDecimal> fee, DataSet data) {
    data.setPayload(new Withdrawal().setBalance(balance.get().subtract(fee.get())));
    msgClient.sendMessage(data);
  }

  @Asynchronous
  public void cacheBalance(Promise<BigDecimal> balance, DataSet data) {
    data.setPayload(new Withdrawal().setBalance(balance.get()));
    msgClient.putCache(data);
  }

  @Asynchronous
  public void respondTransactions(Promise<List<Transaction>> transactions, DataSet data) {
    data.setPayload(transactions.get());
    msgClient.sendMessage(data);
  }

  @Asynchronous
  public void respondDepositConfMessage(
      Promise<BigDecimal> balance, Promise<BigDecimal> fee, Promise<DataSet> addr) {
    DataSet ds = addr.get();
    Withdrawal dep = (Withdrawal) ds.getPayload();
    BigDecimal bal = (dep.getBalance() != null) ? dep.getBalance() : balance.get();
    BigDecimal f = (dep.getFee() != null) ? dep.getFee() : fee.get();
    dep.setBalance(bal.subtract(f));
    msgClient.sendMessage(ds);
  }
}