summaryrefslogtreecommitdiff
path: root/designs
diff options
context:
space:
mode:
Diffstat (limited to 'designs')
-rw-r--r--designs/syncs.json12
1 files changed, 11 insertions, 1 deletions
diff --git a/designs/syncs.json b/designs/syncs.json
index bab5622..f9aa90d 100644
--- a/designs/syncs.json
+++ b/designs/syncs.json
@@ -1,11 +1,21 @@
{
"_id": "_design/syncs",
"updates": {
- "put": "function(doc, req){\n if (!doc) {\n doc = {}\n doc['_id'] = 'u1db_sync_log';\n doc['syncs'] = [];\n }\n body = JSON.parse(req.body);\n // remove outdated info\n doc['syncs'] = doc['syncs'].filter(\n function (entry) {\n return entry[0] != body['other_replica_uid'];\n }\n );\n // store u1db rev\n doc['syncs'].push([\n body['other_replica_uid'],\n body['other_generation'],\n body['other_transaction_id']\n ]);\n return [doc, 'ok'];\n}\n\n"
+ "put": "function(doc, req){\n if (!doc) {\n doc = {}\n doc['_id'] = 'u1db_sync_log';\n doc['syncs'] = [];\n }\n body = JSON.parse(req.body);\n // remove outdated info\n doc['syncs'] = doc['syncs'].filter(\n function (entry) {\n return entry[0] != body['other_replica_uid'];\n }\n );\n // store u1db rev\n doc['syncs'].push([\n body['other_replica_uid'],\n body['other_generation'],\n body['other_transaction_id']\n ]);\n return [doc, 'ok'];\n}\n\n",
+ "state": "/**\n * This update handler stores information about ongoing synchronization\n * attempts from distinct source replicas.\n *\n * Normally, u1db synchronization occurs during one POST request. In order to\n * split that into many serial POST requests, we store the state of each sync\n * in the server, using a document with id 'u1db_sync_state'. To identify\n * each sync attempt, we use a sync_id sent by the client. If we ever receive\n * a new sync_id, we trash current data for that source replica and start\n * over.\n *\n * We expect the following in the document body:\n *\n * {\n * 'source_replica_uid': '<source_replica_uid>',\n * 'sync_id': '<sync_id>',\n * 'seen_ids': [['<doc_id>', <at_gen>], ...], // optional\n * 'changes_to_return': [ // optional\n * 'gen': <gen>,\n * 'trans_id': '<trans_id>',\n * 'changes_to_return': [[<doc_id>', <gen>, '<trans_id>'], ...]\n * ],\n * }\n *\n * The format of the final document stored on server is:\n *\n * {\n * '_id': '<str>',\n * '_rev' '<str>',\n * 'ongoing_syncs': {\n * '<source_replica_uid>': {\n * 'sync_id': '<sync_id>',\n * 'seen_ids': [['<doc_id>', <at_gen>[, ...],\n * 'changes_to_return': {\n * 'gen': <gen>,\n * 'trans_id': '<trans_id>',\n * 'changes_to_return': [\n * ['<doc_id>', <gen>, '<trans_id>'],\n * ...,\n * ],\n * },\n * },\n * ... // info about other source replicas here\n * }\n * }\n */\nfunction(doc, req) {\n\n // prevent updates to alien documents\n if (doc != null && doc['_id'] != 'u1db_sync_state')\n return [null, 'invalid data'];\n\n // create the document if it doesn't exist\n if (!doc)\n doc = {\n '_id': 'u1db_sync_state',\n 'ongoing_syncs': {},\n };\n\n // parse and validate incoming data\n var body = JSON.parse(req.body);\n if (body['source_replica_uid'] == null)\n return [null, 'invalid data'];\n var source_replica_uid = body['source_replica_uid'];\n\n if (body['sync_id'] == null)\n return [null, 'invalid data'];\n var sync_id = body['sync_id'];\n\n // trash outdated sync data for that replica if that exists\n if (doc['ongoing_syncs'][source_replica_uid] != null &&\n doc['ongoing_syncs'][source_replica_uid]['sync_id'] != sync_id)\n delete doc['ongoing_syncs'][source_replica_uid];\n\n // create an entry for that source replica\n if (doc['ongoing_syncs'][source_replica_uid] == null)\n doc['ongoing_syncs'][source_replica_uid] = {\n 'sync_id': sync_id,\n 'seen_ids': {},\n 'changes_to_return': null,\n };\n\n // incoming meta-data values should be exclusive, so we count how many\n // arrived and deny to accomplish the transaction if the count is high.\n var incoming_values = 0;\n var info = doc['ongoing_syncs'][source_replica_uid]\n\n // add incoming seen id\n if ('seen_id' in body) {\n info['seen_ids'][body['seen_id'][0]] = body['seen_id'][1];\n incoming_values += 1;\n }\n\n // add incoming changes_to_return\n if ('changes_to_return' in body) {\n info['changes_to_return'] = body['changes_to_return'];\n incoming_values += 1;\n }\n\n if (incoming_values != 1)\n return [null, 'invalid data'];\n\n return [doc, 'ok'];\n}\n\n"
},
"views": {
+ "state": {
+ "map": "function(doc) {\n if (doc['_id'] == 'u1db_sync_state' && doc['ongoing_syncs'] != null)\n for (var source_replica_uid in doc['ongoing_syncs']) {\n var changes = doc['ongoing_syncs'][source_replica_uid]['changes_to_return'];\n var sync_id = doc['ongoing_syncs'][source_replica_uid]['sync_id'];\n if (changes == null)\n emit([source_replica_uid, sync_id], null);\n else\n emit(\n [source_replica_uid, sync_id],\n {\n 'gen': changes['gen'],\n 'trans_id': changes['trans_id'],\n 'number_of_changes': changes['changes_to_return'].length\n });\n }\n}\n"
+ },
+ "changes_to_return": {
+ "map": "function(doc) {\n if (doc['_id'] == 'u1db_sync_state' && doc['ongoing_syncs'] != null)\n for (var source_replica_uid in doc['ongoing_syncs']) {\n var changes = doc['ongoing_syncs'][source_replica_uid]['changes_to_return'];\n var sync_id = doc['ongoing_syncs'][source_replica_uid]['sync_id'];\n if (changes == null)\n emit([source_replica_uid, sync_id, 0], null);\n else if (changes.length == 0)\n emit([source_replica_uid, sync_id, 0], []);\n else\n for (var i = 0; i < changes['changes_to_return'].length; i++)\n emit(\n [source_replica_uid, sync_id, i],\n {\n 'gen': changes['gen'],\n 'trans_id': changes['trans_id'],\n 'next_change_to_return': changes['changes_to_return'][i],\n });\n }\n}\n"
+ },
"log": {
"map": "function(doc) {\n if (doc._id == 'u1db_sync_log') {\n if (doc.syncs)\n doc.syncs.forEach(function (entry) {\n emit(entry[0],\n {\n 'known_generation': entry[1],\n 'known_transaction_id': entry[2]\n });\n });\n }\n}\n"
+ },
+ "seen_ids": {
+ "map": "function(doc) {\n if (doc['_id'] == 'u1db_sync_state' && doc['ongoing_syncs'] != null)\n for (var source_replica_uid in doc['ongoing_syncs']) {\n var sync_id = doc['ongoing_syncs'][source_replica_uid]['sync_id'];\n emit(\n [source_replica_uid, sync_id],\n {\n 'seen_ids': doc['ongoing_syncs'][source_replica_uid]['seen_ids'],\n });\n }\n}\n"
}
}
} \ No newline at end of file