-
Notifications
You must be signed in to change notification settings - Fork 29.6k
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
AsyncLocalStorage not working on Nodejs 13.11.0 #32330
Comments
@averri - I did not run the test so not making any inferences, but: io.use((socket, next) => {
// Get the user agent from the request.
const userAgent = socket.conn.request.headers['user-agent']
// Make information available to async local storage (for logging).
storage.run(new Map(), () => {
storage.getStore().set(storageKey, {userAgent})
next()
})
}) As per the spec, in my understanding, In this case I don't see that top level asynchronous function. Probably you may want to elevate the storage.run to the outer call ( /cc @vdeturckheim |
@averri I am not clear about the sequence of calls in your example (mostly because I am unfamiliar with the Feather framework). Also cc-ing @puzpuzpuz, @Qard and @Flarna :) |
Probably something in feathers is doing something indirectly async, similar to connection pooling, and not using an |
I would also assume that this is caused by some connection pooling or similar within feathers or some module used by it (e.g. for websockets) as mentioned by @Qard |
Thanks to all folks who answered here. I initially thought it could be related to Nodejs, but I agree with all the comments here. I have requested help in the Feathersjs repository. |
Hi @vdeturckheim, thanks for your comment. I do not know the internals of the SocketIO middleware and how it calls the framework service methods. But I do know how to extend the functionality of the service methods by using mixins. I was able to get it working for service methods, but the store context is lost when the service method throws an exception. Changing the const feathers = require('@feathersjs/feathers')
const express = require('@feathersjs/express')
const socketio = require('@feathersjs/socketio')
const {AsyncLocalStorage} = require('async_hooks')
const storage = new AsyncLocalStorage()
// Logs to console, adding extra information from async local storage.
const info = (...args) => {
const store = storage.getStore() || {status: '<undefined store>'}
console.info(`${new Date().toISOString()}`, {...store}, ...args)
}
class MessageService {
async find() {
info('Invoking find') // This should log additional data from the client.
return 'Hello from the server'
}
}
// Creates an ExpressJS compatible Feathers application
const app = express(feathers())
// Parse HTTP JSON bodies
app.use(express.json())
// Parse URL-encoded params
app.use(express.urlencoded({extended: true}))
// Host static files from the current folder
app.use(express.static(__dirname))
// Add REST API support
app.configure(express.rest())
// Configure Socket.io real-time APIs
app.configure(socketio(io => {
io.use((socket, next) => {
const userAgent = socket.conn.request.headers['user-agent']
socket.feathers.store = { userAgent }
next()
})
}))
// The new mixin to create the async local storage.
app.mixins.push((service, path) => {
Object.entries(service.methods).forEach(([method, params]) => {
const paramsIdx = params.indexOf('params')
const serviceMethod = service[method]
service[method] = (...args) => {
const params = args[paramsIdx]
storage.enterWith(params.store)
return serviceMethod.apply(service, args) // The store will be available to the service method, but the context will get lost if any exception is thrown.
}
})
})
// Register a messages service
app.use('/messages', new MessageService())
// Register a nicer error handler than the default Express one
app.use(express.errorHandler())
// Start the server
app.listen(3030).on('listening', () =>
console.log('Feathers server listening on localhost:3030')
) I have seen the AsyncLocalStorage working as specified, so I'm closing this issue now. |
What steps will reproduce the bug?
Please refer the following code to reproduce the issue.
package.json
:server.js
:client.js
:Run the server:
Run the client:
How often does it reproduce? Is there a required condition?
Always.
What is the expected behavior?
When the
client.js
starts theserver.js
log should print the information retrieved from AsyncLocalStorage API:What do you see instead?
The AsyncLocalStorage API return an undefined store:
The text was updated successfully, but these errors were encountered: