minghuaw/azservicebus

Peeking on an empty Queue. Is it possible to return early

AhyaanTech opened this issue · 6 comments

When peeking on an empty queues it awaits for some time and gives the following error

warning: `rust_lib_azure` (lib test) generated 2 warnings (run `cargo fix --lib -p rust_lib_azure_bus --tests` to apply 2 suggestions)
    Finished `test` profile [unoptimized + debuginfo] target(s) in 2.44s
     Running unittests src\lib.rs (target\debug\deps\rust_lib_azure_bus-b9a918f953b77c77.exe)

running 1 test
test api::reciever::test::test_peek_messages ... ok

successes:

---- api::reciever::test::test_peek_messages stdout ----
Err(Error decoding from message

Caused by:
    Error decoding from message)

successes:
    api::reciever::test::test_peek_messages

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 12.79s

as you can see 12.79s is quite long. is it possible to return early before it tries to decode the message?

#[tokio::main]
pub async fn peek_messages(
    connection_string: String,
    queue_name: String,
    message_count: u32,
) -> anyhow::Result<Vec<AzureQueueMessage>> {
    let mut client = ServiceBusClient::new_from_connection_string(
        connection_string,
        ServiceBusClientOptions::default(),
    )
    .await?;

    let mut receiver = client
        .create_receiver_for_queue(queue_name, Default::default())
        .await?;

    let messages = receiver.peek_messages(message_count, None).await;

    match messages {
        Ok(messages) => {
            let azure_messages: Vec<AzureQueueMessage> = messages
                .iter()
                .map(|message| {
                    let message_id = message.message_id().map(|id| id.into_owned());

                    AzureQueueMessage {
                        system_properties: MessageSystemProperties {
                            message_id,
                            ..Default::default()
                        },
                        ..Default::default()
                    }
                })
                .collect();

            Result::Ok(azure_messages)
        }
        Err(error) => anyhow::bail!(error),
    }
}

As suggested here (https://learn.microsoft.com/en-us/answers/questions/222488/peeklock-empty-topic-queue-takes-longer-than-expec), the duration that the server waits before returning an empty response is determined by the timeout parameter in the request message, and this currently matches to the try_timeout parameter in ServiceBusClientOptions.

This, however, indeed shows two problems with the current implementation

  1. An empty peek message response is not interpreted properly
  2. The user should be able to set this timeout parameter

This is confirmed a bug after some investigation.

The SB server doesn't wait seem to wait for the whole duration of try_timeout before returning a response of NO_CONTENT, and other than the server response time, the long duration is also caused by:

  • the NO_CONTENT response is not interpreted properly
  • failing to decode the response causes the retry policy to retry the operation for 3 times (the default number of retries), and the retry policy waits for a short period of time before attempting the next retry

Fixing this does not require a breaking change.

@AhyaanTech This should be fixed in 0.20.1.

Please note that the expected behaviour is to get an empty vector if the queue is empty

Fixed!


running 1 test
test api::reciever::test::test_peek_messages ... ok

successes:

---- api::reciever::test::test_peek_messages stdout ----
Ok(
    [],
)

successes:
    api::reciever::test::test_peek_messages

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 1.28s