-
Notifications
You must be signed in to change notification settings - Fork 542
Description
Expected Behavior
When using Event Hubs as a pubsub or binding, messages should be delivered in the order they were posted (assume PartitionKey is set when publishing/posting to ensure ordering across partitions.)
Actual Behavior
In the pubsub case, the sidecar delivers new events before the subscriber has completed handling the last one. This causes major problems when trying to ensure order sensitive work is executed correctly (e.g. starting a workflow to process subsequent events.)
Steps to Reproduce the Problem
We're publishing to our topic like this (dotnet sdk):
await dapr.PublishEventAsync(
WellKnownPubSubNames.Percept,
WellKnownPubSubTopics.RecordingSessionFileEventV1,
data,
new Dictionary<string, string>
{
{ "partitionKey", data.DeviceId }
}
);and receiving like this:
pubsub.MapPost(
WellKnownPubSubTopics.RecordingSessionFileEventV1,
[Topic(WellKnownPubSubNames.Percept, WellKnownPubSubTopics.RecordingSessionFileEventV1)]
async (
[FromServices] ILogger<Program> logger,
[FromServices] IRecordingSessionRepository recordingSessionRepository,
HttpContext HttpContext,
[FromBody] RecordingSessionFileEventV1 data
) => {
try {
var messageId = HttpContext.Request.Headers["Message-Id"];
logger.LogInformation("Start message id: {messageId}", messageId!);
await Task.Delay(500);
logger.LogInformation("Stop message id: {messageId}", messageId!);
return Results.Ok();
}
catch (Exception ex) {
logger.LogError(ex);
return Results.Problem(ex.Message);
}
}
);The problem is clear when watching the logs: instead of seeing a constant start/stop/start/stop alternating sequence of log events, we're seeing start/stop/start/start/stop/stop interleaving. The sidecar should not be sending another event until the current one has completed processing, i.e. it receives a http 200 (in this case.)
The same issue likely occurs for the binding since the common code is the problem (according to @yaron2):
It appears our implementation is using goroutines for each message, which would cause out-of-order delivery: https://github.com/dapr/components-contrib/blob/main/common/component/azure/eventhubs/eventhubs.go#L293. We do have a concurrency mechanism for components, it just hasn't been applied to Event Hubs. This should be an easy change - can you please open an issue in components-contrib for this? I'll add it to the v1.15 milestone
Release Note
PubSub and Binding components using ordered delivery (with a partitionkey) would interleave event deliveries to a subscriber. Now the sidecar will wait until the handler returns before sending the next event.
RELEASE NOTE: