-
Notifications
You must be signed in to change notification settings - Fork 32
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
Should await using
Await for forward compatibility?
#189
Comments
I am not convinced we should consider implementing full Python-like context managers. If we are not borrowing that complexity, then the only purpose that adding |
My main worry is that by not awaiting unconditionally at the |
If it's an AsyncDisposable, the create function should be async in case the creation fails and needs to perform async roll back. |
I think @rbuckton 's argument is that the create can always return an AsyncDisposable. In the case of a create failing, it can technically initiate the rollback right away and return a useless AsyncDisposable that will block that rollback's completion when disposed, and maybe return the creation error there? I do agree it's not optimal, hence why I had raised this issue. |
This is part of the reason why I'm not in favor of calling it await using x = await openResourceAsync(); // explicit `await` as part of opening the resource If the intent of the symbol is purely to guide users towards |
If you do that, you can't bail out the program after you return the Disposable, the closest point you can bail out the caller is when the caller uses any method on the disposable, or until the object is disposed. function createRemoteHandle(addr: string, file: string): Creator<AsyncDisposable<Handle>> {
return { [Symbol.create]() {
const stack = new AsyncDisposableStack();
const { open, closeAsync: closeRemoteAsync } = remoteHandle(addr);
stack.defer(async () => await closeRemoteAsync());
try {
const { writeAsync, closeAsync: closeFileAsync } = open(file);
stack.defer(async () => await closeFileAsync());
return {
writeAsync,
async [Symbol.asyncDispose]() {
await using _ = stack.move();
}
};
} catch (error) {
return {
async writeAsync() {
throw error;
},
async [Symbol.asyncDispose]() {
await using _ = stack.move();
throw error;
}
};
}
} };
}
{
await using handle = createRemoteHandle(addr, file); // if the Symbol.create function fails,
await someIntensiveOperations(); // you can't bail out here;
await handle.writeAsync(data); // only here you have a chance to bail
} And if |
As I said, I think if you're going to perform any kind of async acquisition of a resource, you should do so explicitly in the initializer, i.e. |
But the type AsyncDeferrer = AsyncDisposableStack["defer"];
function AsyncDeferrer(): Creator<Disposable<AsyncDeferrer>> {
return { [Symbol.create]() {
const stack = new AsyncDisposableStack();
return Object.assign(stack.defer.bind(stack), {
[Symbol.asyncDispose]: stack.dispose.bind(stack)
});
} };
}
async function createRemoteHandle(defer: AsyncDeferrer, addr: string, file: string): Handle {
const { openAsync, closeAsync: closeRemoteAsync } = await remoteHandle(addr);
defer(async () => await closeRemoteAsync());
const { writeAsync, closeAsync: closeFileAsync } = await openAsync(file);
defer(async () => await closeFileAsync());
return { writeAsync };
}
{
await using defer = AsyncDeferrer();
const handle = await createRemoteHandle(defer, addr, file);
await someIntensiveOperations();
await handle.writeAsync(data);
} |
Given the talks about potentially adding a
Symbol.asyncEnter
in follow-up proposals, I would like to discuss the implications.I assume that a
[Symbol.asyncEnter]()
method would return a promise (or it wouldn't have to be differentiated from[Symbol.enter]()
), in which case theawait using
declaration would have to introduce anAwait
step for the result.Given that we at Agoric are still opposed to non statically analyzable conditional await points (aka depending on the value), and that we consider a later change to the static
await using
semantics to be a non backward compatible change for the same reason, if there is a fair possibility of such future language extensions, we ask the champions to consider introducing anAwait
step today for anyawait using
declaration.The text was updated successfully, but these errors were encountered: