[edit: I have reformulated and simplified my original question]
I am using Azure service bus topic/subscriptions with sessions and I am having issue closing sessions.
For background information, my application receives data from a topic subscription session (FIFO requirement) which I keep alive most of the time. Only once in a while we need to 'pause' the data flow momentarily.
When this data flow 'pause' is requested, we exit the subscription session and wait to be asked to open the session again.
// pseudo code
public class Test
{
public static async Task Me()
{
var client = new SubscriptionClient(
EndPoint,
Path,
Name,
TokenProvider,
TransportType.Amqp,
ReceiveMode.PeekLock,
new RetryExponential(
minimumBackoff: TimeSpan.FromSeconds(1),
maximumBackoff: TimeSpan.FromSeconds(30),
maximumRetryCount: 10));
// Setup consumer options
var sessionOptions = new SessionHandlerOptions(OnHandleExceptionReceived)
{
AutoComplete = false,
MessageWaitTimeout = TimeSpan.FromSeconds(10),
MaxConcurrentSessions = 1,
};
// Registration 1 - Start data flow
client.RegisterSessionHandler(OnMessageSessionAsync, sessionOptions);
// Wait 1 - Artificially wait for 'data flow pause' to kick in.
// For the sake of this example, we artificially give plenty
// of time to the message session handler to receive something
// and close the session.
Task.Wait(TimeSpan.FromSeconds(30));
// Registration 2 - Artificially 'unpause' data flow
client.RegisterSessionHandler(OnMessageSessionAsync, sessionOptions);
// Wait 2 - Artificially wait for 'pause' to kick in again
Task.Wait(TimeSpan.FromSeconds(30));
// Finally close client
await client.CloseAsync();
}
private static async Task OnMessageSessionAsync(IMessageSession session, Message message, CancellationToken cancellationToken)
{
try
{
await client.CompleteAsync(message.SystemProperties.LockToken);
// Process message .. It doesn't matter what it is,
// just that at some point I want to break away from session
if (bool.TryParse(message.UserProperties["SessionCompleted"] as string, out bool completed) && completed)
await session.CloseAsync(); // <-- This never works
}
catch (Exception e)
{
Console.WriteLine("OnMessageSessionAsync exception: {0}", e);
// Indicates a problem, unlock message in subscription.
await client.AbandonAsync(message.SystemProperties.LockToken);
}
}
private static Task OnHandleExceptionReceived(ExceptionReceivedEventArgs e)
{
var context = e.ExceptionReceivedContext;
Options.Logger?.LogWarning(e.Exception, new StringBuilder()
.AppendLine($"Message handler encountered an exception {e.Exception.GetType().Name}.")
.AppendLine("Exception context for troubleshooting:")
.AppendLine($" - Endpoint: {context.Endpoint}")
.AppendLine($" - Entity Path: {context.EntityPath}")
.Append($" - Executing Action: {context.Action}"));
return Task.CompletedTask;
}
}
Questions :
As previously stated, I have an issue exiting the session as calling session.CloseAsync()
seems to be inoperative. Messages keep coming up even though I explicitly asked the session to stop.
- Is that normal behavior that a topic session cannot be directly closed ? If so, why expose the call
session.CloseAsync()
at all ? - Can I actually close a session independently from a subscription connection ?
ps1: I based my code on the official sample made available on github.com by Microsoft. And although this example is based on queue session rather than a topic session, it seems logical to me that the behavior should be identical.
ps2: I drilled down what could be the reason on Microsoft.Azure.ServiceBus repository and I wonder if there is a variable initialization missing under the hood of MessageSession.OwnsConnection
property ..