Skip to content
38 changes: 19 additions & 19 deletions sdk/core/Azure.Core/src/Shared/NextLinkOperationImplementation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -98,20 +98,24 @@ public static IOperation Create(
AssertNotNull(pipeline, nameof(pipeline));

// TODO: Once we remove NextLinkOperationImplementation from internal shared and make it internal to Azure.Core only, we can access the internal members from RehydrationToken directly
var lroDetails = ModelReaderWriter.Write(rehydrationToken!, ModelReaderWriterOptions.Json).ToObjectFromJson<Dictionary<string, string>>();
var data = ModelReaderWriter.Write(rehydrationToken!, ModelReaderWriterOptions.Json);
using var document = JsonDocument.Parse(data);
var lroDetails = document.RootElement;

var initialUri = GetContentFromRehydrationToken(lroDetails, "initialUri");
// We are sure that the following properties exists in the serialized rehydrationToken
var initialUri = lroDetails.GetProperty("initialUri").GetString();
if (!Uri.TryCreate(initialUri, UriKind.Absolute, out var startRequestUri))
{
throw new ArgumentException($"\"initialUri\" property on \"rehydrationToken\" is an invalid Uri", nameof(rehydrationToken));
}

string nextRequestUri = GetContentFromRehydrationToken(lroDetails, "nextRequestUri");
string requestMethodStr = GetContentFromRehydrationToken(lroDetails, "requestMethod");
RequestMethod requestMethod = new RequestMethod(requestMethodStr);
string lastKnownLocation = GetContentFromRehydrationToken(lroDetails, "lastKnownLocation");
// We are sure that the following properties(apart from nullable lastKnownLocation) are not null as they are required in the rehydrationToken
string nextRequestUri = lroDetails.GetProperty("nextRequestUri").GetString()!;
string requestMethodStr = lroDetails.GetProperty("requestMethod").GetString()!;
RequestMethod requestMethod = new RequestMethod(requestMethodStr)!;
string? lastKnownLocation = lroDetails.GetProperty("lastKnownLocation").GetString();

string finalStateViaStr = GetContentFromRehydrationToken(lroDetails, "finalStateVia");
string finalStateViaStr = lroDetails.GetProperty("finalStateVia").GetString()!;
OperationFinalStateVia finalStateVia;
if (Enum.IsDefined(typeof(OperationFinalStateVia), finalStateViaStr))
{
Expand All @@ -122,7 +126,7 @@ public static IOperation Create(
finalStateVia = OperationFinalStateVia.Location;
}

string headerSourceStr = GetContentFromRehydrationToken(lroDetails, "headerSource");
string headerSourceStr = lroDetails.GetProperty("headerSource").GetString()!;
HeaderSource headerSource;
if (Enum.IsDefined(typeof(HeaderSource), headerSourceStr))
{
Expand All @@ -136,16 +140,6 @@ public static IOperation Create(
return new NextLinkOperationImplementation(pipeline, requestMethod, startRequestUri, nextRequestUri, headerSource, lastKnownLocation, finalStateVia, null, rehydrationToken.Id);
}

private static string GetContentFromRehydrationToken(Dictionary<string, string> lroDetails, string key)
{
if (!lroDetails.TryGetValue(key, out var nextRequestUri))
{
throw new ArgumentException($"\"{key}\" is missing from rehydrationToken");
}

return nextRequestUri;
}

private NextLinkOperationImplementation(
HttpPipeline pipeline,
RequestMethod requestMethod,
Expand Down Expand Up @@ -222,10 +216,16 @@ public static RehydrationToken GetRehydrationToken(
string finalStateVia,
string? operationId = null)
{
var data = new BinaryData(new { version = RehydrationTokenVersion, id = operationId, requestMethod = requestMethod.ToString(), initialUri = startRequestUri.AbsoluteUri, nextRequestUri, headerSource, lastKnownLocation, finalStateVia });
// TODO: Once we remove NextLinkOperationImplementation from internal shared and make it internal to Azure.Core only, we can access the internal members from RehydrationToken directly
var json = $$"""
{"version":"{{RehydrationTokenVersion}}","id":{{ConstructStringValue(operationId)}},"requestMethod":"{{requestMethod}}","initialUri":"{{startRequestUri.AbsoluteUri}}","nextRequestUri":"{{nextRequestUri}}","headerSource":"{{headerSource}}","finalStateVia":"{{finalStateVia}}","lastKnownLocation":{{ConstructStringValue(lastKnownLocation)}}}
""";
var data = new BinaryData(json);
return ModelReaderWriter.Read<RehydrationToken>(data);
}

private static string? ConstructStringValue(string? value) => value is null ? "null" : $"\"{value}\"";

public async ValueTask<OperationState> UpdateStateAsync(bool async, CancellationToken cancellationToken)
{
Response response = async
Expand Down