diff --git a/sdk/eventhub/Azure.Messaging.EventHubs.Shared/src/BlobCheckpointStore/BlobCheckpointStoreInternal.cs b/sdk/eventhub/Azure.Messaging.EventHubs.Shared/src/BlobCheckpointStore/BlobCheckpointStoreInternal.cs index c3a4156679a4..90a9d2a5f5cc 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs.Shared/src/BlobCheckpointStore/BlobCheckpointStoreInternal.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs.Shared/src/BlobCheckpointStore/BlobCheckpointStoreInternal.cs @@ -603,10 +603,6 @@ private async Task CreateLegacyCheckpoint(string fully { startingPosition ??= EventPosition.FromOffset(offset, false); } - else if (sequenceNumber.HasValue && sequenceNumber.Value != long.MinValue) - { - startingPosition = EventPosition.FromSequenceNumber(sequenceNumber.Value, false); - } else { // Skip checkpoints without an offset without logging an error. diff --git a/sdk/eventhub/Azure.Messaging.EventHubs.Shared/tests/BlobCheckpointStore/BlobsCheckpointStoreInternalTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs.Shared/tests/BlobCheckpointStore/BlobsCheckpointStoreInternalTests.cs index 4519fc88889b..00a664bf8a67 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs.Shared/tests/BlobCheckpointStore/BlobsCheckpointStoreInternalTests.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs.Shared/tests/BlobCheckpointStore/BlobsCheckpointStoreInternalTests.cs @@ -589,13 +589,13 @@ public async Task GetCheckpointUsesOffsetAsTheStartingPositionWhenPresentInLegac containerClient.AddBlobClient($"{FullyQualifiedNamespace}/{EventHubName}/{ConsumerGroup}/0", client => { client.Content = Encoding.UTF8.GetBytes("{" + - "\"PartitionId\":\"0\"," + - "\"Owner\":\"681d365b-de1b-4288-9733-76294e17daf0\"," + - "\"Token\":\"2d0c4276-827d-4ca4-a345-729caeca3b82\"," + - "\"Epoch\":386," + - "\"Offset\":\"13\"," + - "\"SequenceNumber\":960180" + - "}"); + "\"PartitionId\":\"0\"," + + "\"Owner\":\"681d365b-de1b-4288-9733-76294e17daf0\"," + + "\"Token\":\"2d0c4276-827d-4ca4-a345-729caeca3b82\"," + + "\"Epoch\":386," + + "\"Offset\":\"13\"," + + "\"SequenceNumber\":960180" + + "}"); }); var target = new BlobCheckpointStoreInternal(containerClient, initializeWithLegacyCheckpoints: true); @@ -606,6 +606,44 @@ public async Task GetCheckpointUsesOffsetAsTheStartingPositionWhenPresentInLegac Assert.That(checkpoint.PartitionId, Is.EqualTo("0")); } + /// + /// Verifies basic functionality of GetCheckpointAsync and ensures the starting position is set correctly. + /// + /// + [Test] + [TestCase(null)] + [TestCase("")] + public async Task GetCheckpointLegacyCheckpointWithoutOffset(string offsetValue) + { + var blobList = new List + { + BlobsModelFactory.BlobItem($"{FullyQualifiedNamespace}/{EventHubName}/{ConsumerGroup}/0", + false, + BlobsModelFactory.BlobItemProperties(true, lastModified: DateTime.UtcNow, eTag: new ETag(MatchingEtag)), + "snapshot") + }; + + var offsetJsonValue = offsetValue is null ? "null" : $"\"{offsetValue}\""; + var containerClient = new MockBlobContainerClient() { Blobs = blobList }; + + containerClient.AddBlobClient($"{FullyQualifiedNamespace}/{EventHubName}/{ConsumerGroup}/0", client => + { + client.Content = Encoding.UTF8.GetBytes("{" + + "\"PartitionId\":\"0\"," + + "\"Owner\":\"681d365b-de1b-4288-9733-76294e17daf0\"," + + "\"Token\":\"2d0c4276-827d-4ca4-a345-729caeca3b82\"," + + "\"Epoch\":386," + + $"\"Offset\":{offsetJsonValue}," + + "\"SequenceNumber\":960180" + + "}"); + }); + + var target = new BlobCheckpointStoreInternal(containerClient, initializeWithLegacyCheckpoints: true); + var checkpoint = await target.GetCheckpointAsync(FullyQualifiedNamespace, EventHubName, ConsumerGroup, "0", CancellationToken.None); + + Assert.That(checkpoint, Is.Null, "A checkpoint should have not been returned."); + } + /// /// Verifies basic functionality of GetCheckpointAsync and ensures the appropriate events are emitted on failure. /// diff --git a/sdk/eventhub/Azure.Messaging.EventHubs.sln b/sdk/eventhub/Azure.Messaging.EventHubs.sln index dd5634931f48..c4b8666c1d3a 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs.sln +++ b/sdk/eventhub/Azure.Messaging.EventHubs.sln @@ -67,8 +67,6 @@ Global EndGlobalSection GlobalSection(NestedProjects) = preSolution {327A0C67-D9B6-4831-A53F-BFE059934787} = {4C209B69-98C3-4B12-B777-111EFF0E6F66} - {AF73A238-61D1-4D1C-807F-57C19F193DC6} = {4C209B69-98C3-4B12-B777-111EFF0E6F66} - {5CFD80DB-98F3-4E59-9792-1C421786D3D0} = {4C209B69-98C3-4B12-B777-111EFF0E6F66} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {A9B7844C-B066-4B3D-A0E7-D5008C5EC232} diff --git a/sdk/eventhub/Microsoft.Azure.WebJobs.Extensions.EventHubs/CHANGELOG.md b/sdk/eventhub/Microsoft.Azure.WebJobs.Extensions.EventHubs/CHANGELOG.md index 503734d8782d..2ce2f5eca026 100644 --- a/sdk/eventhub/Microsoft.Azure.WebJobs.Extensions.EventHubs/CHANGELOG.md +++ b/sdk/eventhub/Microsoft.Azure.WebJobs.Extensions.EventHubs/CHANGELOG.md @@ -8,6 +8,8 @@ ### Bugs Fixed +- Fixed an issue where a legacy ownership record without checkpoint data was interpreted as a valid checkpoint and used to initialize a partition when no current generation checkpoint was present. + ### Other Changes ## 6.5.2 (2025-06-16)