Hacker News new | ask | show | jobs
by rglover 4051 days ago
> For intance, when is it ever OK to let your client write directly in the database, even for their own data? If you're going to pass their calls through a deny and allow call, why not just expose RPCs to the client that will handle any writing?

Good question. A pattern I like to use for this in Meteor is to rely solely on their Method calls which allow you to restrict any database ops to the server side. The trick is that you lock down all client-side writing from the get go so you're not trying to guess whether you set your rules properly. Here's an example of that pattern: https://gist.github.com/themeteorchef/194a803f8a28840f475f.

Re: concurrent purchases in your store example, you can actually strip reactivity from certain database queries. So, on the front-end you can prevent state shifting out from under users. To control data on the server, you could have a method that checks whether or not the inventory has been depleted before allowing certain operations (e.g. routing to a new page, manipulating the database, etc). Definitely possible to do this without going bonkers.

Does that answer what you're looking for?

1 comments

Yes, thanks, sort of! The pattern you use is basically the one I would naturally do, but it doesn't feel "meteoritic"... the client side manipulation of the db really seems centric to the magic of it.

Regarding the concurrent store, forget event about the client. You need to check whether or not the inventory has been depleted and then update the inventory, and create the client's invoice. That means blocking calls, double staged commits, and a whole lot of nasty things that have nothing to do with reactivity and everything to do with integrity.

> but it doesn't feel "meteoritic"... the client side manipulation of the db really seems centric to the magic of it.

In the prototyping sense, yes. I've been working with Meteor for about two years and the pattern I shared above still feels magical when you realize what it's doing in just a few minutes of work. The client-side writes are still okay. The big problem is remembering to specify the correct allow/deny rules.

The pattern above is a sort of brute force approach to saying "I'm an idiot, I'll forget to set rules, let's make this a non-issue." Of note, I recall some chatter about dropping allow/deny rules altogether in the future, so there's likely a better solution on the horizon.

> You need to check whether or not the inventory has been depleted and then update the inventory, and create the client's invoice.

This isn't as big of a problem as it's being made out to be. Really just a few lines of code, e.g.:

```

// Fetch just makes this an array instead of a Mongo cursor.

// The fields part just strips the returned object(s) back

// with only those fields + the _id of the object.

var inventoryAvailable = Inventory.find({product: productName}, {fields: {"available": 1}}).fetch();

if ( inventoryAvailable.available > 1 ) { // Call some purchase function. } else { // Throw an error back to the client. }

```

Re: the concern around race conditions between customers, Meteor could actually have a leg up on this. Because you have reactivity, if say there was only 1 of an item left, if one customer completed the purchase before another, you could throw up an overlay on the slower customers screen saying "uh oh, the last one of these just got snatched up...get on the waiting list?"

A lot of ways to skin this cat :)