@@ -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