Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

copy demo workflow over #5

Merged
merged 1 commit into from
Sep 11, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package iwf.demo.subscription;

import iwf.core.Context;
import iwf.core.StateDecision;
import iwf.core.WorkflowState;
import iwf.core.attributes.QueryAttributesRW;
import iwf.core.attributes.SearchAttributesRW;
import iwf.core.attributes.StateLocalAttributesR;
import iwf.core.attributes.StateLocalAttributesW;
import iwf.core.command.CommandRequest;
import iwf.core.command.CommandResults;
import iwf.core.command.SignalCommand;

import static iwf.core.StateDecision.COMPLETING_WORKFLOW;

public class CancelSubscriptionState implements WorkflowState<Void> {
public static final String WF_STATE_CANCEL_SUBSCRIPTION = "cancelSubscription";

@Override
public String getStateId() {
return WF_STATE_CANCEL_SUBSCRIPTION;
}

@Override
public Class<Void> getInputType() {
return Void.class;
}

@Override
public CommandRequest start(Context context, Void input, StateLocalAttributesW stateLocals, SearchAttributesRW searchAttributes, QueryAttributesRW queryAttributes) {
return CommandRequest.forAllCommandCompleted(
new SignalCommand(SubscriptionWorkflow.SIGNAL_METHOD_CANCEL_SUBSCRIPTION)
);
}

@Override
public StateDecision decide(Context context, Void input, CommandResults commandResults, StateLocalAttributesR stateLocals, SearchAttributesRW searchAttributes, QueryAttributesRW queryAttributes) {
return COMPLETING_WORKFLOW;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package iwf.demo.subscription;

import iwf.core.Context;
import iwf.core.StateDecision;
import iwf.core.StateMovement;
import iwf.core.WorkflowState;
import iwf.core.attributes.QueryAttributesRW;
import iwf.core.attributes.SearchAttributesRW;
import iwf.core.attributes.StateLocalAttributesR;
import iwf.core.attributes.StateLocalAttributesW;
import iwf.core.command.CommandRequest;
import iwf.core.command.CommandResults;
import iwf.demo.subscription.models.Customer;

import static iwf.demo.subscription.WaitForPeriodState.WF_STATE_WAIT_FOR_NEXT_PERIOD;

public class ChargeCurrentPeriodState implements WorkflowState<Void> {
public static final String WF_STATE_CHARGE_CURRENT_PERIOD = "chargeCurrentPeriod";

@Override
public String getStateId() {
return WF_STATE_CHARGE_CURRENT_PERIOD;
}

@Override
public Class<Void> getInputType() {
return Void.class;
}

@Override
public CommandRequest start(Context context, Void input, StateLocalAttributesW stateLocals, SearchAttributesRW searchAttributes, QueryAttributesRW queryAttributes) {
final Customer customer = searchAttributes.get(SubscriptionWorkflow.QUERY_ATTRIBUTE_CUSTOMER);
final int currentPeriod = queryAttributes.get(SubscriptionWorkflow.QUERY_ATTRIBUTE_BILLING_PERIOD_NUMBER);
// invoke API here to chart the user
// control the timeout by customizing the WorkflowStateOptions
return CommandRequest.none();
}

@Override
public StateDecision decide(Context context, Void input, CommandResults commandResults, StateLocalAttributesR stateLocals, SearchAttributesRW searchAttributes, QueryAttributesRW queryAttributes) {
return new StateDecision(
new StateMovement(WF_STATE_WAIT_FOR_NEXT_PERIOD)
);
}
}
13 changes: 13 additions & 0 deletions core/src/test/java/iwf/demo/subscription/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
## Subscription workflow

This is an [example](https://github.com/longquanzheng/iwf/blob/main/src/com/indeed/iwf/demo/subscription) as a
translation of the [ Subscription workflow](https://cadenceworkflow.io/docs/concepts/workflows/#example)

Based on the workflow definition, a diagram can be drawn easily to illustrate the flow.

Imagine if you want to add some sleeping in somewhere of the workflow, you can add it right away without any versioning, and
* It will take into affect for any newly started workflow
* It will also take affect for any existing started workflow

![alt text](diagram.png "Subscription workflow")

Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package iwf.demo.subscription;

import iwf.core.Context;
import iwf.core.StateDecision;
import iwf.core.WorkflowState;
import iwf.core.attributes.QueryAttributesRW;
import iwf.core.attributes.SearchAttributesRW;
import iwf.core.attributes.StateLocalAttributesR;
import iwf.core.attributes.StateLocalAttributesW;
import iwf.core.command.CommandRequest;
import iwf.core.command.CommandResults;
import iwf.demo.subscription.models.Customer;

public class SubscriptionOverState implements WorkflowState<Void> {
public static final String WF_STATE_SUBSCRIPTION_OVER = "subscriptionOver";

@Override
public String getStateId() {
return WF_STATE_SUBSCRIPTION_OVER;
}

@Override
public Class<Void> getInputType() {
return Void.class;
}

@Override
public CommandRequest start(Context context, Void input, StateLocalAttributesW stateLocals, SearchAttributesRW searchAttributes, QueryAttributesRW queryAttributes) {
final Customer customer = queryAttributes.get(SubscriptionWorkflow.QUERY_ATTRIBUTE_CUSTOMER);
// invoke API here to send subscription over email.
// control the timeout by customizing the WorkflowStateOptions
return CommandRequest.none();
}

@Override
public StateDecision decide(Context context, Void input, CommandResults commandResults, StateLocalAttributesR stateLocals, SearchAttributesRW searchAttributes, QueryAttributesRW queryAttributes) {
return StateDecision.COMPLETING_WORKFLOW;
}
}
37 changes: 37 additions & 0 deletions core/src/test/java/iwf/demo/subscription/SubscriptionWorkflow.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package iwf.demo.subscription;

import iwf.core.StateDef;
import iwf.core.Workflow;
import iwf.core.attributes.QueryAttributeDef;
import iwf.core.attributes.SearchAttributeDef;
import iwf.core.command.SignalMethodDef;

import java.util.List;

public class SubscriptionWorkflow implements Workflow {
public static final String SIGNAL_METHOD_CANCEL_SUBSCRIPTION = "CancelSubscription";
public static final String SIGNAL_METHOD_UPDATE_BILLING_PERIOD_CHARGE_AMOUNT = "UpdateBillingPeriodChargeAmount";

public static final String QUERY_ATTRIBUTE_BILLING_PERIOD_NUMBER = "BillingPeriodNumber";
public static final String QUERY_ATTRIBUTE_CUSTOMER = "BillingSubscription";

@Override
public List<StateDef> getStates() {
return null;
}

@Override
public List<SignalMethodDef<?>> getSignalMethods() {
return null;
}

@Override
public List<SearchAttributeDef<?>> getSearchAttributes() {
return null;
}

@Override
public List<QueryAttributeDef<?>> getQueryAttributes() {
return null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package iwf.demo.subscription;

import iwf.core.Context;
import iwf.core.StateDecision;
import iwf.core.StateMovement;
import iwf.core.WorkflowState;
import iwf.core.attributes.QueryAttributesRW;
import iwf.core.attributes.SearchAttributesRW;
import iwf.core.attributes.StateLocalAttributesR;
import iwf.core.attributes.StateLocalAttributesW;
import iwf.core.command.CommandRequest;
import iwf.core.command.CommandResults;
import iwf.core.command.SignalCommand;
import iwf.demo.subscription.models.Customer;

public class UpdateChargeAmountState implements WorkflowState<Void> {
public static final String WF_STATE_UPDATE_CHARGE_AMOUNT = "updateChargeAmount";

@Override
public String getStateId() {
return WF_STATE_UPDATE_CHARGE_AMOUNT;
}

@Override
public Class<Void> getInputType() {
return Void.class;
}

@Override
public CommandRequest start(Context context, Void input, StateLocalAttributesW stateLocals, SearchAttributesRW searchAttributes, QueryAttributesRW queryAttributes) {
return CommandRequest.forAllCommandCompleted(
new SignalCommand(SubscriptionWorkflow.SIGNAL_METHOD_UPDATE_BILLING_PERIOD_CHARGE_AMOUNT)
);
}

@Override
public StateDecision decide(Context context, Void input, CommandResults commandResults, StateLocalAttributesR stateLocals, SearchAttributesRW searchAttributes, QueryAttributesRW queryAttributes) {
final int newAmount = commandResults.getSignalValueByIndex(0);
final Customer customer = queryAttributes.get(SubscriptionWorkflow.QUERY_ATTRIBUTE_CUSTOMER);
customer.getSubscription().setBillingPeriodCharge(newAmount);
queryAttributes.upsert(SubscriptionWorkflow.QUERY_ATTRIBUTE_CUSTOMER, customer);

return new StateDecision(
new StateMovement(WF_STATE_UPDATE_CHARGE_AMOUNT) // go to a loop to update the value
);
}
}
59 changes: 59 additions & 0 deletions core/src/test/java/iwf/demo/subscription/WaitForPeriodState.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package iwf.demo.subscription;

import iwf.core.Context;
import iwf.core.StateDecision;
import iwf.core.StateMovement;
import iwf.core.WorkflowState;
import iwf.core.attributes.QueryAttributesRW;
import iwf.core.attributes.SearchAttributesRW;
import iwf.core.attributes.StateLocalAttributesR;
import iwf.core.attributes.StateLocalAttributesW;
import iwf.core.command.CommandRequest;
import iwf.core.command.CommandResults;
import iwf.core.command.TimerCommand;
import iwf.demo.subscription.models.Customer;

import java.util.ArrayList;

import static iwf.demo.subscription.ChargeCurrentPeriodState.WF_STATE_CHARGE_CURRENT_PERIOD;
import static iwf.demo.subscription.SubscriptionOverState.WF_STATE_SUBSCRIPTION_OVER;

public class WaitForPeriodState implements WorkflowState<Void> {
public static final String WF_STATE_WAIT_FOR_NEXT_PERIOD = "waitForNextPeriod";

@Override
public String getStateId() {
return WF_STATE_WAIT_FOR_NEXT_PERIOD;
}

@Override
public Class<Void> getInputType() {
return Void.class;
}

@Override
public CommandRequest start(Context context, Void input, StateLocalAttributesW stateLocals, SearchAttributesRW searchAttributes, QueryAttributesRW queryAttributes) {
final Customer customer = queryAttributes.get(SubscriptionWorkflow.QUERY_ATTRIBUTE_CUSTOMER);

return CommandRequest.forAllCommandCompleted(
new TimerCommand((int) (System.currentTimeMillis() / 1000) + customer.getSubscription().getPeriodsInSubscription())
);
}

@Override
public StateDecision decide(Context context, Void input, CommandResults commandResults, StateLocalAttributesR stateLocals, SearchAttributesRW searchAttributes, QueryAttributesRW queryAttributes) {
ArrayList<StateMovement> nextStates = new ArrayList();
final Customer customer = queryAttributes.get(SubscriptionWorkflow.QUERY_ATTRIBUTE_CUSTOMER);
int currentPeriodNum = queryAttributes.get(SubscriptionWorkflow.QUERY_ATTRIBUTE_BILLING_PERIOD_NUMBER);
if (currentPeriodNum < customer.getSubscription().getPeriodsInSubscription()) {
queryAttributes.upsert(SubscriptionWorkflow.QUERY_ATTRIBUTE_BILLING_PERIOD_NUMBER, currentPeriodNum + 1);
nextStates.add(new StateMovement(WF_STATE_CHARGE_CURRENT_PERIOD));
} else {
nextStates.add(new StateMovement(WF_STATE_SUBSCRIPTION_OVER));
}

return new StateDecision(
nextStates
);
}
}
51 changes: 51 additions & 0 deletions core/src/test/java/iwf/demo/subscription/WelcomeEmailState.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package iwf.demo.subscription;

import iwf.core.Context;
import iwf.core.StateDecision;
import iwf.core.StateMovement;
import iwf.core.WorkflowState;
import iwf.core.attributes.QueryAttributesRW;
import iwf.core.attributes.SearchAttributesRW;
import iwf.core.attributes.StateLocalAttributesR;
import iwf.core.attributes.StateLocalAttributesW;
import iwf.core.command.CommandRequest;
import iwf.core.command.CommandResults;
import iwf.demo.subscription.models.Customer;

import static iwf.demo.subscription.CancelSubscriptionState.WF_STATE_CANCEL_SUBSCRIPTION;
import static iwf.demo.subscription.UpdateChargeAmountState.WF_STATE_UPDATE_CHARGE_AMOUNT;
import static iwf.demo.subscription.WaitForPeriodState.WF_STATE_WAIT_FOR_NEXT_PERIOD;

public class WelcomeEmailState implements WorkflowState<Customer> {
public static final String WF_STATE_SEND_WELCOME_EMAIL = "sendWelcomeEmail";

@Override
public String getStateId() {
return WF_STATE_SEND_WELCOME_EMAIL;
}

@Override
public Class<Customer> getInputType() {
return Customer.class;
}

@Override
public CommandRequest start(Context context, Customer input, StateLocalAttributesW stateLocals, SearchAttributesRW searchAttributes, QueryAttributesRW queryAttributes) {
// invoke API here to send subscription start email.
// control the timeout by customizing the WorkflowStateOptions
return CommandRequest.none();
}

@Override
public StateDecision decide(final Context context,final Customer customer, final CommandResults commandResults, final StateLocalAttributesR stateLocals,
final SearchAttributesRW searchAttributes, final QueryAttributesRW queryAttributes) {
queryAttributes.upsert(SubscriptionWorkflow.QUERY_ATTRIBUTE_BILLING_PERIOD_NUMBER, 0); // starting from 0
queryAttributes.upsert(SubscriptionWorkflow.QUERY_ATTRIBUTE_CUSTOMER, customer);

return new StateDecision(
new StateMovement(WF_STATE_CANCEL_SUBSCRIPTION),
new StateMovement(WF_STATE_UPDATE_CHARGE_AMOUNT),
new StateMovement(WF_STATE_WAIT_FOR_NEXT_PERIOD)
);
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 11 additions & 0 deletions core/src/test/java/iwf/demo/subscription/models/Customer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package iwf.demo.subscription.models;

public class Customer {
public String getId() {
return null;
}

public Subscription getSubscription() {
return null;
}
}
18 changes: 18 additions & 0 deletions core/src/test/java/iwf/demo/subscription/models/Subscription.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package iwf.demo.subscription.models;

public class Subscription {
public int getPeriodsInSubscription() {
return 10;
}

public int getBillingPeriodInSeconds() {
return 3600 * 24 * 7;
}

public int getBillingPeriodCharge() {
return 100;
}

public void setBillingPeriodCharge(int newAmount) {
}
}
2 changes: 1 addition & 1 deletion iwf-idl