Skip to content
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

Hook function cannot access request-context variables #7292

Closed
mtbnunu opened this Issue Nov 30, 2018 · 6 comments

Comments

Projects
None yet
3 participants
@mtbnunu
Copy link

mtbnunu commented Nov 30, 2018

When using await approach, request context variables returns undefined in pre find* hooks

I have noticed that it is accessible inside
pre save

on related note, if using callback approach, the context variables are not accessible inside the callback function.
This may or may not be related to mongoose code, but with combination of original issue it creates bigger problem since neither approach works perfectly when having to access the context variable both in pre hook and with the result.

I did find a closed ticket maked cannot reproduce but I was able to modify the given sample code to reproduce the issue:

Thanks!

const assert = require("assert");
const mongoose = require("mongoose");
mongoose.set("debug", true);

const httpContext = require("express-http-context");
const superagent = require("superagent");
const express = require("express");

const GITHUB_ISSUE = `gh7292`;
const connectionString = `mongodb://localhost:27017/${GITHUB_ISSUE}`;
const { Schema } = mongoose;

run()
	.then(() => console.log("done"))
	.catch(error => console.error(error.stack));

async function run() {
	await mongoose.connect(connectionString);
	await mongoose.connection.dropDatabase();

	const app = express();

	app.use(httpContext.middleware);

	const userSchema = new Schema({ name: String });

	userSchema.pre("find", function(next) {
		console.log(httpContext.get("test"));
		next();
	});

	const User = mongoose.model("User", userSchema);

	app.get("/", async (req, res) => {
		httpContext.set("test", "42");
		const user = await User.find({});
		res.json({ ok: 1 });
	});

	await app.listen(3003);

	await superagent.get("http://localhost:3003/");

	console.log("done");
	process.exit(0);
}

express@4.16.4 express-http-context@1.2.0 mongoose@5.3.12

Originally posted by @mtbnunu in #7001 (comment)

@mhombach

This comment has been minimized.

Copy link

mhombach commented Nov 30, 2018

You are perfectly able to access httpContext and you are doing it correct. But you are missing the real issue here and that is, that httpContext.get("test") is really undefined. This has nothing to do with the context. If you change console.log(httpContext.get("test")); to console.log(JSON.stringify(httpContext)); you will see, that you are able to access the variable.
Why your specific httpContext.get("test") is undefined in general, is out of my scope and also has nothing to do with mongoose ;) I don't know the express-http-context-library. You may check your other code and find your real issue here, but it is not related to the scope of mongoose-hooks :)

@vkarpov15 vkarpov15 added this to the 5.3.16 milestone Dec 6, 2018

@vkarpov15

This comment has been minimized.

Copy link
Collaborator

vkarpov15 commented Dec 6, 2018

Thanks for reporting, will investigate ASAP

@mhombach this is an issue we should look into. Enough people use CLS / request context style libs, we should be able to support them 👍

@vkarpov15

This comment has been minimized.

Copy link
Collaborator

vkarpov15 commented Dec 11, 2018

@mtbnunu I opened up an issue in the underlying cls-hooked library. I managed to identify a potential issue but I'll wait to see if it is expected behavior or not before really digging into it. Looks like there's some unexpected behavior with await and custom thenables. In the meantime, the workaround is easy, just use exec() to get a real promise to await on.

	app.get("/", async (req, res) => {
		httpContext.set("test", "42");
		const user = await User.find({}).exec(); // <-- Change here
		res.json({ ok: 1 });
	});
@vkarpov15

This comment has been minimized.

Copy link
Collaborator

vkarpov15 commented Dec 13, 2018

Looks like superagent switched how they do promises a while back: visionmedia/superagent@43aaa4a . Will investigate whether this helps us

@vkarpov15

This comment has been minimized.

Copy link
Collaborator

vkarpov15 commented Dec 28, 2018

Looks like superagent's approach doesn't help with this particular issue. Will look into cls-hooked more later.

@vkarpov15 vkarpov15 modified the milestones: 5.4.2, 5.4.4 Dec 28, 2018

@vkarpov15

This comment has been minimized.

Copy link
Collaborator

vkarpov15 commented Jan 13, 2019

I looked some more at cls-hooked and haven't been able to make any headway. The issue seems to apply to all custom thenables, not just Mongoose. The workaround is easy, just use .exec(). I'm going to close this for now.

Related to #7398 and other issues. Perhaps we can make queries extend Promise in the future and solve this issue without using .exec()

@vkarpov15 vkarpov15 closed this Jan 13, 2019

@vkarpov15 vkarpov15 removed this from the 5.4.4 milestone Jan 13, 2019

@vkarpov15 vkarpov15 removed the help wanted label Jan 13, 2019

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.