How to ensure that Workflow execution should waits till an event is received and then proceeds with further execution - amazon-swf

I have requirement where workflow should start execution but it should wait for next subsequent events to do the execution. Events are generated based of API calls that the service receives from client. The events semantics is based on a state machine. Please let me know how this can be implemented in java. Please provide any sample code for reference.

If you are using AWS Flow Framework an external event should use Signal API to notify a workflow instance. Inside a workflow it becomes a handler method like:
#Workflow
#WorkflowRegistrationOptions(
defaultExecutionStartToCloseTimeoutSeconds = 60,
defaultTaskStartToCloseTimeoutSeconds = 10)
public interface MyWorkflow
{
#Execute(version = "1.0")
void startMyWF();
#Signal
void signal1();
}
public class MyWFImpl implements MyWorkflow
{
MyActivitiesClient client = new MyActivitiesClientImpl();
// Used to block the workflow until a signal is received.
Settable<Void> signal1Called = new Settable<Void>();
#Override
public void startMyWF(){
Promise<Integer> result = client.activity1();
// Continues when both result and signal1 are ready.
client.activity2(result, signal1);
}
#Override
public void signal1() {
//Process signal
signal1.set(null);
}
}
http://docs.aws.amazon.com/amazonswf/latest/awsflowguide/features.workflow.html describes how to write a workflow interface.
http://docs.aws.amazon.com/amazonswf/latest/awsflowguide/workflowimpl.html describes how to implement workflows.
http://docs.aws.amazon.com/amazonswf/latest/awsflowguide/clients.html describes how to send signals using external client.

Related

Readiness for Spring Cloud Data Flow

Spring Cloud Data Flow's documentation describes how to integrate with kubernetes Readiness probes. I'm developing my dataflow locally and running it in a docker-compose configuration, while we wait for our k8s SCDF environment to be stood up.
Is there another way to implement a readiness / do not send data context for SCDF? Upon component spin-up, I need to make a RESTful call and then run some computations on the results. Things attempted unsuccessfully:
use of ApplicationAvailabilityEvents - publishing a ReadinessState.ACCEPTING_TRAFFIC after the load + compilation is complete, after publishing a ReadinessState.REFUSING_TRAFFIC. When Spring completes its own load, it publishes an ACCEPTING_TRAFFIC, and so doesn't wait for mine from my service.
setting up an ApplicationRunner which also serves as an ApplicationListener for custom events which I throw when the computations are complete. Effectively, the run() method looks like:
public class ApplicationStartupRunner implements ApplicationRunner, ApplicationListener {
private boolean sessionLoaded = false;
public void run(ApplicationArguments args) {
doTimeExpensiveThing();
while (!sessionLoaded) {
TimeUnit.MILLISECONDS.sleep(150);
}
}
public void onApplicationEvent(SessionLoadEvent event) {
this.sessionLoaded = true;
}
}
Additional technical note: the Spring Boot application is built as a processor, which is using a function exposed as a Bean to provide its capability, ala
public Function<Flux<ChangeEvent>, Flux<Alert>> processChangeEvents()
Optimally, whatever approach I use which works in docker-compose, I'll wire into an indicator which'll be picked up by k8s and its readiness probe. Given that SCDF can be deployed on k8s, docker-compose (locally), or CloudFoundry, hoping that there's a model I can hook into that I've just overlooked.
Potential answer: instead of using the ApplicationRunner, wait in the processChangeEvents method and do not return the function until startup processing is complete.
In our case, because the doTimeExpensiveThing is an asynchronous activity, I use the technique of watching/waiting for the sessionLoaded flag, but now within the processChangeEvents method itself.
#Configuration
public class ConfigurationForProcessor implements ApplicationEventListener<SessionLoadEvent> {
boolean sessionLoaded;
Function<Flux<ChangeEvent>, Flux<Alert>> processChangeEvents() {
doTimeExpensiveAsynchronousThing();
while (!sessionLoaded) {
TimeUnit.MILLISECONDS.sleep(150);
}
return (Flux<ChangeEvent>) -> ... code which returns a Flux of Alert
}
public void onApplicationEvent(SessionLoadEvent event) {
this.sessionLoaded = true;
}
}
Very open to guidance on other approaches. This appears like it's working, though not sure there aren't gotchas I haven't caught yet.

stomp disconnects its processing twice in channel interceptor and SimpleBrokerMessageHandler

I have modified to implement channel interceptor in spring-websocket-portfolio sample application (https://github.com/rstoyanchev/spring-websocket-portfolio). whenever the client disconnects, channel interceptor is processed twice. I have similar implementation in my production application. As it is being invoked twice so it has unwanted result for the 2nd invocation. I had put work around for the time being. But wondering why my channel interceptor is invoked twice? Any help would be highly appreciated.
modified items: WebSocketConfig.java:
#Override
public void configureClientInboundChannel(ChannelRegistration registration) {
registration.setInterceptors(channelInterceptor());
}
#Bean
public ChannelInterceptor channelInterceptor() {
return new ChannelInterceptor();
}
ChannelInterceptor :
package org.springframework.samples.portfolio.config;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.simp.stomp.StompHeaderAccessor;
import org.springframework.messaging.support.ChannelInterceptorAdapter;
public class ChannelInterceptor extends ChannelInterceptorAdapter {
#Override
public void postSend(Message<?> message, MessageChannel channel, boolean sent) {
StompHeaderAccessor sha = StompHeaderAccessor.wrap(message);
System.out.println(sha.getCommand() + " " + sha);
switch (sha.getCommand()) {
case CONNECT: {
System.out.println("connected:"+sha.getSessionId());
break;
}
case DISCONNECT: {
System.out.println("disconnected:"+sha.getSessionId());
break;
}
default:
System.out.println("default:"+sha.getCommand());
break;
}
}
}
logs:
**disconnected**:9k1hvln6
**disconnected**:9k1hvln6
Disconnect events may happen more than once for the same session, your interceptor should be idempotent and ignore duplicate events.
You may also consider using application events (SessionConnectEvent, SessionDisconnectEvent...) instead of a channel interceptor. Here's an example of an idempotent event listener: https://github.com/salmar/spring-websocket-chat/blob/master/src/main/java/com/sergialmar/wschat/event/PresenceEventListener.java
Generally a DISCONNECT frame comes the client side, is processed in the StompSubProtocolHandler, and is then propagated to the broker. However, a connection can also be closed or lost without a DISCONNECT frame. Regardless of how a connection is closed, the StompSubProtocolMessageHandler generates a DISCONNECT frame. So there is some redundancy on the server side to ensure the broker is aware the client connection is gone.
As Sergi mentioned you can either subscribe to listen for SessionDisconnectEvent (of which there should be only one) and other AbstractSubProtocol events or ensure your code is idempotent.

listener that groups jms messages then sends to next queue / batching messages

I need to implement a listener that receives multiple messages then groups them base on a certain criteria then send the grouped messages to the next queue. In other words batching them in a logical way.
I'm using Grails and JMS integration plugin.
In my mind, it can be implemented in a listener that runs a single thread that runs an infinite loop that forever consume messages from a queue then do the grouping logic there.
Runnable runnable = new Runnable() {
#Override
public void run() {
while(true) {
def obj = consumer.receive()
//group the messages and store on a list then send them in groups to the next queue
producer.send(groupedObjList)
}
}
}
def thread = new Thread(runnable);
thread.start();
I'm not sure if this is a clean way to do it. So I'm looking for alternatives on how to implement this.

Struts2 JMS request processing long running process

I have a Struts2 Action class that places a JMS Fetch request for a list of Trade in a JMS Queue. This JMS Fetch message is processed by an external process and can take either a few seconds or even few minutes depending on the number of Trade files to be processed by the external task processing app.
I want to know how to handle this HTTP Request with an appropriate response. Does the client wait till the list of Trades is returned? (client (UI) has to action on it and has nothing else to do meanwhile).
The way I approached it is
HTTP Request -->
Struts2 Action -->
Invokes a Runnable to run in a separate Thread (separate from Action class)
UI waits
Action class thread sleeps till runnable does it's job
When Task completed, return list of Trades to UI
Flow is as follows:
Place JMS Fetch Request on Queue1
ExecutorService for Runnable
CClass cclass = new CClass();
final ExecutorService execSvc = Executors.newFixedThreadPool(1);
execSvc.execute(cclass);
Where CClass implements runnable returning a list of Trades:
List<Trade> tradesList = new ArrayList<Trade>();
#Override
public void run() {
while (true) {
try {
Message message = msgConsumer.receive(); // SYNCHRONOUS / NO MDB
if (message == null){
break;
}
if (message instanceof TextMessage) {
TextMessage txtMessage = (TextMessage) message;
Trade trade = TradeBuilder.buildTradeFromInputXML(txtMessage);
if (trade != null) {
tradesList.add(trade); // tradeList is a CClass class variable
}
}
} catch (JMSException e) {
logger.error("JMSException occurred ", e);
}
}
closeConnection();
}
And while this runnableis executing, I do a Thread.sleep in Action class (to let the Runnable execute in the separate Thread)
// In Action class
try {
Thread.sleep(5000); // some time till when the runnable will get executed
} catch (InterruptedException e) {
e.printStackTrace();
}
execSvc.shutdown();
Problem is If I use Callable with a FutureTask and do a get() , that will be blocking till any result is returned. If I do a Runnable, I have to put Action class Thread to sleep till runnable has executed and tradeList is available.
Using Runnable approach, I am able to get couple of hundred records back to UI giving a 5 second Thread.sleep() in main Action class, but only partially constructed tradeList when thousands of records are to be fetched and shown in UI.
This is clearly Not a fail-proof approach.
Any better approach to suggest ? Please elucidate steps for processing in one complete request - response flow.
Yes there is a much better approach when making a standard HTTP request (with ajax you can do other things).
You want to look at the Struts2 Execute and Wait Interceptor Which has most of the functionality you've already implemented. Also look at the token interceptor... which could be useful (it prevents duplicate requests, but doesn't provide a happy wait screen like exec and wait does).

ASP.NET MVC async call a WCF service

After complete of asynchronous call to WCF service I want set success message into session and show user the notification .
I tried use two ways for complete this operation.
1) Event Based Model.
client.GetDataCompleted += new EventHandler<GetDataCompletedEventArgs>(GetDataCompleted);
client.GetDataAsync(id, client);
private void GetDataCompleted(object obj, GetDataCompletedEventArgs e)
{
this.SetNotification(new Notification() { Message = e.Result, Type = NotificationType.Success });
}
In MyOperationCompleted event i can set notification to HttpContext.Current.Session, but I must waiting before this operation will completed and can't navigate to others pages.
2) IAsyncResult Model.
In this way I can navigate to other pages and make asynchronous calls to wcf service, but in GetDataCallback method can't set notification, becouse session = null.
client.BeginGetData(id, GetDataCallback, client);
private void GetDataCallback(IAsyncResult ar)
{
string name = ((ServiceReference1.Service1Client)ar.AsyncState).EndGetData(ar);
this.SetNotification(new Notification() { Message = name, Type = NotificationType.Success });
}
"Generate asynchronous operations" in service reference enabled.
Please help me with this trouble. Thanks.
I'm no wcf expert, but what I've found to work is wrapping your call to the Async version of your method in ThreadPool.QueueUserWorkItem. Without this, I had same blocking issue. So this seems to free up the main thread in your asp mvc to move on while another worker thread waits for the callback.
Also, I used AsyncController, although that alone was not enough without the worker thread.
See this: http://msdn.microsoft.com/en-us/library/ee728598.aspx
I used this as a guide, but still needed the ThreadPool.
Cheers

Resources