On Tue, Aug 7, 2012 at 7:36 PM, craiggwilson <
craigg...@gmail.com>
wrote:
> Use a mongodb collection like an event log [...] To ensure
> concurrency, you'll need to use some sort of lock. Another collection
> called lock would do. [...]
This looks like a smart solution, and it gives me quite some insight on
how to design things with MongoDB - thanks for that! However, I plan to
keep this solution for later. At the moment I want to avoid premature
optimization.
> For reading, I don't know how you are storing the aggregated blocks
> for the image
The image handling is all done separately. In fact the Reality Builder
is just a web-widget with transparent background that you may put on top
of anything you like, be it a live stream or prerecorded images.
> [...] Even if you incorporate the ability for multiple users to update
> the construction simultaneously if their updates do not confict,
My proposal *does* allow for multiple users to update the construction
simultaneously. The check in step 3 (see below) just checks that the
construction *as a whole* matches the rules.
> the requirements still dictate the 1 writer at a time rule because you
> have to handle conflicts based on committed blocks.
Naturally, one writer at a time. It's MongoDB + Node.js after all. :-)
> I'd encourage you to look at some patterns called CQRS and
> EventSourcing as they might help you model your business logic.
This is cool - thanks for the suggestions!
Finally, my original proposal updated for better efficiency:
* Initialization (block data is simplified!):
db.construction.insert({_id: 'blocksData',
version: 0,
blocks: [[1, 0, 0], [1, 1, 0]]})
* To add a new block:
1. Get blocks data:
blocksData = db.construction.findOne({_id: 'blocksData'})
2. Add a new block (e.g. `newBlock = [3, 0, 0]`):
blocksData.blocks.push(newBlock)
3. Check if `blocksData.blocks` adheres to game's rules:
// something complicated
4. If the check failed, then exit.
5. Update, unless the blocks in the database have changed:
db.construction.update({_id: 'blocksData',
version: blocksData.version},
{$inc: {version: 1},
$push: {blocks: newBlock}})
6. Check for status of update:
db.$cmd.findOne({getlasterror: 1});
7. If the update failed ("n": 0), then go back to step 1.