@azure/core-lro 3.0.0-beta.1 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser/http/models.d.ts +2 -2
- package/dist/browser/http/models.d.ts.map +1 -1
- package/dist/browser/http/models.js.map +1 -1
- package/dist/browser/http/operation.d.ts +11 -12
- package/dist/browser/http/operation.d.ts.map +1 -1
- package/dist/browser/http/operation.js +22 -16
- package/dist/browser/http/operation.js.map +1 -1
- package/dist/browser/http/poller.d.ts +2 -2
- package/dist/browser/http/poller.d.ts.map +1 -1
- package/dist/browser/http/poller.js +1 -15
- package/dist/browser/http/poller.js.map +1 -1
- package/dist/browser/index.d.ts +1 -1
- package/dist/browser/index.d.ts.map +1 -1
- package/dist/browser/index.js.map +1 -1
- package/dist/browser/poller/models.d.ts +15 -39
- package/dist/browser/poller/models.d.ts.map +1 -1
- package/dist/browser/poller/models.js.map +1 -1
- package/dist/browser/poller/operation.d.ts +12 -14
- package/dist/browser/poller/operation.d.ts.map +1 -1
- package/dist/browser/poller/operation.js +25 -29
- package/dist/browser/poller/operation.js.map +1 -1
- package/dist/browser/poller/poller.d.ts +1 -1
- package/dist/browser/poller/poller.d.ts.map +1 -1
- package/dist/browser/poller/poller.js +9 -34
- package/dist/browser/poller/poller.js.map +1 -1
- package/dist/commonjs/http/models.d.ts +2 -2
- package/dist/commonjs/http/models.d.ts.map +1 -1
- package/dist/commonjs/http/models.js.map +1 -1
- package/dist/commonjs/http/operation.d.ts +11 -12
- package/dist/commonjs/http/operation.d.ts.map +1 -1
- package/dist/commonjs/http/operation.js +22 -16
- package/dist/commonjs/http/operation.js.map +1 -1
- package/dist/commonjs/http/poller.d.ts +2 -2
- package/dist/commonjs/http/poller.d.ts.map +1 -1
- package/dist/commonjs/http/poller.js +1 -15
- package/dist/commonjs/http/poller.js.map +1 -1
- package/dist/commonjs/index.d.ts +1 -1
- package/dist/commonjs/index.d.ts.map +1 -1
- package/dist/commonjs/index.js.map +1 -1
- package/dist/commonjs/poller/models.d.ts +15 -39
- package/dist/commonjs/poller/models.d.ts.map +1 -1
- package/dist/commonjs/poller/models.js.map +1 -1
- package/dist/commonjs/poller/operation.d.ts +12 -14
- package/dist/commonjs/poller/operation.d.ts.map +1 -1
- package/dist/commonjs/poller/operation.js +25 -29
- package/dist/commonjs/poller/operation.js.map +1 -1
- package/dist/commonjs/poller/poller.d.ts +1 -1
- package/dist/commonjs/poller/poller.d.ts.map +1 -1
- package/dist/commonjs/poller/poller.js +9 -34
- package/dist/commonjs/poller/poller.js.map +1 -1
- package/dist/commonjs/tsdoc-metadata.json +1 -1
- package/dist/core-lro.d.ts +28 -32
- package/dist/esm/http/models.d.ts +2 -2
- package/dist/esm/http/models.d.ts.map +1 -1
- package/dist/esm/http/models.js.map +1 -1
- package/dist/esm/http/operation.d.ts +11 -12
- package/dist/esm/http/operation.d.ts.map +1 -1
- package/dist/esm/http/operation.js +22 -16
- package/dist/esm/http/operation.js.map +1 -1
- package/dist/esm/http/poller.d.ts +2 -2
- package/dist/esm/http/poller.d.ts.map +1 -1
- package/dist/esm/http/poller.js +1 -15
- package/dist/esm/http/poller.js.map +1 -1
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/poller/models.d.ts +15 -39
- package/dist/esm/poller/models.d.ts.map +1 -1
- package/dist/esm/poller/models.js.map +1 -1
- package/dist/esm/poller/operation.d.ts +12 -14
- package/dist/esm/poller/operation.d.ts.map +1 -1
- package/dist/esm/poller/operation.js +25 -29
- package/dist/esm/poller/operation.js.map +1 -1
- package/dist/esm/poller/poller.d.ts +1 -1
- package/dist/esm/poller/poller.d.ts.map +1 -1
- package/dist/esm/poller/poller.js +9 -34
- package/dist/esm/poller/poller.js.map +1 -1
- package/dist/react-native/http/models.d.ts +2 -2
- package/dist/react-native/http/models.d.ts.map +1 -1
- package/dist/react-native/http/models.js.map +1 -1
- package/dist/react-native/http/operation.d.ts +11 -12
- package/dist/react-native/http/operation.d.ts.map +1 -1
- package/dist/react-native/http/operation.js +22 -16
- package/dist/react-native/http/operation.js.map +1 -1
- package/dist/react-native/http/poller.d.ts +2 -2
- package/dist/react-native/http/poller.d.ts.map +1 -1
- package/dist/react-native/http/poller.js +1 -15
- package/dist/react-native/http/poller.js.map +1 -1
- package/dist/react-native/index.d.ts +1 -1
- package/dist/react-native/index.d.ts.map +1 -1
- package/dist/react-native/index.js.map +1 -1
- package/dist/react-native/poller/models.d.ts +15 -39
- package/dist/react-native/poller/models.d.ts.map +1 -1
- package/dist/react-native/poller/models.js.map +1 -1
- package/dist/react-native/poller/operation.d.ts +12 -14
- package/dist/react-native/poller/operation.d.ts.map +1 -1
- package/dist/react-native/poller/operation.js +25 -29
- package/dist/react-native/poller/operation.js.map +1 -1
- package/dist/react-native/poller/poller.d.ts +1 -1
- package/dist/react-native/poller/poller.d.ts.map +1 -1
- package/dist/react-native/poller/poller.js +9 -34
- package/dist/react-native/poller/poller.js.map +1 -1
- package/package.json +26 -20
- package/.rush/temp/operation/build/state.json +0 -3
- package/.rush/temp/operation/build_samples/all.log +0 -2
- package/.rush/temp/operation/build_samples/state.json +0 -3
- package/.rush/temp/shrinkwrap-deps.json +0 -510
- package/.tshy/browser.json +0 -12
- package/.tshy/build.json +0 -9
- package/.tshy/commonjs.json +0 -14
- package/.tshy/esm.json +0 -12
- package/.tshy/react-native.json +0 -12
- package/CHANGELOG.md +0 -179
- package/api-extractor.json +0 -31
- package/config/rush-project.json +0 -3
- package/core-lro.build.cache.error.log +0 -1
- package/core-lro.build_samples.cache.log +0 -1
- package/core-lro.build_samples.log +0 -2
- package/core-lro.pack.cache.log +0 -1
- package/core-lro.pack.log +0 -1
- package/docs/LROEngine.md +0 -158
- package/review/core-lro.api.md +0 -106
- package/samples/README.md +0 -284
- package/samples/typescript/samplesClient.ts +0 -254
- package/src/http/models.ts +0 -119
- package/src/http/operation.ts +0 -343
- package/src/http/poller.ts +0 -83
- package/src/index.ts +0 -21
- package/src/logger.ts +0 -10
- package/src/poller/constants.ts +0 -11
- package/src/poller/models.ts +0 -251
- package/src/poller/operation.ts +0 -315
- package/src/poller/poller.ts +0 -250
- package/temp/core-lro.api.json +0 -1892
- package/temp/core-lro.api.md +0 -106
- package/test/getYieldedValue.ts +0 -16
- package/test/lro.spec.ts +0 -3141
- package/test/matrix.ts +0 -46
- package/test/utils/coreRestPipelineLro.ts +0 -25
- package/test/utils/router.ts +0 -231
- package/test/utils/utils.ts +0 -144
- package/tsconfig.browser.config.json +0 -10
- package/tsconfig.json +0 -13
- package/tsdoc.json +0 -4
- package/tslint.json +0 -47
- package/vitest.browser.config.ts +0 -34
- package/vitest.config.ts +0 -31
package/samples/README.md
DELETED
|
@@ -1,284 +0,0 @@
|
|
|
1
|
-
# Azure Core LRO developer guide and samples
|
|
2
|
-
|
|
3
|
-
Here we will expand on how to use `@azure/core-lro` by presenting a sample, and exploring on how to use the core concepts to build your own Long Running Operation methods returning pollers.
|
|
4
|
-
|
|
5
|
-
## Sample
|
|
6
|
-
|
|
7
|
-
In this folder you will be able to see a simple sample file implementing a `Poller` and a `PollOperation` and then using them from a `main()` function.
|
|
8
|
-
|
|
9
|
-
The sample file:
|
|
10
|
-
|
|
11
|
-
- [typescript/samplesClient.ts](https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/core/core-lro/samples/typescript/samplesClient.ts)
|
|
12
|
-
|
|
13
|
-
## Guide on implementing a LRO method
|
|
14
|
-
|
|
15
|
-
The following sections go through the core concepts explaining how to build Long Running Operation methods returning pollers.
|
|
16
|
-
|
|
17
|
-
### Implementing an operation
|
|
18
|
-
|
|
19
|
-
To work with a Long Running Operation, we need to define how to update, cancel and serialize the information related to the remote pending task.
|
|
20
|
-
|
|
21
|
-
To implement this class for your library or application, you'll need to import the definitions of a poll operation and its state.
|
|
22
|
-
|
|
23
|
-
```typescript
|
|
24
|
-
import { PollOperationState, PollOperation } from "@azure/core-lro";
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
A `PollOperation` is an interface that defines how to update the local reference of the state of the remote long running operation, just as well as how to request the cancellation of the same operation.
|
|
28
|
-
|
|
29
|
-
Besides updating and cancelling, it also defines how to serialize its information, so that polling can be resumed at any time from a previously serialized operation (more at [Serializing an operation](#serializing-an-operation)).
|
|
30
|
-
|
|
31
|
-
`PollOperationState` provides a basic state for the poll operation. It contains the minimal set of properties needed to keep track of a long running operation, and it's intended to be extended with any custom property that your program might need. The state can be updated any time, but it should be updated at least in three opportunities: when the operation starts, when it's finished, and when it's cancelled.
|
|
32
|
-
|
|
33
|
-
To be able to create your custom operations, you'll need to extend the `PollOperation` class with both your operation's state and the final result value. For this example, we'll think on the final result value to be `MyResult`, which can be any type.
|
|
34
|
-
|
|
35
|
-
```typescript
|
|
36
|
-
import { PollOperationState, PollOperation } from "@azure/core-lro";
|
|
37
|
-
|
|
38
|
-
export interface MyOperationState extends PollOperationState<MyResult> {
|
|
39
|
-
serviceClient: any; // You define all of these properties
|
|
40
|
-
myCustomString: string;
|
|
41
|
-
startedAt: Date;
|
|
42
|
-
finishedAt: Date;
|
|
43
|
-
// ... and so on
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
export interface MyPollOperation extends PollOperation<MyOperationState, MyResult> {}
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
We recommend making a utility function to create new instances of your operation. Just like the following:
|
|
50
|
-
|
|
51
|
-
```typescript
|
|
52
|
-
function makeOperation(
|
|
53
|
-
state: MyOperationState,
|
|
54
|
-
): MyOperation {
|
|
55
|
-
return {
|
|
56
|
-
// We recommend creating copies of the given state,
|
|
57
|
-
// just to make sure that no references are left or manipulated by mistake.
|
|
58
|
-
state: {
|
|
59
|
-
...state,
|
|
60
|
-
},
|
|
61
|
-
update,
|
|
62
|
-
cancel,
|
|
63
|
-
toString
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
To properly define an operation, you will need to have implemented these three functions: `update`, `cancel` and `toString`.
|
|
69
|
-
|
|
70
|
-
A guide on how to write them follows.
|
|
71
|
-
|
|
72
|
-
#### Your operation's update method
|
|
73
|
-
|
|
74
|
-
The `update` method defines how to request the remote service for updates on the status of the long running operation.
|
|
75
|
-
|
|
76
|
-
It optionally receives an object with an `abortSignal` property, from [@azure/abort-controller](https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/core/abort-controller)'s `AbortSignalLike`.
|
|
77
|
-
|
|
78
|
-
A more advanced use allows passing in a `fireProgress` function, which, if called, is responsible for triggering the
|
|
79
|
-
poller's `onProgress` callbacks.
|
|
80
|
-
|
|
81
|
-
Here is an example of how to write an update method for your operation:
|
|
82
|
-
|
|
83
|
-
```typescript
|
|
84
|
-
async function update(
|
|
85
|
-
this: MyOperation,
|
|
86
|
-
options: {
|
|
87
|
-
abortSignal?: AbortSignalLike;
|
|
88
|
-
fireProgress?: (state: MyOperationState) => void;
|
|
89
|
-
} = {}
|
|
90
|
-
): Promise<MyOperation> {
|
|
91
|
-
let isDone: boolean = false;
|
|
92
|
-
let doFireProgress: boolean = false;
|
|
93
|
-
|
|
94
|
-
// Asynchronously call your service client...
|
|
95
|
-
|
|
96
|
-
// You might update the operation's state at any point
|
|
97
|
-
if (isDone) {
|
|
98
|
-
this.state.completed = true;
|
|
99
|
-
this.state.result = "Done";
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
// You can also arbitrarily report progress
|
|
103
|
-
if (doFireProgress) {
|
|
104
|
-
options.fireProgress(state);
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
return makeOperation(this.state);
|
|
108
|
-
}
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
#### Your operation's cancel method
|
|
112
|
-
|
|
113
|
-
The operation's `cancel` method should attempt to cancel the pending operation, if it's allowed by the remote service. Otherwise, it should throw.
|
|
114
|
-
|
|
115
|
-
It only optionally receives an object with an `abortSignal` property, from [@azure/abort-controller](https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/core/abort-controller)'s `AbortSignalLike`.
|
|
116
|
-
|
|
117
|
-
It returns a promise that should be resolved with an updated version of the poller's operation.
|
|
118
|
-
|
|
119
|
-
```typescript
|
|
120
|
-
async function cancel(
|
|
121
|
-
this: MyOperation,
|
|
122
|
-
options: { abortSignal?: AbortSignalLike } = {}
|
|
123
|
-
): Promise<MyOperation> {
|
|
124
|
-
// ... Reach out to your service to trigger the cancellation of the operation ...
|
|
125
|
-
|
|
126
|
-
return makeOperation(
|
|
127
|
-
{
|
|
128
|
-
...this.state,
|
|
129
|
-
cancelled: true
|
|
130
|
-
}
|
|
131
|
-
);
|
|
132
|
-
}
|
|
133
|
-
```
|
|
134
|
-
|
|
135
|
-
#### Serializing an operation
|
|
136
|
-
|
|
137
|
-
The operation's method `toString` returns a string with a serialized representation of the operation. It's useful when a poller wants to be resumed from a previously serialized state.
|
|
138
|
-
|
|
139
|
-
The deserialization of the operation has to be implemented within the constructor of a class that extends the Poller class. You can read more at [Resuming from a previous poller](#resuming-from-a-previous-poller).
|
|
140
|
-
|
|
141
|
-
```typescript
|
|
142
|
-
function toString(this: MyOperation): string {
|
|
143
|
-
return JSON.stringify({
|
|
144
|
-
state: {
|
|
145
|
-
...this.state,
|
|
146
|
-
// Only the plain text properties, for example
|
|
147
|
-
}
|
|
148
|
-
});
|
|
149
|
-
}
|
|
150
|
-
```
|
|
151
|
-
|
|
152
|
-
### Implementing a poller
|
|
153
|
-
|
|
154
|
-
@azure/core-lro's `Poller` is a class that represents the definition of a program that polls through consecutive requests until it reaches a state of completion.
|
|
155
|
-
|
|
156
|
-
A poller can be executed manually, by polling request by request by calling to the `poll()` method repeatedly, until its operation is completed. It also provides a way to wait until the operation finishes, by calling `pollUntilDone()`, which returns a promise. Pollers can also request the cancellation of the ongoing process (internally using `PollOperation`'s `cancel()` method).
|
|
157
|
-
|
|
158
|
-
The Poller needs two types to be defined, a type representing the state of the poller, which must include a basic set of properties from `PollOperationState<TResult>` (as mentioned in [Implementing an operation](#implementing-an-operation)), and a return type defined by `TResult`, which can be anything.
|
|
159
|
-
|
|
160
|
-
To implement a poller, you must pull in the definitions of your operation and extend @azure/core-lro's `Poller` class, as follows:
|
|
161
|
-
|
|
162
|
-
```typescript
|
|
163
|
-
import { Poller } from "@azure/core-lro";
|
|
164
|
-
import { makeOperation, MyOperation, MyOperationState } from "./myOperation";
|
|
165
|
-
|
|
166
|
-
// See that "MyResult" here is the type of the result
|
|
167
|
-
export class MyPoller extends Poller<MyOperationState, MyResult> {
|
|
168
|
-
constructor(
|
|
169
|
-
baseOperation?: MyOperation,
|
|
170
|
-
onProgress?: (state: MyOperationState) => void
|
|
171
|
-
) {
|
|
172
|
-
let state: MyOperationState = {};
|
|
173
|
-
|
|
174
|
-
if (baseOperation) {
|
|
175
|
-
state = baseOperation.state;
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
const operation = makeOperation(state);
|
|
179
|
-
|
|
180
|
-
super(operation);
|
|
181
|
-
|
|
182
|
-
// Setting up the poller to call progress when the operation decides.
|
|
183
|
-
// This ties to the operation's update method, which receives a
|
|
184
|
-
// fireProgress method in the optional properties.
|
|
185
|
-
if (onProgress) {
|
|
186
|
-
this.onProgress(onProgress);
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
async delay(): Promise<void> {
|
|
191
|
-
// Your own implementation of a delay
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
```
|
|
195
|
-
|
|
196
|
-
Once defined, you'll be able to use your poller as shown below:
|
|
197
|
-
|
|
198
|
-
```ts
|
|
199
|
-
const poller = new MyPoller();
|
|
200
|
-
|
|
201
|
-
// Polling just once:
|
|
202
|
-
await poller.poll();
|
|
203
|
-
|
|
204
|
-
// We can try to cancel the request here, by calling:
|
|
205
|
-
//
|
|
206
|
-
// await poller.cancelOperation();
|
|
207
|
-
//
|
|
208
|
-
|
|
209
|
-
// Getting the final result:
|
|
210
|
-
const result = await poller.pollUntilDone();
|
|
211
|
-
```
|
|
212
|
-
|
|
213
|
-
The Poller class implements the `PollerLike` interface, which allows poller implementations that avoid having to export the Poller's class directly, and instead only export the already instantiated poller with the `PollerLike` type.
|
|
214
|
-
|
|
215
|
-
An example of the definition of a client that returns an instantiated poller can be seen below:
|
|
216
|
-
|
|
217
|
-
```ts
|
|
218
|
-
class Client {
|
|
219
|
-
public async makePoller: PollerLike<MyOperationState, MyResult> {
|
|
220
|
-
const poller = new MyPoller({});
|
|
221
|
-
// It might be preferred to return the poller after the first request is made,
|
|
222
|
-
// so that some information can be obtained right away.
|
|
223
|
-
await poller.poll();
|
|
224
|
-
return poller;
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
// No knowledge of the class MyPoller:
|
|
229
|
-
const poller: PollerLike<MyOperationState, MyResult> = myClient.makePoller();
|
|
230
|
-
```
|
|
231
|
-
|
|
232
|
-
A poller can be created through its constructor, then it can be polled until it's completed. At any point in time, the state of the poller can be obtained without delay through the getOperationState method. At any point in time, the intermediate forms of the result type can be requested without delay.
|
|
233
|
-
|
|
234
|
-
Once the underlying operation is marked as completed, the poller will stop and the final value will be returned.
|
|
235
|
-
|
|
236
|
-
Here's an example usage of your client's poller:
|
|
237
|
-
|
|
238
|
-
```ts
|
|
239
|
-
const poller = myClient.makePoller();
|
|
240
|
-
const state: MyOperationState = poller.getOperationState();
|
|
241
|
-
|
|
242
|
-
// The intermediate result can be obtained at any time.
|
|
243
|
-
const result: MyResult | undefined = poller.getResult();
|
|
244
|
-
|
|
245
|
-
// The final result can only be obtained after the poller finishes.
|
|
246
|
-
const result: MyResult = await poller.pollUntilDone();
|
|
247
|
-
```
|
|
248
|
-
|
|
249
|
-
#### Resuming from a previous poller
|
|
250
|
-
|
|
251
|
-
Pollers by default have a method called `toString` that invokes the operation's `toString` method. It can be used to store the state of a poller indefinitely, to then resume by creating another poller at any time in the future.
|
|
252
|
-
|
|
253
|
-
If an operation's `toString` method is defined as follows:
|
|
254
|
-
|
|
255
|
-
```ts
|
|
256
|
-
function toString(this: TestOperation): string {
|
|
257
|
-
return JSON.stringify({
|
|
258
|
-
state: this.state
|
|
259
|
-
});
|
|
260
|
-
}
|
|
261
|
-
```
|
|
262
|
-
|
|
263
|
-
A custom implementation of a poller can deserialize it by receiving this string and converting it back to JSON, like in the following example:
|
|
264
|
-
|
|
265
|
-
```ts
|
|
266
|
-
export class MyPoller extends Poller<MyOperationState, string> {
|
|
267
|
-
constructor(
|
|
268
|
-
baseOperation: string | undefined
|
|
269
|
-
) {
|
|
270
|
-
let state: MyOperationState = {};
|
|
271
|
-
if (baseOperation) {
|
|
272
|
-
state = {
|
|
273
|
-
...JSON.parse(baseOperation).state,
|
|
274
|
-
...state
|
|
275
|
-
};
|
|
276
|
-
}
|
|
277
|
-
const operation = {
|
|
278
|
-
state,
|
|
279
|
-
// ...
|
|
280
|
-
}
|
|
281
|
-
super(operation);
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
```
|
|
@@ -1,254 +0,0 @@
|
|
|
1
|
-
// Copyright (c) Microsoft Corporation.
|
|
2
|
-
// Licensed under the MIT License.
|
|
3
|
-
|
|
4
|
-
import { Poller, PollOperation, PollerLike, PollOperationState } from "@azure/core-lro";
|
|
5
|
-
import { delay } from "@azure/core-util";
|
|
6
|
-
|
|
7
|
-
// This sample implements a poller, a client and runs the poller operation until it finishes.
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* The return value of our long running operation.
|
|
11
|
-
*/
|
|
12
|
-
interface ReturnValue {
|
|
13
|
-
/**
|
|
14
|
-
* Anything can be here. We're choosing a number value to make it easier for this sample.
|
|
15
|
-
*/
|
|
16
|
-
value: number;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* This sample's poll operation state.
|
|
21
|
-
* Extends PollOperationState, which has all the required minimal properties to make the poller work.
|
|
22
|
-
*/
|
|
23
|
-
export interface SamplePollOperationState extends PollOperationState<ReturnValue> {
|
|
24
|
-
/**
|
|
25
|
-
* As part of the operation state, we'll be using a reference to the client.
|
|
26
|
-
* This will let us use the public methods of the client to reach to remote services.
|
|
27
|
-
*/
|
|
28
|
-
requestCount: number;
|
|
29
|
-
/**
|
|
30
|
-
* To keep track of the progress we've made so far, we're going to record all the previously received ReturnValues in this array.
|
|
31
|
-
*/
|
|
32
|
-
previousResponses: ReturnValue[];
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* The definition of our sample's poll operation.
|
|
37
|
-
* It extends PollOperation, which makes sure the shape of the interface remains consistent.
|
|
38
|
-
* It uses the SamplePollOperationState, which allows to use the default properties of a poll operation state,
|
|
39
|
-
* plus the ones we've defined above.
|
|
40
|
-
* It returns an instance of the ReturnValue interface.
|
|
41
|
-
*/
|
|
42
|
-
interface SamplePollOperation extends PollOperation<SamplePollOperationState, ReturnValue> {}
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* A utility method that builds an instance of the sample poll operation with some default methods.
|
|
46
|
-
*/
|
|
47
|
-
function makeSamplePollOperation(state: SamplePollOperationState, client: Client): SamplePollOperation {
|
|
48
|
-
return {
|
|
49
|
-
/**
|
|
50
|
-
* To ensure the state is always clean of previously used references, we're making a copy of it.
|
|
51
|
-
*/
|
|
52
|
-
state: {
|
|
53
|
-
...state,
|
|
54
|
-
previousResponses: [...state.previousResponses]
|
|
55
|
-
},
|
|
56
|
-
/**
|
|
57
|
-
* The update method should change the operation's state.
|
|
58
|
-
* In our case, we'll be calling the Client's makeRequest.
|
|
59
|
-
*/
|
|
60
|
-
async update(): Promise<SamplePollOperation> {
|
|
61
|
-
const state: SamplePollOperationState = {
|
|
62
|
-
...this.state
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
if (!state.isStarted) {
|
|
66
|
-
state.result = await client.makeRequest(state);
|
|
67
|
-
state.isStarted = true;
|
|
68
|
-
} else if (!state.isCompleted) {
|
|
69
|
-
state.result = await client.makeRequest(state);
|
|
70
|
-
if (client.isDone(state.result!.value)) {
|
|
71
|
-
state.isCompleted = true;
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
state.previousResponses.push(state.result!);
|
|
76
|
-
|
|
77
|
-
return makeSamplePollOperation(state, client);
|
|
78
|
-
},
|
|
79
|
-
/**
|
|
80
|
-
* The cancel method can be called to send a cancelling signal to the remote service.
|
|
81
|
-
* If cancelling isn't supported, an error can be thrown instead.
|
|
82
|
-
*/
|
|
83
|
-
async cancel(): Promise<SamplePollOperation> {
|
|
84
|
-
const state = this.state;
|
|
85
|
-
|
|
86
|
-
state.result = await client.cancel();
|
|
87
|
-
|
|
88
|
-
state.previousResponses.push(state.result);
|
|
89
|
-
|
|
90
|
-
return makeSamplePollOperation(
|
|
91
|
-
{ ...state, isCancelled: true },
|
|
92
|
-
client
|
|
93
|
-
);
|
|
94
|
-
},
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* The toString method serializes the PollOperationState, so that
|
|
98
|
-
* one poller can be stopped and another poller can recover at any time
|
|
99
|
-
* based on a copy of the first one.
|
|
100
|
-
*/
|
|
101
|
-
toString(): string {
|
|
102
|
-
return JSON.stringify({
|
|
103
|
-
state: this.state
|
|
104
|
-
});
|
|
105
|
-
}
|
|
106
|
-
};
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
/**
|
|
110
|
-
* Here's our sample's poller.
|
|
111
|
-
* It will work over our SamplePollOperationState.
|
|
112
|
-
* Once the polling is completed, it will return an instance of the ReturnValue interface.
|
|
113
|
-
*/
|
|
114
|
-
class SamplePoller extends Poller<SamplePollOperationState, ReturnValue> {
|
|
115
|
-
public intervalInMs: number;
|
|
116
|
-
|
|
117
|
-
constructor({
|
|
118
|
-
client,
|
|
119
|
-
requestCount,
|
|
120
|
-
intervalInMs = 2000,
|
|
121
|
-
resumeFrom
|
|
122
|
-
}: {
|
|
123
|
-
client: Client;
|
|
124
|
-
requestCount:number;
|
|
125
|
-
intervalInMs?: number;
|
|
126
|
-
resumeFrom?: string;
|
|
127
|
-
}) {
|
|
128
|
-
let state: SamplePollOperationState = {
|
|
129
|
-
requestCount,
|
|
130
|
-
previousResponses: []
|
|
131
|
-
};
|
|
132
|
-
|
|
133
|
-
// Here's an example of how to resume from the serialized version of a previously defined poller.
|
|
134
|
-
if (resumeFrom) {
|
|
135
|
-
state = JSON.parse(resumeFrom).state;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
// Making a new instance of the SamplePollOperation
|
|
139
|
-
const operation = makeSamplePollOperation(state, client);
|
|
140
|
-
|
|
141
|
-
super(operation);
|
|
142
|
-
this.intervalInMs = intervalInMs;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
/**
|
|
146
|
-
* The method used by the poller to wait before attempting to update its operation.
|
|
147
|
-
*/
|
|
148
|
-
async delay(): Promise<void> {
|
|
149
|
-
return delay(this.intervalInMs);
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
/**
|
|
153
|
-
* Could be used to get a publicly safe version of the poller state.
|
|
154
|
-
*/
|
|
155
|
-
public getOperationState(): SamplePollOperationState {
|
|
156
|
-
return this.operation.state;
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
/**
|
|
161
|
-
* Now it's time to define our Client.
|
|
162
|
-
* Our client will have four public methods:
|
|
163
|
-
* `makeRequest()` attempts to emulate the network request,
|
|
164
|
-
* `cancel()` which portrays how to tell the remote resource to cancel the long running operation,
|
|
165
|
-
* and `beginLongOperation()`, the method that returns the poller.
|
|
166
|
-
*/
|
|
167
|
-
class Client {
|
|
168
|
-
constructor() {}
|
|
169
|
-
|
|
170
|
-
/**
|
|
171
|
-
* We'll keep track of the number of requests through this private property.
|
|
172
|
-
* This is just to demonstrate the poller's behavior.
|
|
173
|
-
*/
|
|
174
|
-
private requestCount: number = 1;
|
|
175
|
-
|
|
176
|
-
/**
|
|
177
|
-
* isDone is here to represent a way to determine if the response from the service indicates that the long running operation has finished.
|
|
178
|
-
* In this sample we're considering a number value of 3 to be the only indicator that the operation has finished.
|
|
179
|
-
*/
|
|
180
|
-
public isDone(value: number): boolean {
|
|
181
|
-
return value === 3;
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
/**
|
|
185
|
-
* cancel should reach out to the remote service to indicate that the
|
|
186
|
-
* long running operation should be cancelled. In our case it simply returns a value,
|
|
187
|
-
* the poller will stop nonetheless.
|
|
188
|
-
*/
|
|
189
|
-
public async cancel(): Promise<ReturnValue> {
|
|
190
|
-
return {
|
|
191
|
-
value: 0
|
|
192
|
-
};
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
/**
|
|
196
|
-
* makeRequest simulates a method that reaches out to a remote resource that responds differently each time
|
|
197
|
-
*/
|
|
198
|
-
public async makeRequest(state: SamplePollOperationState): Promise<ReturnValue> {
|
|
199
|
-
// Let's assume the HTTP request happens here.
|
|
200
|
-
await delay(1000);
|
|
201
|
-
return {
|
|
202
|
-
value: state.requestCount++
|
|
203
|
-
};
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
public async beginLongOperation(options?: {
|
|
207
|
-
resumeFrom?: string;
|
|
208
|
-
}): Promise<PollerLike<PollOperationState<ReturnValue>, ReturnValue>> {
|
|
209
|
-
const poller = new SamplePoller({
|
|
210
|
-
client: this,
|
|
211
|
-
requestCount: this.requestCount,
|
|
212
|
-
...options
|
|
213
|
-
});
|
|
214
|
-
await poller.poll();
|
|
215
|
-
return poller;
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
// Now let's see how the client is used.
|
|
220
|
-
|
|
221
|
-
export async function main(): Promise<void> {
|
|
222
|
-
let client = new Client();
|
|
223
|
-
let poller = await client.beginLongOperation();
|
|
224
|
-
console.log(poller.getResult()); // Should show: { value: 1 }
|
|
225
|
-
let result = await poller.pollUntilDone();
|
|
226
|
-
console.log(result); // Should show: { value: 3 }
|
|
227
|
-
|
|
228
|
-
// We can start again and do each call individually
|
|
229
|
-
client = new Client();
|
|
230
|
-
poller = await client.beginLongOperation();
|
|
231
|
-
console.log(poller.getResult()); // Should show: { value: 1 }
|
|
232
|
-
await poller.poll();
|
|
233
|
-
console.log(poller.getResult()); // Should show: { value: 2 }
|
|
234
|
-
await poller.poll();
|
|
235
|
-
console.log(poller.getResult()); // Should show: { value: 3 }
|
|
236
|
-
console.log(poller.isDone()); // Should be: true
|
|
237
|
-
|
|
238
|
-
// We can also start it, then serialize it, then resume it with a different poller
|
|
239
|
-
client = new Client();
|
|
240
|
-
poller = await client.beginLongOperation();
|
|
241
|
-
console.log(poller.getResult()); // Should show: { value: 1 }
|
|
242
|
-
const serialized = poller.toString();
|
|
243
|
-
poller = await client.beginLongOperation({ resumeFrom: serialized });
|
|
244
|
-
console.log(poller.getResult()); // Should show: { value: 2 }
|
|
245
|
-
await poller.poll();
|
|
246
|
-
console.log(poller.getResult()); // Should show: { value: 3 }
|
|
247
|
-
console.log(poller.isDone()); // Should be: true
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
main().catch((err) => {
|
|
251
|
-
console.log("error code: ", err.code);
|
|
252
|
-
console.log("error message: ", err.message);
|
|
253
|
-
console.log("error stack: ", err.stack);
|
|
254
|
-
});
|
package/src/http/models.ts
DELETED
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
// Copyright (c) Microsoft Corporation.
|
|
2
|
-
// Licensed under the MIT license.
|
|
3
|
-
|
|
4
|
-
import { AbortSignalLike } from "@azure/abort-controller";
|
|
5
|
-
import { LroError } from "../poller/models.js";
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* The potential location of the result of the LRO if specified by the LRO extension in the swagger.
|
|
9
|
-
*/
|
|
10
|
-
export type ResourceLocationConfig = "azure-async-operation" | "location" | "original-uri";
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* The type of a LRO response body. This is just a convenience type for checking the status of the operation.
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
export interface ResponseBody extends Record<string, unknown> {
|
|
17
|
-
/** The status of the operation. */
|
|
18
|
-
status?: unknown;
|
|
19
|
-
/** The state of the provisioning process */
|
|
20
|
-
provisioningState?: unknown;
|
|
21
|
-
/** The properties of the provisioning process */
|
|
22
|
-
properties?: { provisioningState?: unknown } & Record<string, unknown>;
|
|
23
|
-
/** The error if the operation failed */
|
|
24
|
-
error?: Partial<LroError>;
|
|
25
|
-
/** The location of the created resource */
|
|
26
|
-
resourceLocation?: string;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Simple type of the raw request.
|
|
31
|
-
*/
|
|
32
|
-
export interface RawRequest {
|
|
33
|
-
/** The HTTP request method */
|
|
34
|
-
method: string;
|
|
35
|
-
/** The request path */
|
|
36
|
-
url: string;
|
|
37
|
-
/** The request body */
|
|
38
|
-
body?: unknown;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Simple type of the raw response.
|
|
43
|
-
*/
|
|
44
|
-
export interface RawResponse<TRequest extends RawRequest = RawRequest> {
|
|
45
|
-
/** The HTTP status code */
|
|
46
|
-
statusCode: number;
|
|
47
|
-
/** The raw request that was sent to the server */
|
|
48
|
-
request: TRequest;
|
|
49
|
-
/** A HttpHeaders collection in the response represented as a simple JSON object where all header names have been normalized to be lower-case. */
|
|
50
|
-
headers: {
|
|
51
|
-
[headerName: string]: string;
|
|
52
|
-
};
|
|
53
|
-
/** The parsed response body */
|
|
54
|
-
body?: unknown;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* The type of the response of a LRO.
|
|
59
|
-
*/
|
|
60
|
-
export interface OperationResponse<T = unknown, TRequest extends RawRequest = RawRequest> {
|
|
61
|
-
/** The flattened response */
|
|
62
|
-
flatResponse: T;
|
|
63
|
-
/** The raw response */
|
|
64
|
-
rawResponse: RawResponse<TRequest>;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* Description of a long running operation.
|
|
69
|
-
*/
|
|
70
|
-
export interface LongRunningOperation<T = unknown> {
|
|
71
|
-
/**
|
|
72
|
-
* A function that can be used to send initial request to the service.
|
|
73
|
-
*/
|
|
74
|
-
sendInitialRequest: () => Promise<OperationResponse<unknown>>;
|
|
75
|
-
/**
|
|
76
|
-
* A function that can be used to poll for the current status of a long running operation.
|
|
77
|
-
*/
|
|
78
|
-
sendPollRequest: (
|
|
79
|
-
path: string,
|
|
80
|
-
options?: { abortSignal?: AbortSignalLike },
|
|
81
|
-
) => Promise<OperationResponse<T>>;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
export type HttpOperationMode = "OperationLocation" | "ResourceLocation" | "Body";
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* Options for `createPoller`.
|
|
88
|
-
*/
|
|
89
|
-
export interface CreateHttpPollerOptions<TResult, TState> {
|
|
90
|
-
/**
|
|
91
|
-
* Defines how much time the poller is going to wait before making a new request to the service.
|
|
92
|
-
*/
|
|
93
|
-
intervalInMs?: number;
|
|
94
|
-
/**
|
|
95
|
-
* A serialized poller which can be used to resume an existing paused Long-Running-Operation.
|
|
96
|
-
*/
|
|
97
|
-
restoreFrom?: string;
|
|
98
|
-
/**
|
|
99
|
-
* The potential location of the result of the LRO if specified by the LRO extension in the swagger.
|
|
100
|
-
*/
|
|
101
|
-
resourceLocationConfig?: ResourceLocationConfig;
|
|
102
|
-
/**
|
|
103
|
-
* A function to process the result of the LRO.
|
|
104
|
-
*/
|
|
105
|
-
processResult?: (result: unknown, state: TState) => TResult | Promise<TResult>;
|
|
106
|
-
/**
|
|
107
|
-
* A function to process the state of the LRO.
|
|
108
|
-
*/
|
|
109
|
-
updateState?: (state: TState, response: OperationResponse) => void;
|
|
110
|
-
/**
|
|
111
|
-
* A function to be called each time the operation location is updated by the
|
|
112
|
-
* service.
|
|
113
|
-
*/
|
|
114
|
-
withOperationLocation?: (operationLocation: string) => void;
|
|
115
|
-
/**
|
|
116
|
-
* Control whether to throw an exception if the operation failed or was canceled.
|
|
117
|
-
*/
|
|
118
|
-
resolveOnUnsuccessful?: boolean;
|
|
119
|
-
}
|