-
-
Notifications
You must be signed in to change notification settings - Fork 92
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
Make userId available when a hooked function is called inside a Meteor.publish callback #7
Comments
So what I think needs to happen is to monkey-patch probably a function in |
It seems to me like using the global may be dangerous. Because the publish callback is allowed to unblock (the client subscription), this implicitly says that multiple callbacks may be running (even at the same time) in different fibers. Hence there's no clean way to store the right userId in a global. I don't completely understand how the fibers work in Meteor but maybe you can chip in. The |
I might be wrong but my interpretation of the execution of JS is that there is always only a single event loop, and Fibers are just doing some high-level stuff to simulate "threads"... but at the end of the day, it's still a single thread. For example, if you put an infinite loop in one of your publish functions, none of your other publish functions will ever run, Fibers or not -- your app will completely stall. That's because the function never has a chance to finish, so the next tick never occurs. So as long as the execution path of our code never goes off into an async path (one where execution continues in the next tick) , we are guaranteed that our variables will be as expected. I'm certainly no expert though, this is just piecing disparate knowledge together. I quickly googled "js event loop" and came across this: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/EventLoop |
Okay...thanks for explaining that! I added some client-server tests that check for a userId being loaded properly in the hooks. Client environment and server methods work; the big issue is server publish which we need to implement. See here: Sorry it's in coffeescript. However I work faster with coffeescript and I thought it would be okay for testing only. I did keep the main files in JS and even converted my spaces to tabs, though I disagree with using tabs :) I left your other test file alone as well, although you can either use this one or edit that one to add more client-server tests. We can add in a test for publish when we figure out how to do that properly. Meteor really needs a better testing framework for this kind of stuff :) |
I've been trying to write this functionality and I hit a roadblock. The function I need to monkey-patch is I'll hold for now while I think about another approach. Only thing I can think of at the moment is to wrap |
Another approach may be to just change something in the Meteor code so that |
Yeah, it might be time to formalize a pull request over to Meteor. It's a bigger undertaking than what we're doing though -- it'd be a complete rewrite. I say this because collection-hooks, as great as it is, isn't Meteor core quality. Specifically, the hook callbacks should be on a per-document basis, just like allow/deny. If we could get to that point, i.e. a more "natural" extension of what Meteor is already doing with allow/deny, I think we'd stand a chance at integrating this into Meteor core. |
OK...let's think a bit about how to do this and I'll work with you to get this completed properly. Trying to monkey-patch this functionality is going to be very difficult and unmaintainable especially if the undocumented APIs change. For now, I've just given the monkey-patched |
Sounds good. We'll have to start a dialogue with Meteor to find out if they are even interested. They may have other ideas to accomplish similar functionality. I'll ask around |
Digging through the meteor-core group, someone though up an interesting approach: https://groups.google.com/forum/#!topic/meteor-core/DzfX-ZirrtA It would allow hooks to get fired even when the database is changed directly. |
I managed to get it working. The |
What's the impetus for giving it in For example, if |
Ah yes good point, I was focused on how userId was delivered to |
I think |
Updated to pass userId as first param: 0efcbb5 |
Yes, this approach matches the other methods better as well as I'm going to make a post to meteor-core just to verify that this approach isn't going to break anything or be messed up in future releases. It will also be a good opportunity to make a pitch for supporting better hooking operations on collections and hopefully getting this stuff implemented in upstream eventually :) Follow https://groups.google.com/forum/#!topic/meteor-core/JGA_LQDEqw0 |
Question about https://github.com/meteor/meteor/blob/master/packages/accounts-base/accounts_server.js: Do you understand what it says with the part
|
I think the comment meant to say |
No, I think it's talking about doing |
Hi @matb33, I was just thinking about how to ensure that the However, what types of Meteor operations would cause the Fiber to yield and possibly mess up the stored value of Is there any way to store the value of the current
|
@mizzao I just realized I never answered your question. This sounds like the job of Meteor.bindEnvironment (maybe) For the "refactor" branch, I'm not trying anything fancy to get the userId for the find/findOne hooks unfortunately. I'd rather think of a more solid approach. |
@matb33 I've been out of the country for a couple of weeks but now I'm back and ready to help you get all this working. The ability to have |
@mizzao I wonder if passing Meteor.publish("test", function () {
return coll.find({abc: 1}, {userId: this.userId});
}); In the collection hook, since you get access to the options, you could take the userId, do whatever, and clean it up:
|
@matb33 Remember our discussion about making all of the collection operations transparent to the user, so that they wouldn't need to deal with a changed API? I can use this for now, but it's a stop-gap measure. I'll see if I can propose a better way to do things. Another question: is that |
@mizzao yeah I recall the convo, and yeah it would be nice for sure. I'm just hesitant to do anything further with that userId trick until we close off your issue with collection-hooks messing up your inserts etc The |
After writing a MySQL driver for Meteor, I've learned some new tricks that can apply here. I'm going to take another stab at making the userId available in the find hooks. |
@matb33 I thought your current version already did that? In any case, looking forward to it. |
My tricks didn't make any difference -- same general approach as last time. Open an issue if this change causes any problems! |
Hooks are great when used on the client. However, they are a bit hobbled on the server. It would be great to use them naturally inside
publish
functions.This entails two issues. The first is just trying to set the userId at all:
Even if we do something like
foo.find.call(this)
inside a publish, the getUserId call does not work properly. It'll throw an error likeTypeError: Object #<Object> has no method '_getFindSelector'
. So there's no way to hook theuserId
into a server-side find right now.Second, it would be great to somehow make
this.userId
directly available to the hook, without having to change the API usage. i.e,foo.find()
should be callable as normal inside a publish, and the find can be filtered byuserId
or whatever.A workaround for now would be to allow the
userId
to be passed in as an optional argument to the functions. This at least makes it possible, although doesn't fix the change to the API.The text was updated successfully, but these errors were encountered: