From 782a63167e6cf860827527ab5e0ce97b84722948 Mon Sep 17 00:00:00 2001 From: Nalu Tripician Date: Wed, 31 Aug 2022 15:15:44 -0400 Subject: [PATCH 1/5] Made CosmosOperationCanceledException Serializable --- .../CosmosOperationCanceledException.cs | 45 ++++++++++++++++++- .../CosmosOperationCanceledTests.cs | 43 ++++++++++++++++++ 2 files changed, 87 insertions(+), 1 deletion(-) create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosOperationCanceledTests.cs diff --git a/Microsoft.Azure.Cosmos/src/Resource/CosmosExceptions/CosmosOperationCanceledException.cs b/Microsoft.Azure.Cosmos/src/Resource/CosmosExceptions/CosmosOperationCanceledException.cs index 131c6c8203..ab8fd9bf17 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/CosmosExceptions/CosmosOperationCanceledException.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/CosmosExceptions/CosmosOperationCanceledException.cs @@ -6,18 +6,24 @@ namespace Microsoft.Azure.Cosmos { using System; using System.Collections; + using System.Diagnostics; + using System.Drawing.Printing; + using System.Runtime.Serialization; using System.Threading; using global::Azure.Core.Pipeline; + using Microsoft.Azure.Cosmos.ChangeFeed.LeaseManagement; using Microsoft.Azure.Cosmos.Diagnostics; using Microsoft.Azure.Cosmos.Telemetry; using Microsoft.Azure.Cosmos.Telemetry.Diagnostics; using Microsoft.Azure.Cosmos.Tracing; + using Newtonsoft.Json; /// /// The exception that is thrown in a thread upon cancellation of an operation that /// the thread was executing. This extends the OperationCanceledException to include the /// diagnostics of the operation that was canceled. - /// + /// + [Serializable] public class CosmosOperationCanceledException : OperationCanceledException { private readonly OperationCanceledException originalException; @@ -63,6 +69,22 @@ internal CosmosOperationCanceledException( this.lazyMessage = this.CreateLazyMessage(); } + /// + /// Initializes a new instance of the class. + /// + /// The SerializationInfo object that holds serialized object data for the exception being thrown. + /// The StreamingContext that contains contextual information about the source or destination. + protected CosmosOperationCanceledException(SerializationInfo info, StreamingContext context) + : base(info, context) + { + this.originalException = (OperationCanceledException)info.GetValue("originalException", typeof(OperationCanceledException)); + this.tokenCancellationRequested = (bool)info.GetValue("tokenCancellationRequested", typeof(bool)); + + this.toStringMessage = this.CreateToStringMessagDeserialized(); + this.lazyMessage = this.CreateLazyMessageDeserialized(); + this.Diagnostics = new CosmosTraceDiagnostics(NoOpTrace.Singleton); + } + /// public override string Source { @@ -112,6 +134,15 @@ private Lazy CreateToStringMessage() return new Lazy(() => $"{this.originalException}{Environment.NewLine}Cancellation Token has expired: {this.tokenCancellationRequested}. Learn more at: https://aka.ms/cosmosdb-tsg-request-timeout{Environment.NewLine}CosmosDiagnostics: {this.Diagnostics}"); } + private Lazy CreateLazyMessageDeserialized() + { + return new Lazy(() => $"{this.originalException.Message}{Environment.NewLine}Cancellation Token has expired: {this.tokenCancellationRequested}. Note that CosmosDiagnostics cannot be serialized. Learn more at: https://aka.ms/cosmosdb-tsg-request-timeout{Environment.NewLine}CosmosDiagnostics: {this.Diagnostics}"); + } + private Lazy CreateToStringMessagDeserialized() + { + return new Lazy(() => $"{this.originalException}{Environment.NewLine}Cancellation Token has expired: {this.tokenCancellationRequested}. Note that CosmosDiagnostics cannot be serialized. Learn more at: https://aka.ms/cosmosdb-tsg-request-timeout{Environment.NewLine}CosmosDiagnostics: {this.Diagnostics}"); + } + /// /// RecordOtelAttributes /// @@ -123,5 +154,17 @@ internal static void RecordOtelAttributes(CosmosOperationCanceledException excep scope.AddAttribute(OpenTelemetryAttributeKeys.RequestDiagnostics, exception.Diagnostics); scope.AddAttribute(OpenTelemetryAttributeKeys.ExceptionMessage, exception.GetBaseException().Message); } + + /// + /// Sets the System.Runtime.Serialization.SerializationInfo with information about the exception. + /// + /// The SerializationInfo object that holds serialized object data for the exception being thrown. + /// The StreamingContext that contains contextual information about the source or destination. + public override void GetObjectData(SerializationInfo info, StreamingContext context) + { + base.GetObjectData(info, context); + info.AddValue("originalException", this.originalException); + info.AddValue("tokenCancellationRequested", this.tokenCancellationRequested); + } } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosOperationCanceledTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosOperationCanceledTests.cs new file mode 100644 index 0000000000..d0e9697654 --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosOperationCanceledTests.cs @@ -0,0 +1,43 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Tests +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Runtime.Serialization.Formatters.Binary; + using System.Text; + using System.Threading.Tasks; + using Microsoft.Azure.Cosmos.Diagnostics; + using Microsoft.Azure.Cosmos.Tracing; //what is this? for the no op trace + using Microsoft.IdentityModel.Tokens; + using Microsoft.VisualStudio.TestTools.UnitTesting; + using Newtonsoft.Json; + + [TestClass] + public class CosmosOperationCanceledTests + { + + [TestMethod] + public void SerializationValidation() + { + //create test exception + CosmosOperationCanceledException originalException = new CosmosOperationCanceledException( + new OperationCanceledException("error message"), + new CosmosTraceDiagnostics(NoOpTrace.Singleton)); + + //serialize exception + string serialized = JsonConvert.SerializeObject(originalException); + + CosmosOperationCanceledException deserializedExceptoin = + JsonConvert.DeserializeObject(serialized); + + //Asserts + Assert.AreEqual(originalException.GetBaseException().Message, deserializedExceptoin.GetBaseException().Message); + Assert.AreEqual(originalException.GetBaseException().ToString(), deserializedExceptoin.GetBaseException().ToString()); + Assert.AreEqual(originalException.GetBaseException().HResult, deserializedExceptoin.GetBaseException().HResult); + } + } +} From ee899ea374b1cda613f5f48c6652b933433a1d8e Mon Sep 17 00:00:00 2001 From: Nalu Tripician Date: Thu, 1 Sep 2022 11:03:00 -0400 Subject: [PATCH 2/5] removed modified toString functions, added test to check tostring equality upon deserialization --- .../CosmosOperationCanceledException.cs | 20 +++++++------------ .../CosmosOperationCanceledTests.cs | 1 + 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/Resource/CosmosExceptions/CosmosOperationCanceledException.cs b/Microsoft.Azure.Cosmos/src/Resource/CosmosExceptions/CosmosOperationCanceledException.cs index ab8fd9bf17..d1102227d7 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/CosmosExceptions/CosmosOperationCanceledException.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/CosmosExceptions/CosmosOperationCanceledException.cs @@ -8,6 +8,7 @@ namespace Microsoft.Azure.Cosmos using System.Collections; using System.Diagnostics; using System.Drawing.Printing; + using System.Runtime.ConstrainedExecution; using System.Runtime.Serialization; using System.Threading; using global::Azure.Core.Pipeline; @@ -79,9 +80,9 @@ protected CosmosOperationCanceledException(SerializationInfo info, StreamingCont { this.originalException = (OperationCanceledException)info.GetValue("originalException", typeof(OperationCanceledException)); this.tokenCancellationRequested = (bool)info.GetValue("tokenCancellationRequested", typeof(bool)); - - this.toStringMessage = this.CreateToStringMessagDeserialized(); - this.lazyMessage = this.CreateLazyMessageDeserialized(); + this.lazyMessage = new Lazy(() => (string)info.GetValue("lazyMessage", typeof(string))); + this.toStringMessage = new Lazy(() => (string)info.GetValue("toStringMessage", typeof(string))); + //Diagnostics cannot be serialized this.Diagnostics = new CosmosTraceDiagnostics(NoOpTrace.Singleton); } @@ -133,16 +134,7 @@ private Lazy CreateToStringMessage() { return new Lazy(() => $"{this.originalException}{Environment.NewLine}Cancellation Token has expired: {this.tokenCancellationRequested}. Learn more at: https://aka.ms/cosmosdb-tsg-request-timeout{Environment.NewLine}CosmosDiagnostics: {this.Diagnostics}"); } - - private Lazy CreateLazyMessageDeserialized() - { - return new Lazy(() => $"{this.originalException.Message}{Environment.NewLine}Cancellation Token has expired: {this.tokenCancellationRequested}. Note that CosmosDiagnostics cannot be serialized. Learn more at: https://aka.ms/cosmosdb-tsg-request-timeout{Environment.NewLine}CosmosDiagnostics: {this.Diagnostics}"); - } - private Lazy CreateToStringMessagDeserialized() - { - return new Lazy(() => $"{this.originalException}{Environment.NewLine}Cancellation Token has expired: {this.tokenCancellationRequested}. Note that CosmosDiagnostics cannot be serialized. Learn more at: https://aka.ms/cosmosdb-tsg-request-timeout{Environment.NewLine}CosmosDiagnostics: {this.Diagnostics}"); - } - + /// /// RecordOtelAttributes /// @@ -165,6 +157,8 @@ public override void GetObjectData(SerializationInfo info, StreamingContext cont base.GetObjectData(info, context); info.AddValue("originalException", this.originalException); info.AddValue("tokenCancellationRequested", this.tokenCancellationRequested); + info.AddValue("lazyMessage", this.lazyMessage.Value); + info.AddValue("toStringMessage", this.toStringMessage.Value); } } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosOperationCanceledTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosOperationCanceledTests.cs index d0e9697654..ad8ee678b4 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosOperationCanceledTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosOperationCanceledTests.cs @@ -35,6 +35,7 @@ public void SerializationValidation() JsonConvert.DeserializeObject(serialized); //Asserts + Assert.AreEqual(originalException.ToString(), deserializedExceptoin.ToString()); Assert.AreEqual(originalException.GetBaseException().Message, deserializedExceptoin.GetBaseException().Message); Assert.AreEqual(originalException.GetBaseException().ToString(), deserializedExceptoin.GetBaseException().ToString()); Assert.AreEqual(originalException.GetBaseException().HResult, deserializedExceptoin.GetBaseException().HResult); From bebf6a0ffff1d2f34cd6f5e331ba2fd205eba93d Mon Sep 17 00:00:00 2001 From: Nalu Tripician Date: Thu, 1 Sep 2022 11:44:29 -0400 Subject: [PATCH 3/5] added message test --- .../Microsoft.Azure.Cosmos.Tests/CosmosOperationCanceledTests.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosOperationCanceledTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosOperationCanceledTests.cs index ad8ee678b4..37b323cdfe 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosOperationCanceledTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosOperationCanceledTests.cs @@ -36,6 +36,7 @@ public void SerializationValidation() //Asserts Assert.AreEqual(originalException.ToString(), deserializedExceptoin.ToString()); + Assert.AreEqual(originalException.Message, deserializedExceptoin.Message); Assert.AreEqual(originalException.GetBaseException().Message, deserializedExceptoin.GetBaseException().Message); Assert.AreEqual(originalException.GetBaseException().ToString(), deserializedExceptoin.GetBaseException().ToString()); Assert.AreEqual(originalException.GetBaseException().HResult, deserializedExceptoin.GetBaseException().HResult); From d887332f2e811794d5a6c75ed99e1996a0249de5 Mon Sep 17 00:00:00 2001 From: Nalu Tripician Date: Thu, 1 Sep 2022 11:50:46 -0400 Subject: [PATCH 4/5] cleaded up using --- .../CosmosExceptions/CosmosOperationCanceledException.cs | 7 ------- .../CosmosOperationCanceledTests.cs | 8 +------- 2 files changed, 1 insertion(+), 14 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/Resource/CosmosExceptions/CosmosOperationCanceledException.cs b/Microsoft.Azure.Cosmos/src/Resource/CosmosExceptions/CosmosOperationCanceledException.cs index d1102227d7..310616198c 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/CosmosExceptions/CosmosOperationCanceledException.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/CosmosExceptions/CosmosOperationCanceledException.cs @@ -6,18 +6,11 @@ namespace Microsoft.Azure.Cosmos { using System; using System.Collections; - using System.Diagnostics; - using System.Drawing.Printing; - using System.Runtime.ConstrainedExecution; using System.Runtime.Serialization; - using System.Threading; using global::Azure.Core.Pipeline; - using Microsoft.Azure.Cosmos.ChangeFeed.LeaseManagement; using Microsoft.Azure.Cosmos.Diagnostics; using Microsoft.Azure.Cosmos.Telemetry; - using Microsoft.Azure.Cosmos.Telemetry.Diagnostics; using Microsoft.Azure.Cosmos.Tracing; - using Newtonsoft.Json; /// /// The exception that is thrown in a thread upon cancellation of an operation that diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosOperationCanceledTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosOperationCanceledTests.cs index 37b323cdfe..5262c2b343 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosOperationCanceledTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosOperationCanceledTests.cs @@ -5,14 +5,8 @@ namespace Microsoft.Azure.Cosmos.Tests { using System; - using System.Collections.Generic; - using System.Linq; - using System.Runtime.Serialization.Formatters.Binary; - using System.Text; - using System.Threading.Tasks; using Microsoft.Azure.Cosmos.Diagnostics; - using Microsoft.Azure.Cosmos.Tracing; //what is this? for the no op trace - using Microsoft.IdentityModel.Tokens; + using Microsoft.Azure.Cosmos.Tracing; using Microsoft.VisualStudio.TestTools.UnitTesting; using Newtonsoft.Json; From 73d9bfc62305fd1bea924a3948f7e832a4064ebc Mon Sep 17 00:00:00 2001 From: Nalu Tripician Date: Thu, 1 Sep 2022 13:33:05 -0400 Subject: [PATCH 5/5] updates from running UpdateContracts.ps1 --- .../Contracts/DotNetSDKAPI.json | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json index bc28d53536..1a69454b04 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json @@ -3259,7 +3259,7 @@ }, "NestedTypes": {} }, - "Microsoft.Azure.Cosmos.CosmosOperationCanceledException;System.OperationCanceledException;IsAbstract:False;IsSealed:False;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": { + "Microsoft.Azure.Cosmos.CosmosOperationCanceledException;System.OperationCanceledException;IsAbstract:False;IsSealed:False;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:True": { "Subclasses": {}, "Members": { "Microsoft.Azure.Cosmos.CosmosDiagnostics Diagnostics": { @@ -3339,6 +3339,11 @@ "Attributes": [], "MethodInfo": "[Void .ctor(System.OperationCanceledException, Microsoft.Azure.Cosmos.CosmosDiagnostics), Void .ctor(System.OperationCanceledException, Microsoft.Azure.Cosmos.CosmosDiagnostics)]" }, + "Void GetObjectData(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)": { + "Type": "Method", + "Attributes": [], + "MethodInfo": "Void GetObjectData(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext);IsAbstract:False;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, "Void set_HelpLink(System.String)": { "Type": "Method", "Attributes": [],