Skip to content

Commit

Permalink
feat(tcgc): add SdkLroServiceMetadata (#1515)
Browse files Browse the repository at this point in the history
- add `SdkLroServiceMetadata` and corresponding LRO metadata
- update LRO metadata initialization lgoic
- add test cases

resolve #1236

---------

Co-authored-by: Mingzhe Huang (from Dev Box) <mingzhehuang@microsoft.com>
  • Loading branch information
archerzz and Mingzhe Huang (from Dev Box) committed Sep 13, 2024
1 parent 95386b0 commit 5f73ee4
Show file tree
Hide file tree
Showing 4 changed files with 656 additions and 12 deletions.
7 changes: 7 additions & 0 deletions .chronus/changes/tcgc-lro-metadata-2024-8-11-22-30-34.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
changeKind: feature
packages:
- "@azure-tools/typespec-client-generator-core"
---

add `SdkLroServiceMetadata`
59 changes: 58 additions & 1 deletion packages/typespec-client-generator-core/src/interfaces.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import { LroMetadata, PagedResultMetadata } from "@azure-tools/typespec-azure-core";
import {
FinalStateValue,
LroMetadata,
PagedResultMetadata,
} from "@azure-tools/typespec-azure-core";
import {
DateTimeKnownEncoding,
Diagnostic,
Expand Down Expand Up @@ -623,7 +627,60 @@ export interface SdkPagingServiceMethod<TServiceOperation extends SdkServiceOper
}

interface SdkLroServiceMethodOptions {
/**
* @deprecated This property will be removed in future releases. Use `lroMetadata` for synthesized LRO metadata. If you still want to access primitive LRO info, use `lroMetadata.__raw`.
*/
__raw_lro_metadata: LroMetadata;
lroMetadata: SdkLroServiceMetadata;
}

/**
* Long running operation metadata.
*/
export interface SdkLroServiceMetadata {
/** LRO metadata from TypeSpec core library */
__raw: LroMetadata;

/** Legacy `finalStateVia` value */
finalStateVia: FinalStateValue;
/** Polling step metadata */
pollingStep: SdkLroServicePollingStep;
/** Final step metadata */
finalStep?: SdkLroServiceFinalStep;
/** Synthesized final response metadata */
finalResponse?: SdkLroServiceFinalResponse;
}

/**
* Long running operation polling step metadata.
*/
export interface SdkLroServicePollingStep {
/** Response body type */
responseBody?: SdkModelType;
}

/**
* Long running operation final step metadata.
*/
export interface SdkLroServiceFinalStep {
/** Final step kind */
kind:
| "finalOperationLink"
| "finalOperationReference"
| "pollingSuccessProperty"
| "noPollingResult";
}

/**
* Synthesized long running operation response metadata.
*/
export interface SdkLroServiceFinalResponse {
/** Intact response type */
envelopeResult: SdkModelType;
/** Meaningful result type */
result: SdkModelType;
/** Property path to fetch {result} from {envelopeResult}. Note that this property is available only in some LRO patterns. */
resultPath?: string;
}

export interface SdkLroServiceMethod<TServiceOperation extends SdkServiceOperation>
Expand Down
55 changes: 44 additions & 11 deletions packages/typespec-client-generator-core/src/package.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
getService,
getSummary,
ignoreDiagnostics,
Model,
Operation,
Type,
} from "@typespec/compiler";
Expand Down Expand Up @@ -34,6 +35,7 @@ import {
SdkHttpOperation,
SdkInitializationType,
SdkLroPagingServiceMethod,
SdkLroServiceMetadata,
SdkLroServiceMethod,
SdkMethod,
SdkMethodParameter,
Expand Down Expand Up @@ -154,35 +156,66 @@ function getSdkLroServiceMethod<TServiceOperation extends SdkServiceOperation>(
operation: Operation
): [SdkLroServiceMethod<TServiceOperation>, readonly Diagnostic[]] {
const diagnostics = createDiagnosticCollector();
const metadata = getLroMetadata(context.program, operation)!;
const metadata = getServiceMethodLroMetadata(context, operation)!;
const basicServiceMethod = diagnostics.pipe(
getSdkBasicServiceMethod<TServiceOperation>(context, operation)
);

if (metadata.finalResult === undefined || metadata.finalResult === "void") {
basicServiceMethod.response.type = undefined;
} else {
basicServiceMethod.response.type = diagnostics.pipe(
getClientTypeWithDiagnostics(context, metadata.finalResult)
);
}
basicServiceMethod.response.type = metadata.finalResponse?.result;

basicServiceMethod.response.resultPath = metadata.finalResultPath;
basicServiceMethod.response.resultPath = metadata.finalResponse?.resultPath;

return diagnostics.wrap({
...basicServiceMethod,
kind: "lro",
__raw_lro_metadata: metadata,
__raw_lro_metadata: metadata.__raw,
lroMetadata: metadata,
operation: diagnostics.pipe(
getSdkServiceOperation<TServiceOperation>(
context,
metadata.operation,
metadata.__raw.operation,
basicServiceMethod.parameters
)
),
});
}

function getServiceMethodLroMetadata(
context: TCGCContext,
operation: Operation
): SdkLroServiceMetadata | undefined {
const rawMetadata = getLroMetadata(context.program, operation);
if (rawMetadata === undefined) {
return undefined;
}

const diagnostics = createDiagnosticCollector();

return {
__raw: rawMetadata,
finalStateVia: rawMetadata.finalStateVia,
finalResponse:
rawMetadata.finalEnvelopeResult !== undefined && rawMetadata.finalEnvelopeResult !== "void"
? {
envelopeResult: diagnostics.pipe(
getClientTypeWithDiagnostics(context, rawMetadata.finalEnvelopeResult)
) as SdkModelType,
result: diagnostics.pipe(
getClientTypeWithDiagnostics(context, rawMetadata.finalResult as Model)
) as SdkModelType,
resultPath: rawMetadata.finalResultPath,
}
: undefined,
finalStep:
rawMetadata.finalStep !== undefined ? { kind: rawMetadata.finalStep.kind } : undefined,
pollingStep: {
responseBody: diagnostics.pipe(
getClientTypeWithDiagnostics(context, rawMetadata.pollingInfo.responseModel)
) as SdkModelType,
},
};
}

function getSdkMethodResponse(
context: TCGCContext,
operation: Operation,
Expand Down
Loading

0 comments on commit 5f73ee4

Please sign in to comment.