-
Notifications
You must be signed in to change notification settings - Fork 30.7k
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # 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: