googleapis / googleapis/google-cloud-node

`AsyncLocalStorage` context not exiting properly when `.run()` called in `.on('message')` handler

Aperta
#7,628 1 commento 5 reazioni 1 assegnatario Rivendicata da @feywind Vedi su GitHub
api: pubsub priority: p2 type: feature request
Lingua principale
TypeScript
Stelle
3.2k
Fork
712
Merge medio
2g 9h
PR unite (30g)
104

Descrizione

### Please make sure you have searched for information in the following guides.

- [x] Search the issues already opened: https://github.com/GoogleCloudPlatform/google-cloud-node/issues
- [x] Search StackOverflow: http://stackoverflow.com/questions/tagged/google-cloud-platform+node.js
- [x] Check our Troubleshooting guide: https://github.com/googleapis/google-cloud-node/blob/main/docs/troubleshooting.md
- [x] Check our FAQ: https://github.com/googleapis/google-cloud-node/blob/main/docs/faq.md
- [x] Check our libraries HOW-TO: https://github.com/googleapis/gax-nodejs/blob/main/client-libraries.md
- [x] Check out our authentication guide: https://github.com/googleapis/google-auth-library-nodejs
- [x] Check out handwritten samples for many of our APIs: https://github.com/GoogleCloudPlatform/nodejs-docs-samples

### A screenshot that you have tested with "Try this API".

This problem applies specifically to the Node.js client in combination with AsyncLocalStorage. It's not an issue with the API itself.

### Link to the code that reproduces this issue. A link to a **public** Github Repository or gist with a minimal reproduction.

https://github.com/swarmiakimmo/pubsub-async-local-storage-repro

### A step-by-step description of how to reproduce the issue, based on the linked reproduction.

Running in Node v22.16.0.

1. Edit `projectId`, `topicName`, and `subscriptionName` in index.js. They need to refer to a GCP project you have access to, an existing topic name and subscription name.
1. `npm install`
1. Run the example script: `GOOGLE_APPLICATION_CREDENTIALS=/Users/kimmo/.gcloud/ node index.js`

### A clear and concise description of what the bug is, and what you expected to happen.

**The issue**

Once you run the example script, these see these log lines appear:

```
ERROR: operation context already has an ID: 412ebf00-3e8f-4ab1-8ae5-f001ebb97229
```

which means that the `AsyncLocalStorage` context _already_ had a value when it entered the `.on('message', ...)` callback handler.

The fact that previous context is somehow visible to the handler at that point also hints that there could be a potential memory leak when PubSub client is used together with `AsyncLocalStorage`. The contexts "stack up", so it's possible to have multiple nested `.run()` calls with their own isolated store. If the handler sees the context value at that point in the handler _(instead of it being cleared)_, something seems to retain the reference to the ALS.

**Expected result**

At the beginning of `on('message', ...)` handler, the `als.getStore()` should return `undefined` because we should be processing another message in another callback context.

Whenever `.run()` callback function exits, also the context should be exited as stated in [Node.js API docs](https://nodejs.org/docs/latest-v22.x/api/async_context.html#asynclocalstoragerunstore-callback-args):

> Runs a function synchronously within a context and returns its return value. **The store is not accessible outside of the callback function.** The store is accessible to any asynchronous operations created within the callback.

### A clear and concise description WHY you expect this behavior, i.e., was it a recent change, there is documentation that points to this behavior, etc. **

The expected behavior I described is how `AsyncLocalStorage` should work by standard. There's something that the PubSub Node.js internally does to break the normal expected behavior.

Guida per i contributori

Apri la guida per i contributori

Valutazione

Questa issue non è ancora stata valutata.

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.