05:09
<littledan>
Can we land this PR? https://github.com/tc39/proposal-async-context/pull/87#pullrequestreview-2106646155
05:33
<Andreu Botella>
Can we land this PR? https://github.com/tc39/proposal-async-context/pull/87#pullrequestreview-2106646155
I don't know if we decided in the end to have the meetings in the public calendar
05:34
<Andreu Botella>
if you go to the link in that PR, there are no AsyncContext meetings
05:36
<Andreu Botella>
I guess I haven't considered enough the context of module evaluations
05:37
<Andreu Botella>
I've mostly been looking at APIs in the web integration
07:22
<nicolo-ribaudo>
I guess I haven't considered enough the context of module evaluations
Is there any option other than "the same as async functions"?
08:01
<Andreu Botella>
Is there any option other than "the same as async functions"?
I suspect not, but haven't looked at it enough
08:06
<Steve Hicks>
I've been researching past discussions and dug up this one (which Qard participated in many years ago): https://github.com/othiym23/node-continuation-local-storage/issues/64 Some interesting and relevant perspectives.
09:20
<littledan>
if you go to the link in that PR, there are no AsyncContext meetings
OK, let’s land a version of this patch that omits the meetings but includes the other parts
09:21
<littledan>
I think we decided to tell people, there are regular meetings at these times, join the chat to get the zoom link
09:21
<littledan>
So let’s make that be reflected in both the PR and calendar
09:21
<Chengzhong Wu>
yeah, the calendar item was not added yet. I'll move that part out
09:23
<littledan>
I guess I haven't considered enough the context of module evaluations
You’re thinking about https://github.com/tc39/proposal-async-context/issues/93 ?
09:31
<Andreu Botella>
You’re thinking about https://github.com/tc39/proposal-async-context/issues/93 ?
yeah
09:33
<littledan>
What do you think of my suggestion there, that we make modules always run in an “original” (empty) context associated with the realm? (And this should apply for import defer as well)
17:14
<Stephen Belanger>
Yeah I don’t have a better solution. For flow advocates: how bad would it be if we called LexicalVariable “Variable” and did FlowVariable in a follow-on proposal?
I'm fine with through flow being a follow-on, so long as what lands first is very clearly communicated as not providing that flow type. I feel the naming should more clearly communicate the flow type as AsyncContext.Variable alone does not communicate how it flows at all.
17:24
<Stephen Belanger>
Sure but there might not be JS on the stack when rejecting the promise, so at some point earlier you need to save off the context
In flow-through semantics you're modelling causality, so you'd just trace back through directly causal code until you reach JS again. In many cases this may just be the construction of an object which emits events or something like that. If you think of it as tracing all execution and not just JS execution then you can always trace a path back through the code to what logically caused it. That could even be something initiated before any JS ran, which would just be a root context.
17:39
<Stephen Belanger>
What do you think of my suggestion there, that we make modules always run in an “original” (empty) context associated with the realm? (And this should apply for import defer as well)
I find it easiest to think of everything as descending from a root context like that, even if it's empty. OTel does the same thing too with ROOT_CONTEXT being an empty map.
18:03
<Andreu Botella>
I'm fine with through flow being a follow-on, so long as what lands first is very clearly communicated as not providing that flow type. I feel the naming should more clearly communicate the flow type as AsyncContext.Variable alone does not communicate how it flows at all.
I worry that there might be developers that might want any kind of async propagation for their own use cases, and might not understand or care much about the difference between flow-through and flow-around
18:04
<Andreu Botella>
not sure how realistic that situation is though
18:05
<Andreu Botella>
(and I might be taking worries from the other project I'm working on and applying them to AsyncContext when they don't really apply)
18:23
<Stephen Belanger>
I think people generally will have a particular flow in mind for their use case. Likely lacking nuance in the details, but they'll have a general flow in mind, I would think.
18:24
<Stephen Belanger>
I do expect people might make mistakes between the two at first due to lack of understanding though.
18:25
<Stephen Belanger>
The call-only flow does seem like a reasonable starting point though, given the simpler scoping of only flowing into calls and not back out.
18:26
<Stephen Belanger>
I'm just not sure exactly how to describe that succinctly to users. As always, one of the hardest problems in CS is naming things. 😅
20:44
<Steve Hicks>
Just thinking out loud here - it feels a little bit like the difference between const and var w.r.t. for loops. We all remember the bad old days when you'd write for (var key in obj) { tasks.push(function() { console.log(key); }); } and get ten copies of the same key since they all closed over the same reference. So that would be the flow-through case (not making the analogy to be pejorative), while the lexical/block-scoped version is flow-around.
20:44
<Steve Hicks>
Does that help at all with naming? Maybe not.
20:50
<Steve Hicks>
Thinking about people making mistakes or not knowing how to reason about it, or which to pick - I generally expect this to be more of an advanced user feature. I know Shu and others were concerned about the possibility of detrimental performance due to propagating way too many variables. This may not be as "here be dragons" as, say, FinalizationRegistry, but a caveat emptor may still be in order for anyone considering introducing a new variable. I think a bigger concern is cargo-culting snapshot/wrap calls everywhere, and given that even we don't know what the right context is, it seems highly unlikely ordinary users will be able to make heads or tails of it.
21:03
<littledan>
In flow-through semantics you're modelling causality, so you'd just trace back through directly causal code until you reach JS again. In many cases this may just be the construction of an object which emits events or something like that. If you think of it as tracing all execution and not just JS execution then you can always trace a path back through the code to what logically caused it. That could even be something initiated before any JS ran, which would just be a root context.
I get that this is the intuition, but an actual implementation would have to save and propagate the snapshot forward from the last time JS runs, right?
21:03
<littledan>
I find it easiest to think of everything as descending from a root context like that, even if it's empty. OTel does the same thing too with ROOT_CONTEXT being an empty map.
Sounds like we’re agreeing? (Except I would say that the browser could put stuff in the root context, and different realms could have different root contexts)
21:07
<Stephen Belanger>
Thinking about people making mistakes or not knowing how to reason about it, or which to pick - I generally expect this to be more of an advanced user feature. I know Shu and others were concerned about the possibility of detrimental performance due to propagating way too many variables. This may not be as "here be dragons" as, say, FinalizationRegistry, but a caveat emptor may still be in order for anyone considering introducing a new variable. I think a bigger concern is cargo-culting snapshot/wrap calls everywhere, and given that even we don't know what the right context is, it seems highly unlikely ordinary users will be able to make heads or tails of it.
Propagating too many variables? It propagates exactly as many as flow-around does. It just flows in a different way. 🤷
21:08
<Stephen Belanger>
I get that this is the intuition, but an actual implementation would have to save and propagate the snapshot forward from the last time JS runs, right?
Yes. You follow the causality back to the last point JS was running and capture there.
21:08
<Steve Hicks>
Sorry, I meant Shu's concern with AsyncContext at all, not with a specific flow type
21:10
<Stephen Belanger>
Sounds like we’re agreeing? (Except I would say that the browser could put stuff in the root context, and different realms could have different root contexts)
Yes, generally agreeing. Though I don't feel I'm familiar enough with the intricacies of realms to say if each should get its own context or if it should be considered an additional empty node which descends from the root which initiated the realm?
21:10
<Stephen Belanger>
Sorry, I meant Shu's concern with AsyncContext at all, not with a specific flow type
Ah, yeah, that's why a few userland implementations had gone for the Context Frame idea so you only need to propagate a single frame which contains a bunch of variable states within.
21:11
<Stephen Belanger>
With that it's just a pointer copy.
21:11
<Stephen Belanger>
Which, from what I understand, is roughly what AsyncContext is doing too.
22:59
<Steve Hicks>
Which, from what I understand, is roughly what AsyncContext is doing too.
Right, I think that's one of the major concerns with anything more involved. In theory, it would be great if we could define complex merge strategies to get exactly the correct value all the time, but in practice the budget we're working with is very small and if it costs more than a simple pointer copy (regardless of the number of vars) then the budget's already gone.
23:07
<Stephen Belanger>
Well, through flow only needs a pointer copy too. It's when you want to mix flows where it gets more expensive. That having been said though, I don't really agree with the assertion that it always needs to be that absolute minimum cost as if the flow that produces doesn't match the user need then it's just pushing the cost out to the edges where it typically is even more expensive.
23:09
<Stephen Belanger>
Literally every Fortune 500 company is doing context management with Node.js at the least via an installed APM product. Optimizing for the cost of those expected flows will significantly reduce cloud costs across the industry.