Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change Feed / Processor AVAD: Fixes timeToLiveExpired missing from metadata #4523

Merged
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
537624a
longrunning cfp avad test for ttl
philipthomas-MSFT Jun 3, 2024
c6981fa
add more to comment
philipthomas-MSFT Jun 3, 2024
d8da605
internal set
philipthomas-MSFT Jun 3, 2024
cce1f30
other tests fail with higher ms
philipthomas-MSFT Jun 3, 2024
a5efaed
run updatecontracts
philipthomas-MSFT Jun 3, 2024
55c5429
Merge branch 'master' into 4510-change-feed-processor-avad-ttl-istime…
philipthomas-MSFT Jun 3, 2024
3e9820e
Update Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTe…
philipthomas-MSFT Jun 4, 2024
4b52819
Update Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTe…
philipthomas-MSFT Jun 4, 2024
cc171fe
Update Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTe…
philipthomas-MSFT Jun 4, 2024
22633f6
Update Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTe…
philipthomas-MSFT Jun 4, 2024
696176a
using Logger.LogLine
philipthomas-MSFT Jun 4, 2024
441bef7
change back over to ManualResetEvent. fixed assert to look at Previou…
philipthomas-MSFT Jun 6, 2024
b06cb0a
Update GetChangeFeedProcessorBuilderWithAllVersionsAndDeletesTests.cs
philipthomas-MSFT Jun 10, 2024
479f75e
Merge branch 'master' into 4510-change-feed-processor-avad-ttl-istime…
philipthomas-MSFT Jun 12, 2024
4ea8aea
try/finally
philipthomas-MSFT Jun 12, 2024
32be9fa
removing ctor. making all set internal to address serialization issue…
philipthomas-MSFT Jun 14, 2024
1cf88de
fixing de/serialziation issue
philipthomas-MSFT Jun 14, 2024
29a6c17
Merge branch 'master' into 4510-change-feed-processor-avad-ttl-istime…
philipthomas-MSFT Jun 14, 2024
c85ea87
commit
philipthomas-MSFT Jun 17, 2024
6e129bb
Merge branch 'master' into 4510-change-feed-processor-avad-ttl-istime…
philipthomas-MSFT Jun 17, 2024
ada194e
Update GetChangeFeedProcessorBuilderWithAllVersionsAndDeletesTests.cs
philipthomas-MSFT Jun 17, 2024
2a5a30a
Update ReEncryption.csproj
philipthomas-MSFT Jun 17, 2024
d7d1dc4
Merge branch 'master' into 4510-change-feed-processor-avad-ttl-istime…
philipthomas-MSFT Jun 17, 2024
4d06310
internal set change to CanWrite:True;
philipthomas-MSFT Jun 17, 2024
f625588
Merge branch 'master' into 4510-change-feed-processor-avad-ttl-istime…
philipthomas-MSFT Jun 18, 2024
3626726
Merge branch 'master' into 4510-change-feed-processor-avad-ttl-istime…
philipthomas-MSFT Jun 18, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -19,55 +19,36 @@ namespace Microsoft.Azure.Cosmos
#endif
class ChangeFeedMetadata
{
/// <summary>
/// New instance of meta data for <see cref="ChangeFeedItem{T}"/> created.
/// </summary>
/// <param name="conflictResolutionTimestamp"></param>
/// <param name="lsn"></param>
/// <param name="operationType"></param>
/// <param name="previousLsn"></param>
public ChangeFeedMetadata(
DateTime conflictResolutionTimestamp,
long lsn,
ChangeFeedOperationType operationType,
long previousLsn)
{
this.ConflictResolutionTimestamp = conflictResolutionTimestamp;
this.Lsn = lsn;
this.OperationType = operationType;
this.PreviousLsn = previousLsn;
}

/// <summary>
/// The conflict resolution timestamp.
/// </summary>
[JsonProperty(PropertyName = "crts", NullValueHandling = NullValueHandling.Ignore)]
[JsonConverter(typeof(UnixDateTimeConverter))]
public DateTime ConflictResolutionTimestamp { get; }
public DateTime ConflictResolutionTimestamp { get; internal set; }

/// <summary>
/// The current logical sequence number.
/// </summary>
[JsonProperty(PropertyName = "lsn", NullValueHandling = NullValueHandling.Ignore)]
public long Lsn { get; }
public long Lsn { get; internal set; }

/// <summary>
/// The change feed operation type.
/// </summary>
[JsonProperty(PropertyName = "operationType")]
[JsonConverter(typeof(StringEnumConverter))]
public ChangeFeedOperationType OperationType { get; }
public ChangeFeedOperationType OperationType { get; internal set; }

/// <summary>
/// The previous logical sequence number.
/// </summary>
[JsonProperty(PropertyName = "previousImageLSN", NullValueHandling = NullValueHandling.Ignore)]
public long PreviousLsn { get; }
public long PreviousLsn { get; internal set; }

/// <summary>
/// Used to distinquish explicit deletes (e.g. via DeleteItem) from deletes caused by TTL expiration (a collection may define time-to-live policy for documents).
/// </summary>
[JsonProperty(PropertyName = "timeToLiveExpired", NullValueHandling= NullValueHandling.Ignore)]
public bool IsTimeToLiveExpired { get; }
public bool IsTimeToLiveExpired { get; internal set; }
philipthomas-MSFT marked this conversation as resolved.
Show resolved Hide resolved
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,14 @@ namespace Microsoft.Azure.Cosmos.SDK.EmulatorTests.ChangeFeed
{
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Azure.Cosmos.ChangeFeed.Utils;
using Microsoft.Azure.Cosmos.Services.Management.Tests;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

[TestClass]
Expand All @@ -29,6 +32,115 @@ public async Task Cleanup()
await base.TestCleanup();
}

[TestMethod]
philipthomas-MSFT marked this conversation as resolved.
Show resolved Hide resolved
[Timeout(300000)]
[TestCategory("LongRunning")]
[Owner("philipthomas-MSFT")]
[Description("Scenario: When a document is created with ttl set, there should be 1 create and 1 delete that will appear for that " +
"document when using ChangeFeedProcessor with AllVersionsAndDeletes set as the ChangeFeedMode.")]
public async Task WhenADocumentIsCreatedWithTtlSetThenTheDocumentIsDeletedTestsAsync()
{
ContainerInternal monitoredContainer = await this.CreateMonitoredContainer(ChangeFeedMode.AllVersionsAndDeletes);
kirankumarkolli marked this conversation as resolved.
Show resolved Hide resolved
Exception exception = default;
int ttlInSeconds = 5;
Stopwatch stopwatch = new();
philipthomas-MSFT marked this conversation as resolved.
Show resolved Hide resolved
ManualResetEvent allDocsProcessed = new ManualResetEvent(false);
philipthomas-MSFT marked this conversation as resolved.
Show resolved Hide resolved

ChangeFeedProcessor processor = monitoredContainer
.GetChangeFeedProcessorBuilderWithAllVersionsAndDeletes(processorName: "processor", onChangesDelegate: (ChangeFeedProcessorContext context, IReadOnlyCollection<ChangeFeedItem<dynamic>> docs, CancellationToken token) =>
{
// NOTE(philipthomas-MSFT): Please allow these Logger.LogLine because TTL on items will purge at random times so I am using this to test when ran locally using emulator.

Logger.LogLine($"@ {DateTime.Now}, {nameof(stopwatch)} -> CFP AVAD took '{stopwatch.ElapsedMilliseconds}' to read document CRUD in feed.");
Logger.LogLine($"@ {DateTime.Now}, {nameof(docs)} -> {JsonConvert.SerializeObject(docs)}");

foreach (ChangeFeedItem<dynamic> change in docs)
{
if (change.Metadata.OperationType == ChangeFeedOperationType.Create)
{
// current
Assert.AreEqual(expected: "1", actual: change.Current.id.ToString());
Assert.AreEqual(expected: "1", actual: change.Current.pk.ToString());
Assert.AreEqual(expected: "Testing TTL on CFP.", actual: change.Current.description.ToString());
Assert.AreEqual(expected: ttlInSeconds, actual: change.Current.ttl.ToObject<int>());
philipthomas-MSFT marked this conversation as resolved.
Show resolved Hide resolved

// metadata
Assert.IsTrue(DateTime.TryParse(s: change.Metadata.ConflictResolutionTimestamp.ToString(), out _), message: "Invalid csrt must be a datetime value.");
Assert.IsTrue(change.Metadata.Lsn > 0, message: "Invalid lsn must be a long value.");
Assert.IsFalse(change.Metadata.IsTimeToLiveExpired);

// previous
Assert.IsNull(change.Previous);
philipthomas-MSFT marked this conversation as resolved.
Show resolved Hide resolved
}
else if (change.Metadata.OperationType == ChangeFeedOperationType.Delete)
{
// current
Assert.IsNull(change.Current.id);

// metadata
Assert.IsTrue(DateTime.TryParse(s: change.Metadata.ConflictResolutionTimestamp.ToString(), out _), message: "Invalid csrt must be a datetime value.");
Assert.IsTrue(change.Metadata.Lsn > 0, message: "Invalid lsn must be a long value.");
Assert.IsTrue(change.Metadata.IsTimeToLiveExpired);

// previous
Assert.AreEqual(expected: "1", actual: change.Previous.id.ToString());
Assert.AreEqual(expected: "1", actual: change.Previous.pk.ToString());
Assert.AreEqual(expected: "Testing TTL on CFP.", actual: change.Previous.description.ToString());
Assert.AreEqual(expected: ttlInSeconds, actual: change.Previous.ttl.ToObject<int>());

// stop after reading delete since it is the last document in feed.
stopwatch.Stop();
allDocsProcessed.Set();
}
else
{
Assert.Fail("Invalid operation.");
}
}

return Task.CompletedTask;
})
.WithInstanceName(Guid.NewGuid().ToString())
.WithLeaseContainer(this.LeaseContainer)
.WithErrorNotification((leaseToken, error) =>
{
exception = error.InnerException;

return Task.CompletedTask;
})
.Build();

stopwatch.Start();

// NOTE(philipthomas-MSFT): Please allow these Logger.LogLine because TTL on items will purge at random times so I am using this to test when ran locally using emulator.

Logger.LogLine($"@ {DateTime.Now}, CFProcessor starting...");

await processor.StartAsync();

try
{
await Task.Delay(GetChangeFeedProcessorBuilderWithAllVersionsAndDeletesTests.ChangeFeedSetupTime);
await monitoredContainer.CreateItemAsync<dynamic>(new { id = "1", pk = "1", description = "Testing TTL on CFP.", ttl = ttlInSeconds }, partitionKey: new PartitionKey("1"));

// NOTE(philipthomas-MSFT): Please allow these Logger.LogLine because TTL on items will purge at random times so I am using this to test when ran locally using emulator.

Logger.LogLine($"@ {DateTime.Now}, Document created.");

bool receivedDelete = allDocsProcessed.WaitOne(250000);
Assert.IsTrue(receivedDelete, "Timed out waiting for docs to process");

if (exception != default)
{
Assert.Fail(exception.ToString());
}
}
finally
{
await processor.StopAsync();
}
}

[TestMethod]
[Owner("philipthomas-MSFT")]
[Description("Scenario: When a document is created, then updated, and finally deleted, there should be 3 changes that will appear for that " +
Expand Down Expand Up @@ -467,6 +579,7 @@ private async Task<ContainerInternal> CreateMonitoredContainer(ChangeFeedMode ch
if (changeFeedMode == ChangeFeedMode.AllVersionsAndDeletes)
{
properties.ChangeFeedPolicy.FullFidelityRetention = TimeSpan.FromMinutes(5);
properties.DefaultTimeToLive = -1;
}

ContainerResponse response = await this.database.CreateContainerAsync(properties,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@
"Attributes": [
"JsonPropertyAttribute"
],
"MethodInfo": "Boolean IsTimeToLiveExpired;CanRead:True;CanWrite:False;Boolean get_IsTimeToLiveExpired();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;"
"MethodInfo": "Boolean IsTimeToLiveExpired;CanRead:True;CanWrite:True;Boolean get_IsTimeToLiveExpired();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;"
philipthomas-MSFT marked this conversation as resolved.
Show resolved Hide resolved
philipthomas-MSFT marked this conversation as resolved.
Show resolved Hide resolved
},
"Int64 get_Lsn()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": {
"Type": "Method",
Expand Down
Loading