-
Notifications
You must be signed in to change notification settings - Fork 7.3k
context: core module to manage generic contexts for async call chains #5243
Comments
Thinking about it a little more, another approach puts the accessors for the state on the namespace, rather than the context. This is actually the way I'd want to use contexts most of the time: // everything not redefined here remains the same
Context.prototype._set = function (name, value) {
this.bag[name] = value;
};
Context.prototype._get = function (name) {
return this.bag[name];
};
function Namespace(name) {
EventEmitter.call(this);
this.name = name;
namespaces[name] = this;
}
util.inherits(Namespace, EventEmitter);
Namespace.prototype.set = function (name, value) {
if (!this.active) {
return;
// alternately: this.emit('error', "No active context on namespace " + this.name + " to set " + name "."); return;
// alternately: throw new Error("No active context on namespace " + this.name + " to set " + name ".");
}
this.active._set(name, value);
};
Namespace.prototype.get = function (name) {
if (!this.active) {
return;
// alternately: this.emit('error', "No active context on namespace " + this.name + " to get " + name "."); return;
// alternately: throw new Error("No active context on namespace " + this.name + " to get " + name ".");
}
return this.active._get(name);
}; This makes more sense for my use cases, but I'm on the fence as to whether it's the most appropriate general solution. This also allows for fallthrough lookup with nested contexts on a domain while decoupling the context lifecyle from managing the associated namespace state, which makes a lot of sense to me, but might not to everyone else. |
https://github.com/othiym23/node-local-context contains an implementation of the above API. Another module will be along presently to dynamically patch the Node runtime to use this as a basis for domains as a proof of concept that domains will work with this style of API, as well as how it might work in Node core. |
I just had a look to your userland implementation of local context. It could very useful! One question: Do the programmer need to explicitly bind each callback to the current context, or is it implicit like with implicit domain binding"? |
If you're using this module on its own, you'll need to explicitly bind functions into contexts. I'm working right now on a separate module that will do implicit binding (by supplanting the built-in domain code in Node <= 0.10.x). It's definitely the trickier part of the implementation, but I hope to have that up and available shortly, and will link to it from this issue. |
That's very clear. Thanks for the clarification! Regarding the "separate module that will do implicit binding", I have two questions: 1/ How would you summarize what is missing from the built-in domain module that makes necessary to create a new system to manage local context? In other words, what are the differences between domains and the new "local context" module? From other discussions I read on this topic, I understand the way domains handle errors make them inadequate to manage local contexts. 2/ When using a database connection pool, it's frequent for a connection to be created in the context of a domain attached to the current HTTP request. This is problematic when the connection is retrieved some time later in the context of another HTTP request, because then the database connection is incorrectly associated to the "old" close HTTP request, instead of the current one. The solution is of course to have some code to prevent that in the connection pool, or wrapping the connection pool, that makes sure to attach the database connection to the active domain just after poping the connection from the pool and before using it. My question: do you expect your new module to change or facilitate this in some way? Anyway, thanks for your work on this topic! |
There are two primary differences:
The use case you describe is the motivation for there being different methods for If you can come up with a description of a method to automate that, I'm open to trying to make it work with |
@SLaks That's exactly what I'm working on right now, but if you want to give it a shot, do! It's trickier than it looks! |
Hey @SLaks, I've been working on this for about a week now, but monkeypatching stuff close to the event loop is actually weird, hard and scary. Have you poked at this at all? Do you want to join sources on this problem? I'm a strong enough nerd to admit when I'm up against the wall a little. 😉 |
I've been busy with other stuff and have not had time to look at this recently. What kind of problems are you encountering? |
This actually supplants domains, not adds things to them -- without doing that, it's impossible to get the proper nesting behavior (also, with namespaces, domains become a namespace, rather than containing the namespaces). Right now, I'm experimenting with completely replacing all of the the JS side of the Node event loop, although I'm hoping to come up with something less invasive before I'm done. I completely understand not having time, and I'll try to throw up what I have so far at the end of the day so others can see it. I just thought I'd throw myself on the mercy of the community, because this is proving to be kind of a pain in the ass. 🎉 |
@othiym23 how much of this is covered by AL? |
Between CLS, AL, and the pending |
@othiym23 do we still use continuation-local-storage from npm, or is there another module, or example for how do do it in core? |
@OrangeDog CLS is still working (and supported, although I don't have as much time for it as I'd like), you can take a look at StrongLoop's |
sorry for comment on this old thread. |
There never was a v0.13 |
thx @OrangeDog for pointing out. so does it mean this feature never make it into nodejs? or it is part of nodejs 4.x and above? |
Node v4 and v6 doesn't have this feature. So, this feature is abandoned? |
This turned into Since then, work has proceeded on the low-level hooks under the name It turns out it's tricky to implement something like this without complicated consequences for the overall performance of Node as a platform, and coming up with an implementation that has good performance while also handling the core use cases of performance monitoring and continuation-local storage has been a challenge. But it's work that's still in progress! |
The domains mechanism is a useful tool for adding context to errors raised in asynchronous call chains (or, if you like living dangerously / tempting the wrath of @isaacs, to recover from errors without restarting your services). It also almost serves the purposes of developers who want to annotate async call chains with metadata or extra state (examples: logging, tracing / profiling, generic instrumentation), but due to the needs of error-handling, it doesn't quite generalize enough to be truly useful in this regard. There are modules that allow developers to do similar things when they have full control over their stacks (CrabDude/trycatch and Gozala/reducers, among many others), but none of these modules are a good fit for developers writing tooling meant to be dropped transparently into user code.
See also #3733. /cc @isaacs
Here is a sketch at what the user-visible API might look like. My original attempt at this used a slightly modified version of the domains API with some special-purpose logic for dealing with nested contexts, but allowing multiple distinct namespaces is actually simpler and trades memory for execution time. It also makes it possible to special-case behavior for specific namespaces (i.e. my hope would be that domains would just become a specialized namespace, and
_tickDomainCallback
and_nextDomainTick
would be all that would be required to deal with namespaces), although that isn't included here.The API (
context.js
):Here's an example of how the API might be used:
The text was updated successfully, but these errors were encountered: