The best way to model an offline multi-user app

89 views
Skip to first unread message

Stuart Langridge

unread,
Aug 2, 2016, 10:44:49 PM8/2/16
to PouchDB

So, requirements :-)

There are a million numbers. Users may "grab" a number. You can't grab more than one number a day, and you can't grab a number that someone else has already grabbed. You can "grab" while offline, and then that's confirmed (or denied) once you come back online again. The question is: how best to model this?

I'm using Pouch on client (the browser) and on server.

So, obvious thought:

We set up two replications
     // this sends all pending docs to the server
    local.replicate.to(remote, function(doc) { return doc.state == "pending"; })
    // this retrieves all my docs from the server, including ones that the server has updated
    // obviously this would actually be a pointer to a server view so the function runs on the server
    local.replicate.from(remote, function(doc) { return doc.username == myusername; })

Grabbing a number writes a doc, {username: myusername, number: 521, state: "pending"} into my local PouchDB.

Replication, when online, writes that doc to the central PouchDB (which everyone replicates to). Docs without state==pending are denied by a validate_doc_update (or by a plugin which overrides bulkDocs, whatever), so that you have to say that your update is pending.

A thing watches the server Pouch changes feed, and whenever it gets a change which has pending:true and number in, it runs a function.
That function checks if there's not already a document with that number and pending:false (that is: it's checking if this number is already grabbed).
If this number is NOT grabbed, then it puts the doc with state="accepted".
If this number IS grabbed, then it puts the doc with state="rejected".

The second replication, above, will then pull this changed doc back down.

So, first question: is this the best way to model this, do we think? I am open to suggestions here.
Secondly: it would be useful, if my grab is rejected, to find out who actually *has* that number. So what I'd like to say is local.replicate.from(remote, function(doc) { any doc which has a number which I've tried to grab and failed }) but I can't think of a good way of doing that :-)

Thirdly... how do you do the "only one grab a day"? What I'd *like* to do is, when a doc is put to the server by replication, quietly add a timestamp to it. But as far as I can tell one can't do that. I could, I suppose, have another _changes watcher on the server which does that, but then I have to have another validate_doc_update which confirms that nobody changes a timestamp in a doc, and then I have to allow the server _changes watcher to avoid that check, and... grr. So, perhaps there's a better way?

sil

Jan Lehnardt

unread,
Aug 4, 2016, 5:59:20 AM8/4/16
to pou...@googlegroups.com
Heya Stewart 👋

I think you’ve got it mostly, I’d just make a few adjustments. Here’s why:

1. imagine two people grab the same number at the same time while online. Your changes feed handler will run and process one and the other. Since requests to PouchDB are async, you can run into the situation where for both users the handler will have checked that the number hasn’t been taken yet, and then will accept it for both handlers. Boo!

That, plus the “only one per day” requirement leads me to this small alteration:

Make the _id of the “grabbing” doc significant. E.g.:

`grab/20160804/521` i.e.: `type/YYYYMMDD/number`

(assuming db-per-user)

or `type/userid/YYMMDD/number` if one DB for all users.

Your _changes handler then can atomically check whether a number has been grabbed by trying to create a doc `grab/YYYYMMDD/number` in the server-side database that keeps track of numbers. If the doc create goes through, you successfully grabbed the number, if it fails (409 rev mismatch), then it already got grabbed.

I’m glossing over a few details, but I’m sure you can take it from here :)

Best
Jan
--



--
You received this message because you are subscribed to the Google Groups "PouchDB" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pouchdb+u...@googlegroups.com.
To post to this group, send email to pou...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/pouchdb/61770500-96f9-431e-9688-8ebe6110b6d2%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Stuart Langridge

unread,
Aug 11, 2016, 11:36:24 AM8/11/16
to PouchDB
On Thursday, 4 August 2016 10:59:20 UTC+1, Jan Lehnardt wrote:
Heya Stewart 👋
Hey Jan :-) 
Your _changes handler then can atomically check whether a number has been grabbed by trying to create a doc `grab/YYYYMMDD/number` in the server-side database that keeps track of numbers. If the doc create goes through, you successfully grabbed the number, if it fails (409 rev mismatch), then it already got grabbed.
Sneaky. I would not have thought of this, and you're right. Cheers!

sil 
Reply all
Reply to author
Forward
0 new messages