deno_std icon indicating copy to clipboard operation
deno_std copied to clipboard

std/node/async_hooks: implement AsyncLocalStorage

Open lbguilherme opened this issue 2 years ago • 4 comments

I have an existing application that depends on Node's AsyncLocalStorage to run properly and Deno doesn't support it yet in the compatibility mode. So this is a feature request for that.

It has only two methods that are not marked as "experimental", I think the policy would be to implement only those:

class AsyncLocalStorage<T> {
  getStore(): T | undefined {
    // returns the currently stored value, if any
  }

  run<R, TArgs extends any[]>(value: T, callback: (...args: TArgs) => R, ...args: TArgs): R {
    // Stores the value for the current async context and calls the call back.
    // Any call to getStore from the callback (or from any other async callback initiated by it, recursively)
    // will return this value.
  }
}

I'm willing to contribute an implementation for that myself, but before I would like to ask if there is any existing machinery to track async contexts? Does Deno have some equivalent?

lbguilherme avatar Jun 03 '22 12:06 lbguilherme

I'm willing to contribute an implementation for that myself, but before I would like to ask if there is any existing machinery to track async contexts? Does Deno have some equivalent?

No, currently Deno has no infrastructure to track that. I'm sure it's something @cjihrig would be interested in.

bartlomieju avatar Jun 06 '22 10:06 bartlomieju

@bartlomieju I think we'll need to be cautious here. Node is keeping async_hooks marked as unstable indefinitely while exposing stable APIs like AsyncLocalStorage that are built on async_hooks.

cjihrig avatar Jun 06 '22 19:06 cjihrig

I'm willing to contribute an implementation for that myself, but before I would like to ask if there is any existing machinery to track async contexts? Does Deno have some equivalent?

No, currently Deno has no infrastructure to track that. I'm sure it's something @cjihrig would be interested in.

I think https://github.com/denoland/deno/issues/5638 is the base infrastructure that'd be needed to track this? Of course if that's something that makes sense to impelement here per @cjihrig's response

austinhallock avatar Jun 06 '22 19:06 austinhallock

I think it makes sense to try to implement. I think we should make sure not to paint ourselves into any corners while doing so though since the future of async_hooks is unclear on the Node.js side.

cjihrig avatar Jun 06 '22 19:06 cjihrig

@lbguilherme now that #15475 has landed, are you planning on working on this?

ascorbic avatar Dec 20 '22 19:12 ascorbic

Hi @ascorbic. I have been working on this but right now I can't find the time to finish it. I hope I can do so in the next few weeks, but if you or someone else need this and want to take over, that's not a problem.

My WIP implementation is here: https://github.com/lbguilherme/deno_std/tree/feat/async_context It includes a new async_context module for Deno with async context tracking and a AsyncLocal class. I believe this interface is easier to use than Node's, but I still need to put more thought on it. I also include the Node.js polyfills on top of these. They are mostly done, but not complete yet.

lbguilherme avatar Dec 21 '22 11:12 lbguilherme

That's great news. Your progress looks good. It's very interesting to me now because React has added support for using AsyncLocalStorage in SSR, which Next.js is now using. When your work ready, would we be able to import the polyfill without needing to enable compat mode?

ascorbic avatar Dec 21 '22 11:12 ascorbic

AsyncLocalStorage is now supported in both Deno CLI and Deno Deploy, as of [email protected].

lucacasonato avatar Jan 31 '23 21:01 lucacasonato