Hey

It's my first attempt to contribute to ECMAScript so would love your
feedback if I better off change how I go about it.

The problem I want to highlight is that besides argument passing it is
impossible to have any information associated with a flow of async code as
any async code will create its own context and will only get the arguments
passed to it from its caller.

A simple use case for information that is not easy to pass as arguments is
"transaction ID" where unique IDs are generated at the beginning of a
transaction, and propagate that ID to any function that is being called as
part of that transaction.

However as a javascript codebase grows, it becomes hard to introduce new
project-wide information such as transaction ID when the only mechanism to
pass such information is function argument passing, and this becomes
impossible as many times you are using other libraries of code inside the
code stack, and one cannot change all the code just to add arguments.

Few examples:

   - Identify HTTP requests and print that a request ID in every log print
   that was fan-out from that request.
   - Find how many database calls one async flow created.
   - Keep pools of resources (buffers / connections / tokens) per request.

In C/C++ one can use thread local storage (https://en.wikipedia.org/
wiki/Thread-local_storage) to keep information that automatically switches
with the threads context switch.

I imagine a similar mechanism, in the spirit of javascript - define a
variable as `async`:

```
async var name = <initial value>;
```

Async variables will be saved and restored automatically when the context
is resumed. It should probably have a more precise definition in ECMAScript
terms.

```
async var reqid = '';

http_server.on('request', handler);

async function handler(req, res) => {

  // setting async variable concurrently be different requests
  // will retain the generated value for the other calls made by this
context (sync or async).
  reqid = `REQ-${uuid()}`;

  await load_data_from_db(req);
  await send_analytics_info(req);
  send_reply(res);
});

async function load_data_from_db(req) {
  console.log(`${reqid} load_data_from_db`);
  try {
     ...
  } catch (err) {
    ...
    if (err.code === 'ACCESS_DENIED') {
      console.log(`${reqid} ACCESS_DENIED. this incident will be reported.
`);
    }
  }
}

async function send_analytics_info(req) {
  console.log(`${reqid} send_analytics_info`);
  ...
  analytics.send(reqid, ...);
  ...
}

function send_reply(res) {
  console.log(`${reqid} send_analytics_info`);
  ...
  res.setHeader('reqid', reqid); // for supportability
  res.send(...);
  ...
}
```

Technically speaking, async variables should be replaced whenever there is
a context switch - either when a sync stack returns to the top stack level,
or when an async function returns from await.

However, this means that every registration of a function for later, such
as setTimeout(func), should also keep the async variables which sounds
difficult.

Would be great to hear if you think this is valuable and feasible, or maybe
there's a way to design this with less overhead.

Thanks,
Guy Margalit
_______________________________________________
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to