Extend Visibility Timeout
Extend the processing window for long-running queue operations.
When to Extend Visibility
Some tasks take longer than expected. Instead of setting an excessively long initial visibility timeout, you can extend the timeout mid-processing to prevent the message from being redelivered.
Extending the timeout before it lapses keeps a slow task hidden from other consumers until the consumer acknowledges.
Steps
Receive with Initial Visibility
resp, err := client.PollQueue(ctx, &kubemq.PollRequest{
Channel: "orders",
MaxItems: 1,
WaitTimeoutSeconds: 5,
VisibilitySeconds: 60,
})
if err != nil {
log.Fatal(err)
}response = client.receive_queue_messages(
channel="orders",
max_messages=1,
wait_timeout_in_seconds=5,
visibility_seconds=60,
)const messages = await client.receiveQueueMessages({
channel: 'orders',
maxMessages: 1,
waitTimeoutSeconds: 5,
visibilitySeconds: 60,
});ReceiveQueueMessagesResponse response = client.receiveQueueMessages(
ReceiveQueueMessagesRequest.builder()
.channel("orders")
.maxMessages(1)
.waitTimeoutSeconds(5)
.visibilitySeconds(60)
.build());var response = await client.ReceiveQueueMessagesAsync(new ReceiveQueueMessagesRequest
{
Channel = "orders",
MaxMessages = 1,
WaitTimeoutSeconds = 5,
VisibilitySeconds = 60,
});val response = client.receiveQueueMessages(
channel = "orders",
maxMessages = 1,
waitTimeoutSeconds = 5,
visibilitySeconds = 60
)auto response = client.receiveQueueMessages("orders", 1, 5, false, 60);// Poll the queue with explicit ack control (auto_ack = false).
let (response, mut receiver) = client
.poll_queue(PollRequest {
channel: "orders".to_string(),
max_items: 1,
wait_timeout_seconds: 5,
auto_ack: false,
})
.await?;receiver = client.create_downstream_receiver
response = receiver.poll(
KubeMQ::Queues::QueuePollRequest.new(
channel: 'orders',
max_items: 1,
wait_timeout: 5,
auto_ack: false
)
){:ok, poll} =
KubeMQ.Client.poll_queue(client,
channel: "orders",
max_items: 1,
wait_timeout: 5_000,
auto_ack: false
)Process and Extend When Needed
Before the visibility timeout expires, extend it to get more processing time.
for _, m := range resp.Messages {
fmt.Printf("Processing: %s\n", string(m.Message.Body))
// Phase 1: Quick validation
time.Sleep(10 * time.Second)
// Need more time — extend by 60 more seconds
if err := m.ExtendVisibility(60); err != nil {
log.Printf("Failed to extend visibility: %v", err)
}
fmt.Println("Visibility extended by 60 seconds")
// Phase 2: Heavy processing
time.Sleep(40 * time.Second)
}
resp.AckAll()
fmt.Println("Done — all messages acknowledged")for msg in response.messages:
print(f"Processing: {msg.body.decode('utf-8')}")
# Phase 1: Quick validation
time.sleep(10)
# Need more time — extend by 60 more seconds
msg.extend_visibility(60)
print("Visibility extended by 60 seconds")
# Phase 2: Heavy processing
time.sleep(40)
msg.ack()
print("Done — all messages acknowledged")for (const msg of messages) {
console.log('Processing:', new TextDecoder().decode(msg.body));
// Phase 1: Quick validation
await new Promise((r) => setTimeout(r, 10000));
// Need more time — extend by 60 more seconds
await msg.extendVisibility(60);
console.log('Visibility extended by 60 seconds');
// Phase 2: Heavy processing
await new Promise((r) => setTimeout(r, 40000));
await msg.ack();
}
console.log('Done — all messages acknowledged');for (QueueMessageReceived msg : response.getMessages()) {
System.out.println("Processing: " + new String(msg.getBody()));
Thread.sleep(10_000);
msg.extendVisibility(60);
System.out.println("Visibility extended by 60 seconds");
Thread.sleep(40_000);
msg.ack();
}
System.out.println("Done — all messages acknowledged");foreach (var msg in response.Messages)
{
Console.WriteLine($"Processing: {Encoding.UTF8.GetString(msg.Body.Span)}");
await Task.Delay(10_000);
await msg.ExtendVisibilityAsync(60);
Console.WriteLine("Visibility extended by 60 seconds");
await Task.Delay(40_000);
await msg.AckAsync();
}
Console.WriteLine("Done — all messages acknowledged");for (msg in response.messages) {
println("Processing: ${String(msg.body)}")
Thread.sleep(10_000)
msg.extendVisibility(60)
println("Visibility extended by 60 seconds")
Thread.sleep(40_000)
msg.ack()
}
println("Done — all messages acknowledged")for (const auto& msg : response.messages) {
std::cout << "Processing: " << msg.body << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(10));
msg.extendVisibility(60);
std::cout << "Visibility extended by 60 seconds" << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(40));
msg.ack();
}
std::cout << "Done — all messages acknowledged" << std::endl;// Extending an in-flight message's visibility is not yet available in the Rust SDK —
// the downstream message exposes ack(), nack(), and re_queue() only.
// Set a generous initial visibility on the poll, then ack once processing completes.
for msg in &response.messages {
println!("Processing: {}", String::from_utf8_lossy(&msg.message.body));
// Phase 1: Quick validation
tokio::time::sleep(std::time::Duration::from_secs(10)).await;
// Phase 2: Heavy processing
tokio::time::sleep(std::time::Duration::from_secs(40)).await;
msg.ack().await?;
}
println!("Done — all messages acknowledged");
receiver.close().await?;# Extending an in-flight message's visibility is not yet available in the Ruby SDK —
# each polled message exposes ack and nack, while requeue is settled at the
# response level via response.requeue_all(channel:).
# Set a generous initial visibility on the poll, then ack once processing completes.
response.messages.each do |msg|
puts "Processing: #{msg.body}"
# Phase 1: Quick validation
sleep(10)
# Phase 2: Heavy processing
sleep(40)
msg.ack
end
puts 'Done — all messages acknowledged'
receiver.close# Extending an in-flight message's visibility is not yet available in the Elixir SDK —
# PollResponse exposes ack_all/1, nack_all/1, and requeue_all/2 only.
# Set a generous initial visibility on the poll, then ack once processing completes.
Enum.each(poll.messages, fn msg ->
IO.puts("Processing: #{msg.body}")
# Phase 1: Quick validation
Process.sleep(10_000)
# Phase 2: Heavy processing
Process.sleep(40_000)
end)
{:ok, _} = KubeMQ.PollResponse.ack_all(poll)
IO.puts("Done — all messages acknowledged")Always extend visibility before the current timeout expires. Once the timeout lapses, the message may be delivered to another consumer, leading to duplicate processing.
Next Steps
Was this page helpful?