-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[core-lro] proof-of-concept for https://github.com/Azure/azure-sdk-for-js/issues/32142 #6
base: keyvault-admin-typespec
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,6 +15,7 @@ import { | |
} from "./operation.js"; | ||
import type { CreateHttpPollerOptions } from "./models.js"; | ||
import { buildCreatePoller } from "../poller/poller.js"; | ||
import { logger } from "../logger.js"; | ||
|
||
/** | ||
* Creates a poller that can be used to poll a long-running operation. | ||
|
@@ -34,6 +35,7 @@ export function createHttpPoller<TResult, TState extends OperationState<TResult> | |
updateState, | ||
withOperationLocation, | ||
resolveOnUnsuccessful = false, | ||
skipFinalGet = false, | ||
} = options || {}; | ||
return buildCreatePoller<OperationResponse, TResult, TState>({ | ||
getStatusFromInitialResponse, | ||
|
@@ -49,6 +51,10 @@ export function createHttpPoller<TResult, TState extends OperationState<TResult> | |
init: async () => { | ||
const response = await lro.sendInitialRequest(); | ||
const config = inferLroMode(response.rawResponse, resourceLocationConfig); | ||
if (skipFinalGet && config?.resourceLocation) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This will end up moving into There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This change works for me. And I was also thinking of that this could also work in the resumeFrom case. nit: should we put this logic into |
||
logger.info("skipFinalGet is enabled, skipping final GET operation of LRO"); | ||
config.resourceLocation = undefined; | ||
} | ||
return { | ||
response, | ||
operationLocation: config?.operationLocation, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
#!/usr/bin/env node | ||
|
||
const { execSync } = require("child_process"); | ||
const fs = require("fs"); | ||
const path = require("path"); | ||
|
||
// Helper to execute shell commands and log output | ||
function execCommand(command) { | ||
try { | ||
execSync(command, { stdio: "inherit" }); | ||
} catch (error) { | ||
console.error(`Command failed: ${command}`); | ||
process.exit(1); | ||
} | ||
} | ||
|
||
console.log("Setting up the environment..."); | ||
|
||
// Workaround for src-folder support in emitter: | ||
// End state: src/generated/* contains generated code (instead of src/generated/src/*) | ||
|
||
// Step 1: Remove all files in src/generated/* | ||
execCommand("rm -rf src/generated/*"); | ||
|
||
// Step 2: Copy tsp-location.yaml to src/generated | ||
execCommand("cp tsp-location.yaml src/generated"); | ||
|
||
// Step 3: Run tsp-client command | ||
// emitter-option as a workaround for https://github.com/Azure/azure-rest-api-specs/issues/31610 | ||
execCommand(`tsp-client update -d -o src/generated --emitter-options generateMetadata=false`); | ||
// execCommand( | ||
// "tsp-client update -d -o src/generated --tsp-config ~/workspace/azure-rest-api-specs/specification/keyvault/Security.KeyVault.Keys/tspconfig.yaml --local-spec-repo ~/workspace/azure-rest-api-specs/specification/keyvault/Security.KeyVault.Keys --repo ~/workspace/azure-rest-api-specs --commit 9561bad7d2eed94cc91aa6164d3721b8aa8699fe --emitter-options generateMetadata=false" | ||
// ); | ||
|
||
// Step 4: Move generated/src/* files to generated until src-folder is supported | ||
execCommand("mv src/generated/src/* src/generated/"); | ||
|
||
// Step 5: Remove generated/src | ||
execCommand("rm -rf src/generated/src"); | ||
|
||
// Step 6: Remove tsp-location.yaml from generated folder | ||
execCommand("rm src/generated/tsp-location.yaml"); | ||
|
||
// Step 7: Read and update package.json | ||
console.log("Updating package.json dependencies..."); | ||
const packageJsonPath = path.resolve("./package.json"); | ||
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf8")); | ||
|
||
// Remove dependency on @azure/core-client and add @azure-rest/core-client | ||
delete packageJson.dependencies["@azure/core-client"]; | ||
packageJson.dependencies["@azure-rest/core-client"] = "^2.0.0"; | ||
|
||
// Write updated package.json back to disk | ||
fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2), "utf8"); | ||
|
||
// Generated code changes | ||
// Workaround for https://github.com/Azure/autorest.typescript/pull/2135/files | ||
const modelsPath = path.resolve("./src/generated/models/models.ts"); | ||
let modelsContent = fs.readFileSync(modelsPath, "utf8"); | ||
modelsContent = modelsContent | ||
.replace( | ||
/created: !item\["created"\] \? item\["created"\] : new Date\(item\["created"\]\),/g, | ||
'created: !item["created"] ? item["created"] : new Date(item["created"] * 1000),' | ||
) | ||
.replace( | ||
/updated: !item\["updated"\] \? item\["updated"\] : new Date\(item\["updated"\]\),/g, | ||
'updated: !item["updated"] ? item["updated"] : new Date(item["updated"] * 1000),' | ||
) | ||
.replace( | ||
/notBefore: !item\["nbf"\] \? item\["nbf"\] : new Date\(item\["nbf"\]\),/g, | ||
'notBefore: !item["nbf"] ? item["nbf"] : new Date(item["nbf"] * 1000),' | ||
) | ||
.replace( | ||
/expires: !item\["exp"\] \? item\["exp"\] : new Date\(item\["exp"\]\),/g, | ||
'expires: !item["exp"] ? item["exp"] : new Date(item["exp"] * 1000),' | ||
) | ||
.replace( | ||
/nbf: !item\["notBefore"\] \? item\["notBefore"\] : item\["notBefore"\].getTime\(\),/g, | ||
'nbf: !item["notBefore"] ? item["notBefore"] : item["notBefore"].getTime() / 1000,' | ||
) | ||
.replace( | ||
/exp: !item\["expires"\] \? item\["expires"\] : item\["expires"\].getTime\(\),/g, | ||
'exp: !item["expires"] ? item["expires"] : item["expires"].getTime() / 1000,' | ||
); | ||
|
||
fs.writeFileSync(modelsPath, modelsContent, "utf8"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Name TBD: any suggestions?
skipFinalGet
seems pretty specific. Other options might beor something else - feel free to chime in. Thoughts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This name could be unclear for someone who is not too familiar with how our pollers work. Could we name it based on impact instead? e.g.
noResourceRetrieval
. I also wonder if other languages have a similar flag and what name did they choose for it.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
skipResourceLocation
orskipGetResource
maybe? Would that make sense? I don't have a good domain understanding of the LRO concepts so I am just brainstorming names 👍 feels likeresourceLocation
is a known term in LROs?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TBH I even prefer the specific name
skipFinalGet
here, because for me LRO would be three steps: initial -> polling -> final get(optional) and the main purpose of this option is to always skip the final step. I guess this would be clear with someone who knows LRO.My concern for
ResourceRetrieval
is - skipping the final get doesn't mean we will not retrieve the resources, for example maybe the resource is directly returned from the initial request or non-standard LRO returns the resources directly from polling process?But open to hear feedbacks also.