🎄 Happy Holidays! 🥳

Most of Solace is closed December 24–January 1 so our employees can spend time with their families. We will re-open Thursday, January 2, 2024. Please expect slower response times during this period and open a support ticket for anything needing immediate assistance.

Happy Holidays!

Please note: most of Solace is closed December 25–January 2, and will re-open Tuesday, January 3, 2023.

Each Message is not removing from Queue after acknowlegement Flow.Ack(message.ADMessageId)

Monjurul
Monjurul Member Posts: 3

Hi, I am consuming messages from queue using .net c# . I am using MessageAckMode.ClientAck. It's acknowledging with Flow.Ack(message.ADMessageId) immediately message recieving. But it is not removing each message after acknowledgement from queue. All messages are removing at once after the flow end.

Answers

  • nicholasdgoodman
    nicholasdgoodman Member, Employee Posts: 43 Solace Employee

    Greetings @Monjurul and welcome to the community!

    Can you provide some additional clarity on the timing of these operations? Acknowledgements generated by a consumer are not always immediately sent to the broker, but instead are sent once per second or whenever the transport window (a configurable number of messages) is 60% full — whichever occurs first. Any unsent acknowledgements are also sent whenever the flow is closed (as you note).

    Are you seeing messages remaining on the queue for greater than a second after acking? Would you like to see messages ack'ed more frequently? And lastly, can you share the code from your message handler?

  • Monjurul
    Monjurul Member Posts: 3
    edited May 22 #3

    I am following the github codes https://github.com/SolaceSamples/solace-samples-dotnet/blob/master/src/QueueConsumer/QueueConsumer.cs . I send 5 messages to the queue. And consumed by following codes. But it removes all the messages after consumed at once, not one by one.

    Flow = Session.CreateFlow(new FlowProperties()
    {
    AckMode = MessageAckMode.ClientAck,

    },
    Queue, null, HandleMessageEvent, HandleFlowEvent);
    Flow.Start();Console.WriteLine("Waiting for a message in the queue '{0}'...", queueName);

    WaitEventWaitHandle.WaitOne();

    private void HandleMessageEvent(object source, MessageEventArgs args)
    {
    // Received a message

     Console.WriteLine("Received message.");           
    using (IMessage message = args.Message)
    {


    try
    {
    // Expecting the message content as a binary attachment
    Console.WriteLine("Message content: {0}", Encoding.ASCII.GetString(message.BinaryAttachment));

    Flow.Ack(message.ADMessageId);

    Console.WriteLine($"Message acknowledged with message id :{message.ADMessageId}" );

    //finish the program
    WaitEventWaitHandle.Set();
    }
    catch (Exception ex)
    {
    Console.WriteLine("Error acknowledging message: {0}", ex.Message);
    }
    } public void HandleFlowEvent(object sender, FlowEventArgs args)
    {
    // Received a flow event
    Console.WriteLine("Received Flow Event '{0}' Type: '{1}' Text: '{2}'",
    args.Event,
    args.ResponseCode.ToString(),
    args.Info);
    }

    }

  • nicholasdgoodman
    nicholasdgoodman Member, Employee Posts: 43 Solace Employee

    So couple of things:

    The sample code found on the GitHub site is designed to exit after it receives (and acks) at least one message. The code would look a little different for a real consumer application, and the main application thread would never exit.

    I am guessing you are observing that the application is successfully pulling down several messages before exiting even though as-written it appears the code should only process one message per run.

    This has to do with the speed of the thread switching. Calling WaitEventWaitHandle.Set() does not actually immediately return control to the WaitEventWaitHandle.WaitOne() calling site (which is on the main thread). The message handler dispatch thread will have sufficient time to continue pulling, processing, and acking before the application can exit.

    You may be able to force the desired behavior by inserting a Thread.Yield() call after setting the wait handle, but this is also not fully guaranteed to work in all cases.

    I could provide sample code that can do different things, but what would you like to see the application do? Run and pull exactly one message off the queue, then exit?

  • Monjurul
    Monjurul Member Posts: 3

    The requirement is to receive message(and acknowledge) and remove it from the queue. If there are multiple messages, sequentially receive each message(and acknowledge) and remove it from the queue, then exit after all messages received.