I have two servers(EC2 instances). In one server(server 1) i have 5 Batch and on another(server 2) i have 6 Batch. I wrapped each batch into activities and the work flow implementation class is given below. I want to iterate over the activities(entire activities, including server 1 and 2) based on the give execution date. For example, if the date is lesser than the current date then, execute all the activities of both server 1 and 2 starting from the given date up to the current date. If the execution date is equal to current date then, execute all the activities of both server 1 and 2 for current date. Also, if any of the activity for a day throws any exception then, don't execute the activities for the next day(<=current date).
public class JobWorkflowImpl implements JobWorkflow{
private DecisionContextProvider contextProvider
= new DecisionContextProviderImpl();
private WorkflowClock clock
= contextProvider.getDecisionContext().getWorkflowClock();
private BS1JobActivitiesClient bs1ActivitiesClient
= new BS1JobActivitiesClientImpl();
private BS2JobActivitiesClient bs2ActivitiesClient
= new BS2JobActivitiesClientImpl();
@Override
public void executeJob(Date exedate) {
Date today = new Date(clock.currentTimeMillis());
Date toProcess = exedate;
// All date manipulations are pseudocode here as I'm lazy
// to look up the real ones.
Promise<Void> previousDateDone = null;
while(toProcess <= today) {
// Create chain of executeJobForExactDate
// linked by previousDateDone to ensure that they are executed sequentially.
// null Promise is treated as ready promise by the framework.
previousDateDone = executeJobForExactDate(toProcess, previousDateDone);
toProcess.addDay(1);
}
}
Promise<Void> void executeJobForExactDate(Date date, Promise<Void> previous) {
Settable<Integer> firstServerDone = new Settable<Integer>();
Settable<Integer> secondServerDone = new Settable<Integer>();
Settable<Integer> resultODLSLBs1 = new Settable<Integer>();
//TODO Iterate over the activities
new TryCatchFinally(previous){
@Override
protected void doTry(){
Promise<Integer> resultFARBs1 = bs1ActivitiesClient.executecommand1(date);
Promise<Integer> resultUAMLFBs1 = bs1ActivitiesClient.executecommand2(date, resultFARBs1);
Promise<Integer> resultLLPBs1 = bs1ActivitiesClient.executecommand3(date, resultUAMLFBs1);
Promise<Integer> resultODLDLBs1 = bs1ActivitiesClient.executecommand4(date, resultLLPBs1);
// Chain links result of the activity execution
// to an aready existing Settable.
resultODLSLBs1.chain(bs1ActivitiesClient.executecommand5(date, resultODLDLBs1));
}
@Override
protected void doCatch(Throwable e){
throw new MyException("Failed");
}
@Override
protected void doFinally() throws Throwable {
firstServerDone.set(null);
}
};
new TryCatchFinally(previous){
@Override
protected void doTry() {
Promise<Integer> resultFARBs2 = bs2ActivitiesClient.executecommand1(date);
Promise<Integer> resultUAMLFBs2 = bs2ActivitiesClient.executecommand2(date, resultFARBs2);
Promise<Integer> resultLLPBs2 = bs2ActivitiesClient.executecommand3(date, resultUAMLFBs2);
Promise<Integer> resultODLDLBs2 = bs2ActivitiesClient.executecommand4(date, resultLLPBs2);
Promise<Integer> resultODLSLBs2 = bs2ActivitiesClient.executecommand5(date, resultODLDLBs2, resultODLSLBs1);
bs2ActivitiesClient.executecommand6(date, resultODLSLBs2);
}
@Override
protected void doCatch(Throwable e){
throw new MyException("Failed");
}
@Override
protected void doFinally(){
secondServerDone.set(null);
}
};
// AndPromise is done when all of its constructor parameters are done.
// I decided to consider the date processing done when both
// TryCatchFinallies are done. You can implement more complex logic depending on
// the business requirements. One option is to wrap both TryCatcFinallies
// in another TryCatchFinally.
return new AndPromise(firstServerDone, secondServerDone);
}
}
The problem is that, if any activity of server 1 throws any exception then, it is cancelling the all the activity that have not started for both server 1 and server 2. But I want only the activity that have not executed within a server should get cancelled as its own server activity has failed, the other server should continue as far as possible(i.e. the place up to which it is dependent).
The tricky part is that the Flow Framework requires that you use the Clock that it provides through the decision context. Otherwise it is not going to function correctly. The rest is just asynchronous Java programming.
public class JobWorkflowImpl implements JobWorkflow{
private DecisionContextProvider contextProvider
= new DecisionContextProviderImpl();
private WorkflowClock clock
= contextProvider.getDecisionContext().getWorkflowClock();
private BS1JobActivitiesClient bs1ActivitiesClient
= new BS1JobActivitiesClientImpl();
private BS2JobActivitiesClient bs2ActivitiesClient
= new BS2JobActivitiesClientImpl();
@Override
public void executeJob(Date exedate) {
Date today = new Date(clock.currentTimeMillis());
Date toProcess = exedate;
// All date manipulations are pseudocode here as I'm lazy
// to look up the real ones.
Promise<Void> previousDateDone = null;
while(toProcess <= today) {
// Create chain of executeJobForExactDate
// linked by previousDateDone to ensure that they are executed sequentially.
// null Promise is treated as ready promise by the framework.
previousDateDone = executeJobForExactDate(toProcess, previousDateDone);
toProcess.addDay(1);
}
}
Promise<Void> void executeJobForExactDate(Date date, Promise<Void> previous) {
Settable<Integer> firstServerDone = new Settable<Integer>();
Settable<Integer> secondServerDone = new Settable<Integer>();
Settable<Integer> resultODLSLBs1 = new Settable<Integer>();
//TODO Iterate over the activities
new TryCatchFinally(previous){
@Override
protected void doTry(){
Promise<Integer> resultFARBs1 = bs1ActivitiesClient.executecommand1(date);
Promise<Integer> resultUAMLFBs1 = bs1ActivitiesClient.executecommand2(date, resultFARBs1);
Promise<Integer> resultLLPBs1 = bs1ActivitiesClient.executecommand3(date, resultUAMLFBs1);
Promise<Integer> resultODLDLBs1 = bs1ActivitiesClient.executecommand4(date, resultLLPBs1);
// Chain links result of the activity execution
// to an aready existing Settable.
resultODLSLBs1.chain(bs1ActivitiesClient.executecommand5(date, resultODLDLBs1));
}
@Override
protected void doCatch(Throwable e){
System.out.println("Failed to execute BS1 daily job");
}
@Override
protected void doFinally() throws Throwable {
firstServerDone.set(null);
}
};
new TryCatchFinally(previous){
@Override
protected void doTry() {
Promise<Integer> resultFARBs2 = bs2ActivitiesClient.executecommand1(date);
Promise<Integer> resultUAMLFBs2 = bs2ActivitiesClient.executecommand2(date, resultFARBs2);
Promise<Integer> resultLLPBs2 = bs2ActivitiesClient.executecommand3(date, resultUAMLFBs2);
Promise<Integer> resultODLDLBs2 = bs2ActivitiesClient.executecommand4(date, resultLLPBs2);
Promise<Integer> resultODLSLBs2 = bs2ActivitiesClient.executecommand5(date, resultODLDLBs2, resultODLSLBs1);
bs2ActivitiesClient.executecommand6(date, resultODLSLBs2);
}
@Override
protected void doCatch(Throwable e){
System.out.println("Failed to execute BS2 daily job");
}
@Override
protected void doFinally(){
secondServerDone.set(null);
}
};
// AndPromise is done when all of its constructor parameters are done.
// I decided to consider the date processing done when both
// TryCatchFinallies are done. You can implement more complex logic depending on
// the business requirements. One option is to wrap both TryCatcFinallies
// in another TryCatchFinally.
return new AndPromise(firstServerDone, secondServerDone);
}
}
来源:https://stackoverflow.com/questions/26181236/iterate-over-the-list-of-activities-based-on-the-input-provided-using-aws-swf