I am currently creating some custom flows, sending back and forth some data through the session. I noticed that in some cases (for example if a responder flow has a session.receive still unanswered when the initiating flow finishes), no exceptions are thrown and everything works smoothly, without even a warn log. Is there a way to force the check of send/receive completeness?
If you can provide some log file to demonstrate your use case would be better.
Send & Receive is typically a one-direction communication, one sends and one receives. If you are looking for a confirm receive, you can try to use method sendAndReceive, which
Serializes and queues the given payload object for sending to the counterparty.
Suspends until a response is received, which must be of the given R type.
Receive method itself is a blocking method, so if your flow successfully finishes. it means the receive method successfully receive what it is looking for.
But again, it would be much better if you can share your log and the elaborate on your questions a bit.
Related
When developing an Async C++ GRPC Server, how can I differentiate between the client being done with writing and the connection being broken ?
I am Streaming data from the client to the server and once the client is done it will call WritesDone to let the server know it should finish storing the file. If I have a sync server I can differentiate between the client calling WritesDone and the connection being broken by calling context->IsCancelled() but in async mode you can not call IsCancelled until you get the tag specified in AsyncNotifyWhenDone.
In both cases (WritesDone and Call done) the Read tag gets returned with ok set to false. However, the AsyncNotifyWhenDone tag, which would allow me to differentiate arrives after the read tag.
I will know after I try to call finish (it will also return false) but I need to know before I call finish as my final processing might fail and I can't return the error anymore if I already called finish.
There's no way to distinguish until the AsyncNotifyWhenDone tag returns. It may come after the Read in which case you may need to buffer it up. In the sync API you can check IsCancelled() anytime (and you can also do that in the Callback API which should be available for general use soon).
I'm creating an async gRPC server in C++. One of the methods streams data from the server to clients - it's used to send data updates to clients. The frequency of the data updates isn't predictable. They could be nearly continuous or as infrequent as once per hour. The model used in the gRPC example with the "CallData" class and the CREATE/PROCESS/FINISH states doesn't seem like it would work very well for that. I've seen an example that shows how to create a 'polling' loop that sleeps for some time and then wakes up to check for new data, but that doesn't seem very efficient.
Is there another way to do this? If I use the "CallData" method can it block in the 'PROCESS' state until there's data (which probably wouldn't be my first choice)? Or better, can I structure my code so I can notify a gRPC handler when data is available?
Any ideas or examples would be appreciated.
In a server-side streaming example, you probably need more states, because you need to track whether there is currently a write already in progress. I would add two states, one called WRITE_PENDING that is used when a write is in progress, and another called WRITABLE that is used when a new message can be sent immediately. When a new message is produced, if you are in state WRITABLE, you can send immediately and go into state WRITE_PENDING, but if you are in state WRITE_PENDING, then the newly produced message needs to go into a queue to be sent after the current write finishes. When a write finishes, if the queue is non-empty, you can grab the next message from the queue and immediately start a write for it; otherwise, you can just go into state WRITABLE and wait for another message to be produced.
There should be no need to block here, and you probably don't want to do that anyway, because it would tie up a thread that should otherwise be polling the completion queue. If all of your threads wind up blocked that way, you will be blind to new events (such as new calls coming in).
An alternative here would be to use the C++ sync API, which is much easier to use. In that case, you can simply write straight-line blocking code. But the cost is that it creates one thread on the server for each in-progress call, so it may not be feasible, depending on the amount of traffic you're handling.
I hope this information is helpful!
First, I want to say that I'm new with Boost asio, and I see a lot of examples but it remains things I don't understand.
I want to create a server, that will accept two clients (it will use two socket). The first client will send messages to the server and the server will send this message to the other client (yes, it is useless to use a server, but it's not the point here, I want to understand how all this work). This will happen until one of the client close.
So, I created a server, the server wait for the clients, and then, it must wait for the first client to send some message. And this is my question: what must I do after?
I thought I need to read the first socket, and then write on the second, and so and so, but how I know if the first client writed on the socket? Same, how I know if the second client read the second socket?
I don't need code, I just want to know the good way to do that.
Thanks a lot for reading!
When you perform async_read you specifify a callback which is going to be called whenever any data is read to the buffer ( you should provide the buffer also, check the async_read's documentation ). Respectively you should provide callback for the async_write to know when your data is already sent. So, from the server perspective, for the client which 'writes' you should do async_read, and for the second client which 'reads' you should do async write. With the offered dataflow client1->server->client2 it is hard to recognize which client the server should read from and which one is write to. It's up to you. You can choose the first connected client as writer and the second as reader, for example.
You might want to start with asio iostreams. It's a high-level iostream-like abstraction above asynchronous sockets.
P.S.: also, don't forget to run io_service.run() loop somewhere. Because all the asio callbacks are executed within that loop.
I am using $SUB for the first time and have come across this problem. Both, client and server use overlapped operations and here is the specific situation I have a problem with.
Client
C1. Connects to the server.
C2. Sends the message bigger than a pipe buffer and buffer passed to overlapped read operation in the server.
C3. Successfully cancels the send operation.
Server
S1. Creates and waits for the client.
S2. When the client is connected, it reads the message.
S21. Because message doesn't fit into the buffer(ERROR_MORE_DATA), it is read part by part.
It seems to me that there is no way to tell when is the whole message, as an isolated unit, canceled. In particular, if client cancels the send operation, server does not receive the whole message, just a part of it, and consequent read operation returns with ERROR_IO_PENDING (in my case), which means there is no data to be read and read operation has been queued. I would expect to have some kind of means telling the reader that the message has been canceled, so that reader can act upon it.
However, relevant documentation is scatter over MSDN, so I may as well be missing something. I would really appreciate if anyone can shed some light on it. Thanks.
You are correct, there is no way to tell.
If you cancel the Writefile partway through, only part of the message will be written, so only that part will be read by the server. There is no "bookkeeping" information sent about how large the message was going to be before you cancelled it - what is sent is just the raw data.
So the answer is: Don't cancel the IO, just wait for it to succeed.
If you do need to cancel IO partway through, you should probably cut the connection and start again from the beginning, just as you would for a network outage.
(You could check your OVERLAPPED structure to find out how much was actually written, and carry on from there, but if you wanted to do that you would probably just not cancel the IO in the first place.)
Why did you want to cancel the IO anyway? What set of circumstances triggers this requirement?
I've seen different snippets demonstrating a Put message that returns unit with F#'s MailboxProcessor. In some, only the Post method is used while others use PostAndAsyncReply, with the reply channel immediately replying once the message is being processed. In doing some testing, I found a significant time lag when awaiting the reply, so it seems that unless you need a real reply, you should use Post.
Note: I started asking this in another thread but thought it useful to post as a full question. In the other thread, Tomas Petricek mentioned that the reply channel could be used a wait mechanism to ensure the caller delayed until the Put message was processed.
Does using PostAndAsyncReply help with message ordering, or is it just to force a pause until the first message is processed? In terms of performance Post appears the right solution. Is that accurate?
Update:
I just thought of a reason why PostAndAsyncReply might be necessary in the BlockingQueueAgent example: Scan is used to find Get messages when the queue is full, so you don't want to Put and then Get before the previous Put has completed.
I think I generally agree with your summary - it makes sense that PostAndAsyncReply is slower than Post, so if the caller doesn't need to get a notification from the agent when the operation (such as putting value into the queue) completes, it should definitely expose a way to do that using just Post. The fact that PostAndAsyncReply is a lot slower probably means that some agents should expose both options and let the caller decide.
Regarding the specific example of BlockingQueueAgent (or a similar one that I used to implement one-place buffer), the typical application of the agent is to solve the consumer-producer problem. In consumer-producer problem, we want to block the producer when the queue is full and block the consumer when it is empty. The .NET BlockingCollection supports only synchronous blocking, which is a bit bad (i.e. it can block the whole thread pool).
The using the BlockingQueueAgent that sends the Put messsage using PostAndAsyncReply, we can wait until the element is added to the queue asynchronously (so it blocks the producer, but without blocking threads!) An example of typical usage is the image processing pipeline that I wrote some time ago. Here is one snippet from that:
// Phase 2: Scale to a thumbnail size and add frame
let scalePipelinedImages = async {
while true do
let! info = loadedImages.AsyncGet()
scaleImage info
do! scaledImages.AsyncAdd(info) }
This loop repeatedly gets an image from the loadedImages queue, does some processing and writes the result to scaledImages. The blocking using the queue (both when reading and when writing) controls the parallelism, so that the steps of pipeline run in parallel, but it does not keep loading more and more images if the pipeline cannot handle them at the required speed.
My advice is to design your system so you can use Post as much as possible.
This technology was designed for asynchronous concurrency where the objective is to fire-and-forget messages. The idea of waiting for a response goes directly against the grain of this.