My problem is as follows: I have a TCP socket on which I asynchronously send messages based on a proprietary protocol. Upon receiving a response for a message I need to make sure that data gets sent back to the function that initially sent the message. The problem is I can only listen for responses on a "data" event on the socket (in this case in Node.js) and I have no way of easily determining which responses correspond to which messages.
Below is an example that I hope will give you an idea of what I am trying to accomplish.
function getTemperature (callback) {
socket.write(message);
// Good?
socket.on('data', callback);
}
function getVoltage (callback) {
socket.write(message);
// Other way to invoke callback?
}
getTemperature(function (err, temperature) {});
getVoltage(function (err, voltage) {});
socket.on('data', handleData function (data) {
// Somehow send data to correct function
}
One idea I had was registering multiple event handlers for the data event but this seems kind of wacky. What is the correct way to handle this?
When dealing with an asynchronous protocol, you would typically need to design the protocol so that each request has a unique ID that is included in the request data and gets sent back in the response. That way, you can receive responses out of order, and even receive unsolicited messages.
When you send a request, put the request ID in a list somewhere, along with a callback that will be called when the response arrives.
When you get a data event, append the raw data to a buffer, and then parse out only complete messages from the buffer, leaving incomplete messages for later completion. For each complete message parsed out, check if it has a request ID. If no, the message is unsolicited, so process it accordingly. Otherwise, look for the request ID in the list, and if found then call the callback associated with it.
Related
I am using a FIX protocol to communicate with one of our counterparties. I have used Camel with Spring to build my communication routes.
I have a requirement where in my counterparty is expecting an ACK for every request it sends to me.
For example:
TradeCaptureRequestAck in response to TradeCaptureRequest
AllocationReportAck in response to AllocationReport
Confirmation_Ack in response to Confirmation
They are expecting a response irrespective of what happens at our end (even if something fails or exception occurs).
One way I know we can intercept the incoming message via MessageFactory. We can create a custom messagefactory and inject it in while creating QuickFixJComponent bean.
Problem with this approach is at factory level I will just be able to get the message type like TradeCaptureReport, AllocationReport etc. but not the content because factory only creates (and returns) the appropriate Message object. Actual work of populating this message object with incoming message data happens in Session class I guess (not sure about this).
Can someone please tell me if there is a way I can get or intercept the request message as soon as it reaches the route so that I can send the appropriate ACK to counterparty?
I am new NATS. Not sure how NATS request reply works.
As per my understanding, this pattern can be use for bi-directional communication but questions is, Does it works between same message id/thread ? If not, can't we use two different queue for the same purpose? How it is different from pub-sub or queue pattern of NATS?
Can someone provide more use case on this?
Thanks.
You added nats-streaming-server tag, so I would first want to clarify that there is no request/reply API in NATS Streaming, because it does not really make sense.
In NATS, you would use request/reply when your publishing application wants to know that the subscribing application did receive and process the message. It is an end-to-end confirmation that the published message was received and processed.
It can also be simply because the subscribing application processes a job and send the result of that job back to the requestor.
A simple example would be:
// Request will create an internal subscription on
// a private inbox and set it to the message's Reply
// field.
msg, err := nc.Request("job", payload, time.Second)
if err != nil {
...
} else {
// msg is the reply sent by the subscribing application.
}
In the other side, you would have registered a subscription to handle the job requests.
nc.Subscribe("job", func(req *nats.Msg) {
// req is the request received by the publisher above.
// Send back a reply to the request reply subject.
nc.Publish(req.Reply, []byte(reply))
})
Not sure what language you use, but here is a link to the Go client
I am looking into the Swift Vapor framework.
I am trying to create a controller class that maps data obtained on an SSL link to a third party system (an Asterisk PBX server..) into a response body that is sent over some time down to the client.
So I need to send received text lines (obtained separately on the SSL connection) as they get in, without waiting for a 'complete response' to be constructed.
Seeing this example:
return Response(status: .ok) { chunker in
for name in ["joe\n", "pam\n", "cheryl\n"] {
sleep(1)
try chunker.send(name)
}
try chunker.close()
}
I thought it might be the way to go.
But what I see connecting to the Vapor server is that the REST call waits for the loop to complete, before the three lines are received as result.
How can I obtain to have try chunker.send(name) send it's characters back the client without first waiting for the loop to complete?
In the real code the controller method can potentially keep an HTTP connection to the client open for a long time, sending Asterisk activity data to the client as soon as it is obtained. So each .send(name) should actually pass immediately data to the client, not waiting for the final .close() call.
Adding a try chunker.flush() did not produce any better result..
HTTP requests aren't really designed to work like that. Different browsers and clients will function differently depending on their implementations.
For instance, if you connect with telnet to the chunker example you pasted, you will see the data is sent every second. But Safari on the other hand will wait for the entire response before displaying.
If you want to send chunked data like this reliably, you should use a protocol like WebSockets that is designed for it.
I use the perform javascript call to perform an action on the server, like this:
subscription.perform('action', {...});
However, from what I've seen there seems to be no builtin javascript "success" callback, i.e. to let me know the action is concluded on the server's side (or possibly failed). I was thinking about sending a broadcast at the end of the action like so:
def action(data)
...do_stuff
ActionCable.server.broadcast "room", success_message...
end
But all clients subscribed to this "room" would receive that message, possibly resulting in false positives. In addition, from what I've heard, message order isn't guaranteed, so a previous broadcast inside this action could be delivered after the success message, possibly leading to further issues.
Any ideas on this or am I missing something completely?
Looking at https://github.com/xtian/action-cable-js/blob/master/dist/cable.js and , https://developer.mozilla.org/en-US/docs/Web/API/WebSocket#send(), perform just executes WebSocket.send() and returns true or false, and there is no way to know whether your data has arrived. (That is just not possible with WebSockets, it seems.)
You could try using just a http call (I recommend setting up an api with jbuilder), or indeed broadcasting back a success message.
You can solve the order of the messages by creating a timestamp on the server, and sending it along with the message, and then sorting the messages with Javascript.
Good luck!
Maybe what you are looking for is the trasmit method: https://api.rubyonrails.org/v6.1.3/classes/ActionCable/Channel/Base.html#method-i-transmit
It sends a message to the current connection being handled for a channel.
Just read about HTTP response code 202, where a POST returns no body and instead returns a location to poll (getting 200s) until completion (getting a 201 or 303).
In C#, we communicate this by the convention of giving a method an Asynch suffix to the method name (and it returns a task or takes a call back reference).
How do I communicate this in HTTP? Do I invent my own ad hoc method, or is there some request header or other standard means for for indicating this?
And is there a standard way to tell the client how often to poll? (And as I understand HTTP, there isn't a way to do a call back without polling, right?)
I have read this related question, it does not address how a client distinguishes between an synch vs an asych request, nor how to communicate polling rates. Ditto for this related question.
How do I communicate this in HTTP? Do I invent my own ad hoc method,
or is there some request header or other standard means for for
indicating this?
I believe the 202 accepted is mostly used by eventual consistency. Afaik there is no standard way to describe a poll link, so you have to use your ad-hoc solution. By HTTP you can poll only, but you can use websockets in combination with HTTP if you don't want your clients to poll. (note: websockets is not REST)
You can possibly use an already existing vocab to describe a poll link with linked data. I haven't found a vocab, which contains this term, so I am afraid you have to define it in your own vocab or probably with a custom link relation... :S
From Firefox manual
var xhr = new XMLHttpRequest();
xhr.open("GET", "/bar/foo.txt", true); // True is asynchronous
xhr.onload = function (e) {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
console.log(xhr.responseText);
} else {
console.error(xhr.statusText);
}
}
};
xhr.onerror = function (e) {
console.error(xhr.statusText);
};
xhr.send(null);