Skip to content

Commit aec3e1e

Browse files
authored
[FormRecognizer] Updated LROs to use new OperationInternal class (#22629)
1 parent d15db31 commit aec3e1e

8 files changed

+250
-518
lines changed

sdk/formrecognizer/Azure.AI.FormRecognizer/src/Azure.AI.FormRecognizer.csproj

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
<Compile Include="$(AzureCoreSharedSources)DiagnosticScope.cs" Link="Shared\%(RecursiveDir)\%(Filename)%(Extension)" />
2626
<Compile Include="$(AzureCoreSharedSources)DiagnosticScopeFactory.cs" Link="Shared\%(RecursiveDir)\%(Filename)%(Extension)" />
2727
<Compile Include="$(AzureCoreSharedSources)HttpMessageSanitizer.cs" Link="Shared\%(RecursiveDir)\%(Filename)%(Extension)" />
28-
<Compile Include="$(AzureCoreSharedSources)OperationHelpers.cs" Link="Shared\%(RecursiveDir)\%(Filename)%(Extension)" />
2928
<Compile Include="$(AzureCoreSharedSources)OperationInternal.cs" Link="Shared\%(RecursiveDir)\%(Filename)%(Extension)" />
3029
<Compile Include="$(AzureCoreSharedSources)TaskExtensions.cs" Link="Shared\%(RecursiveDir)\%(Filename)%(Extension)" />
3130
</ItemGroup>

sdk/formrecognizer/Azure.AI.FormRecognizer/src/CopyModelOperation.cs

Lines changed: 35 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -14,23 +14,16 @@ namespace Azure.AI.FormRecognizer.Training
1414
/// <summary>
1515
/// Tracks the status of a long-running operation for copying a custom model into a target Form Recognizer resource.
1616
/// </summary>
17-
public class CopyModelOperation : Operation<CustomFormModelInfo>
17+
public class CopyModelOperation : Operation<CustomFormModelInfo>, IOperation<CustomFormModelInfo>
1818
{
19+
private readonly OperationInternal<CustomFormModelInfo> _operationInternal;
20+
1921
/// <summary>Provides communication with the Form Recognizer Azure Cognitive Service through its REST API.</summary>
2022
private readonly FormRecognizerRestClient _serviceClient;
2123

2224
/// <summary>Provides tools for exception creation in case of failure.</summary>
2325
private readonly ClientDiagnostics _diagnostics;
2426

25-
/// <summary>The last HTTP response received from the server. <c>null</c> until the first response is received.</summary>
26-
private Response _response;
27-
28-
/// <summary>The result of the long-running operation. <c>null</c> until result is received on status update.</summary>
29-
private CustomFormModelInfo _value;
30-
31-
/// <summary><c>true</c> if the long-running operation has completed. Otherwise, <c>false</c>.</summary>
32-
private bool _hasCompleted;
33-
3427
/// <summary>The ID of the model to use for copy.</summary>
3528
private readonly string _modelId;
3629

@@ -40,8 +33,6 @@ public class CopyModelOperation : Operation<CustomFormModelInfo>
4033
/// <summary>An ID representing the operation that can be used along with <see cref="_modelId"/> to poll for the status of the long-running operation.</summary>
4134
private readonly string _resultId;
4235

43-
private RequestFailedException _requestFailedException;
44-
4536
/// <summary>
4637
/// Gets an ID representing the operation that can be used to poll for the status
4738
/// of the long-running operation.
@@ -54,28 +45,17 @@ public class CopyModelOperation : Operation<CustomFormModelInfo>
5445
/// <remarks>
5546
/// This property can be accessed only after the operation completes successfully (HasValue is true).
5647
/// </remarks>
57-
public override CustomFormModelInfo Value
58-
{
59-
get
60-
{
61-
if (HasCompleted && !HasValue)
62-
#pragma warning disable CA1065 // Do not raise exceptions in unexpected locations
63-
throw _requestFailedException;
64-
#pragma warning restore CA1065 // Do not raise exceptions in unexpected locations
65-
else
66-
return OperationHelpers.GetValue(ref _value);
67-
}
68-
}
48+
public override CustomFormModelInfo Value => _operationInternal.Value;
6949

7050
/// <summary>
7151
/// Returns true if the long-running operation completed.
7252
/// </summary>
73-
public override bool HasCompleted => _hasCompleted;
53+
public override bool HasCompleted => _operationInternal.HasCompleted;
7454

7555
/// <summary>
7656
/// Returns true if the long-running operation completed successfully and has produced final result (accessible by Value property).
7757
/// </summary>
78-
public override bool HasValue => _value != null;
58+
public override bool HasValue => _operationInternal.HasValue;
7959

8060
/// <summary>
8161
/// Initializes a new instance of the <see cref="CopyModelOperation"/> class which
@@ -92,6 +72,7 @@ public CopyModelOperation(string operationId, string targetModelId, FormTraining
9272
_serviceClient = client.ServiceClient;
9373
_diagnostics = client.Diagnostics;
9474
_targetModelId = targetModelId;
75+
_operationInternal = new(_diagnostics, this, rawResponse: null);
9576

9677
// TODO: Use regex to parse ids.
9778
// https://github.com/Azure/azure-sdk-for-net/issues/11505
@@ -124,6 +105,7 @@ internal CopyModelOperation(FormRecognizerRestClient serviceClient, ClientDiagno
124105
_serviceClient = serviceClient;
125106
_diagnostics = diagnostics;
126107
_targetModelId = targetModelId;
108+
_operationInternal = new(_diagnostics, this, rawResponse: null);
127109

128110
// TODO: Use regex to parse ids.
129111
// https://github.com/Azure/azure-sdk-for-net/issues/11505
@@ -160,7 +142,7 @@ protected CopyModelOperation()
160142
/// An instance of <see cref="CopyModelOperation"/> sends requests to a server in UpdateStatusAsync, UpdateStatus, and other methods.
161143
/// Responses from these requests can be accessed using GetRawResponse.
162144
/// </remarks>
163-
public override Response GetRawResponse() => _response;
145+
public override Response GetRawResponse() => _operationInternal.RawResponse;
164146

165147
/// <summary>
166148
/// Periodically calls the server till the long-running operation completes.
@@ -170,8 +152,8 @@ protected CopyModelOperation()
170152
/// <remarks>
171153
/// This method will periodically call UpdateStatusAsync till HasCompleted is true, then return the final result of the operation.
172154
/// </remarks>
173-
public override ValueTask<Response<CustomFormModelInfo>> WaitForCompletionAsync(CancellationToken cancellationToken = default) =>
174-
this.DefaultWaitForCompletionAsync(cancellationToken);
155+
public override async ValueTask<Response<CustomFormModelInfo>> WaitForCompletionAsync(CancellationToken cancellationToken = default) =>
156+
await _operationInternal.WaitForCompletionAsync(cancellationToken).ConfigureAwait(false);
175157

176158
/// <summary>
177159
/// Periodically calls the server till the long-running operation completes.
@@ -186,8 +168,8 @@ public override ValueTask<Response<CustomFormModelInfo>> WaitForCompletionAsync(
186168
/// <remarks>
187169
/// This method will periodically call UpdateStatusAsync till HasCompleted is true, then return the final result of the operation.
188170
/// </remarks>
189-
public override ValueTask<Response<CustomFormModelInfo>> WaitForCompletionAsync(TimeSpan pollingInterval, CancellationToken cancellationToken = default) =>
190-
this.DefaultWaitForCompletionAsync(pollingInterval, cancellationToken);
171+
public override async ValueTask<Response<CustomFormModelInfo>> WaitForCompletionAsync(TimeSpan pollingInterval, CancellationToken cancellationToken = default) =>
172+
await _operationInternal.WaitForCompletionAsync(pollingInterval, cancellationToken).ConfigureAwait(false);
191173

192174
/// <summary>
193175
/// Calls the server to get updated status of the long-running operation.
@@ -198,7 +180,7 @@ public override ValueTask<Response<CustomFormModelInfo>> WaitForCompletionAsync(
198180
/// This operation will update the value returned from GetRawResponse and might update HasCompleted, HasValue, and Value.
199181
/// </remarks>
200182
public override Response UpdateStatus(CancellationToken cancellationToken = default) =>
201-
UpdateStatusAsync(false, cancellationToken).EnsureCompleted();
183+
_operationInternal.UpdateStatus(cancellationToken);
202184

203185
/// <summary>
204186
/// Calls the server to get updated status of the long-running operation.
@@ -209,52 +191,32 @@ public override Response UpdateStatus(CancellationToken cancellationToken = defa
209191
/// This operation will update the value returned from GetRawResponse and might update HasCompleted, HasValue, and Value.
210192
/// </remarks>
211193
public override async ValueTask<Response> UpdateStatusAsync(CancellationToken cancellationToken = default) =>
212-
await UpdateStatusAsync(true, cancellationToken).ConfigureAwait(false);
194+
await _operationInternal.UpdateStatusAsync(cancellationToken).ConfigureAwait(false);
213195

214-
/// <summary>
215-
/// Calls the server to get updated status of the long-running operation.
216-
/// </summary>
217-
/// <param name="async">When <c>true</c>, the method will be executed asynchronously; otherwise, it will execute synchronously.</param>
218-
/// <param name="cancellationToken">A <see cref="CancellationToken"/> used for the service call.</param>
219-
/// <returns>The HTTP response received from the server.</returns>
220-
private async ValueTask<Response> UpdateStatusAsync(bool async, CancellationToken cancellationToken)
196+
async ValueTask<OperationState<CustomFormModelInfo>> IOperation<CustomFormModelInfo>.UpdateStateAsync(bool async, CancellationToken cancellationToken)
221197
{
222-
if (!_hasCompleted)
198+
Response<CopyOperationResult> response = async
199+
? await _serviceClient.GetCustomModelCopyResultAsync(new Guid(_modelId), new Guid(_resultId), cancellationToken).ConfigureAwait(false)
200+
: _serviceClient.GetCustomModelCopyResult(new Guid(_modelId), new Guid(_resultId), cancellationToken);
201+
202+
OperationStatus status = response.Value.Status;
203+
Response rawResponse = response.GetRawResponse();
204+
205+
if (status == OperationStatus.Succeeded)
206+
{
207+
return OperationState<CustomFormModelInfo>.Success(rawResponse,
208+
ConvertValue(response.Value, _targetModelId, CustomFormModelStatus.Ready));
209+
}
210+
else if (status == OperationStatus.Failed)
223211
{
224-
using DiagnosticScope scope = _diagnostics.CreateScope($"{nameof(CopyModelOperation)}.{nameof(UpdateStatus)}");
225-
scope.Start();
226-
227-
try
228-
{
229-
Response<CopyOperationResult> update = async
230-
? await _serviceClient.GetCustomModelCopyResultAsync(new Guid(_modelId), new Guid(_resultId), cancellationToken).ConfigureAwait(false)
231-
: _serviceClient.GetCustomModelCopyResult(new Guid(_modelId), new Guid(_resultId), cancellationToken);
232-
233-
_response = update.GetRawResponse();
234-
235-
if (update.Value.Status == OperationStatus.Succeeded)
236-
{
237-
// We need to first assign a value and then mark the operation as completed to avoid a race condition with the getter in Value
238-
_value = ConvertValue(update.Value, _targetModelId, CustomFormModelStatus.Ready);
239-
_hasCompleted = true;
240-
}
241-
else if (update.Value.Status == OperationStatus.Failed)
242-
{
243-
_requestFailedException = await ClientCommon
244-
.CreateExceptionForFailedOperationAsync(async, _diagnostics, _response, update.Value.CopyResult.Errors)
245-
.ConfigureAwait(false);
246-
_hasCompleted = true;
247-
throw _requestFailedException;
248-
}
249-
}
250-
catch (Exception e)
251-
{
252-
scope.Failed(e);
253-
throw;
254-
}
212+
RequestFailedException requestFailedException = await ClientCommon
213+
.CreateExceptionForFailedOperationAsync(async, _diagnostics, rawResponse, response.Value.CopyResult.Errors)
214+
.ConfigureAwait(false);
215+
216+
return OperationState<CustomFormModelInfo>.Failure(rawResponse, requestFailedException);
255217
}
256218

257-
return GetRawResponse();
219+
return OperationState<CustomFormModelInfo>.Pending(rawResponse);
258220
}
259221

260222
private static CustomFormModelInfo ConvertValue(CopyOperationResult result, string modelId, CustomFormModelStatus status)

0 commit comments

Comments
 (0)