Meteor-Community-Packages / meteor-collection-hooks

Meteor Collection Hooks
https://atmospherejs.com/matb33/collection-hooks
MIT License
657 stars 92 forks source link

Common context between hooks of same request #48

Closed olivermaldonado closed 10 years ago

olivermaldonado commented 10 years ago

Is there currently a shared scope where hooks for the same request can share variables?

For example, if several hooks need some data stored in the database, instead of each hook performing the same query two or more times, just temporarily store the result in the shared scope and use it from there.

I did some tests but the context is not the same between hooks, and I'm not sure if this.context would be the place to store that data.

mizzao commented 10 years ago

You can use Meteor environment variables for this:

https://eventedmind.com/feed/meteor-dynamic-scoping-with-environment-variables

Because the dynamic scope of a Fiber doesn't change across synchronous database operations, it's basically mimicking using some sort of global state (but just within the Fiber.)

olivermaldonado commented 10 years ago

But how would I use a Meteor.EnvironmentVariable between separate hooks? As apparently each of the hooks are called from separate call stacks. I see no way to transfer environment variables from one hook to the other.

var SomeValue = new Meteor.EnvironmentVariable;

someCollection.before.insert(function (userId, doc) {
    SomeValue.withValue("expensive result", function() {
        console.log("Before Hook 1", SomeValue.get()); //OK
    })
});

someCollection.before.insert(function (userId, doc) {
    console.log("Before Hook 2", SomeValue.get()); //undefined
});

This would only work if everything is declared on one single hook. Which is easy to do. I'm just more used to declaring each different rule on it's own hook.

Or maybe there is a way of using withValue so that it affects all following hooks?

mizzao commented 10 years ago

I think you should up on how dynamic scoping works. In Meteor, the dynamic scope is that of the currently executing Fiber, so if you run a bunch of operations sequentially, it will maintain the value of the environment variable.

olivermaldonado commented 10 years ago

Thanks for the help. I understand how dynamic scoping works, but I can't see how you can use Meteor.EnvironmentVariable in independently declared hooks, without modifying the project's code.

Could you please provide an example with two hook declarations (for the same operation) that use the same value for an EnvironmentVariable?

matb33 commented 10 years ago

I don't think this would be too difficult a change, i.e. where we do the extend with the transform and ctx, the shared object could go there. I agree it could be useful

matb33 commented 10 years ago

@olivermaldonado did you end up trying to store some data on this.context as you mentioned? Looking through the code, it looks like storing your shared data in there should carry through across hooks for the same collection of the same method and pointcut (before/after)

olivermaldonado commented 10 years ago

I just did some tests. It does work. this.context does preserve it's state across hooks, even between before and after hooks.

Funny, because I think I did these tests before and it did not work.

In any case, it's working now.

matb33 commented 10 years ago

Happy to hear! AFAIK there were no recent code changes that would affect this behavior. If it stops working for some reason, reopen this issue (or create new one) and we can work towards a solution