todosapp: various tweaks and fixes for demo
- handle concurrent delete and read-modify-write
- tweak instructions to use hostname/ip (not localhost)
so that the mount table name (and thus SG names) are
accessible to peers
- make "make node_modules" do "make node_modules" in
javascript/syncbase repo (to link vanadium there)
- make 'change' event handler update todos for all lists
if the change arrived via sync (since in that case the
change might not be for the current list)
Change-Id: I1834b02aa42f1a2d24b2abe94330f1689116bc85
diff --git a/Makefile b/Makefile
index 810b922..3156e47 100644
--- a/Makefile
+++ b/Makefile
@@ -50,18 +50,19 @@
node_modules: package.json $(shell $(FIND) $(V23_ROOT)/roadmap/javascript/syncbase/{package.json,src} $(V23_ROOT)/release/javascript/core/{package.json,src})
npm prune
npm install
- touch $@
# Link the vanadium and syncbase modules from V23_ROOT.
rm -rf ./node_modules/{vanadium,syncbase}
cd "$(V23_ROOT)/release/javascript/core" && npm link
npm link vanadium
- cd "$(V23_ROOT)/roadmap/javascript/syncbase" && npm link
+# Note, we run "make node_modules" in the JS syncbase repo to ensure that the
+# vanadium module is linked there.
+ cd "$(V23_ROOT)/roadmap/javascript/syncbase" && make node_modules && npm link
npm link syncbase
# Note, browserify 10.2.5 and up will share the vanadium module instance between
# todosapp and syncbase, since their node_modules symlinks point to a common
# location.
# https://github.com/substack/node-browserify/issues/1063
- touch node_modules
+ touch $@
public/bundle.min.css: $(shell find stylesheets) node_modules
lessc -sm=on stylesheets/index.less | postcss -u autoprefixer -u cssnano > $@
@@ -83,6 +84,7 @@
.PHONY: clean
clean:
rm -rf bin node_modules public/bundle.*
+ v23 goext distclean
.PHONY: lint
lint:
diff --git a/browser/index.js b/browser/index.js
index b4d8453..f916a9e 100644
--- a/browser/index.js
+++ b/browser/index.js
@@ -649,12 +649,19 @@
// TODO(sadovsky): Only read (and only redraw) what's needed based on what
// changed.
- disp.on('change', function() {
+ disp.on('change', function(fromSync) {
var onChangeDone = util.logFn('onChange', alertOnError);
that.updateLists_(function(err) {
alertOnError(err);
- var listId = getListId();
- that.updateTodos_(listId, onChangeDone);
+ if (fromSync) {
+ var listIds = _.pluck(that.state.lists.items, '_id');
+ async.each(listIds, function(listId, cb) {
+ that.updateTodos_(listId, cb);
+ }, onChangeDone);
+ } else {
+ var listId = getListId();
+ that.updateTodos_(listId, onChangeDone);
+ }
});
});
diff --git a/browser/syncbase_dispatcher.js b/browser/syncbase_dispatcher.js
index 2bea08c..e83d01b 100644
--- a/browser/syncbase_dispatcher.js
+++ b/browser/syncbase_dispatcher.js
@@ -23,7 +23,7 @@
var syncbase = require('syncbase');
var nosql = syncbase.nosql;
var vanadium = require('vanadium');
-var vtrace = vanadium.vtrace;
+var verror = vanadium.verror, vtrace = vanadium.vtrace;
var Dispatcher = require('./dispatcher');
var util = require('./util');
@@ -332,7 +332,7 @@
syncPriority: 8
});
-define('createSyncGroup', function(ctx, sgName, blessings, mt, cb) {
+define('createSyncGroup', function(ctx, sgName, blessings, mtName, cb) {
var sg = this.db_.syncGroup(sgName);
var spec = new nosql.SyncGroupSpec({
// TODO(sadovsky): Maybe make perms more restrictive.
@@ -345,7 +345,7 @@
]),
// TODO(sadovsky): Update this once we switch to {table, prefix} tuples.
prefixes: ['tb:' + this.sgNameToListId(sgName)],
- mountTables: [vanadium.naming.join(mt, 'rendezvous')]
+ mountTables: [vanadium.naming.join(mtName, 'rendezvous')]
});
sg.create(ctx, spec, MEMBER_INFO, this.maybeEmit_(cb));
});
@@ -452,7 +452,7 @@
console.log('checkForChanges_ failed: ' + err);
} else if (changed) {
console.log('checkForChanges_ detected a change');
- that.emit('change');
+ that.emit('change', true);
}
window.setTimeout(that.watchLoop_.bind(that), 500);
});
@@ -510,7 +510,17 @@
nosql.runInBatch(ctx, this.db_, opts, function(db, cb) {
var tb = db.table('tb');
tb.get(wn(ctx, 'get:' + key), key, function(err, value) {
- if (err) return cb(err);
+ if (err) {
+ if (err instanceof verror.NoExistError) {
+ // Concurrent delete, likely from a remote peer. Pretend this update
+ // never happened.
+ // TODO(sadovsky): Maybe make it so client transactions take priority
+ // over sync transactions, so that app developers don't have to worry
+ // about this concurrency scenario.
+ return cb();
+ }
+ return cb(err);
+ }
var newValue = marshal(updateFn(unmarshal(value)));
tb.put(wn(ctx, 'put:' + key), key, newValue, cb);
});
diff --git a/demo.md b/demo.md
index 61ce4be..a37030e 100644
--- a/demo.md
+++ b/demo.md
@@ -1,10 +1,7 @@
# Demo setup
This page describes how to set things up for a demo.
-For detailed explanations of the setup steps, see [README.md](README.md).
-
-FIXME: Currently, once anything is deleted, outgoing sync permanently stops
-working.
+For detailed explanations of the app setup steps, see [README.md](README.md).
## Single-machine setup
@@ -23,20 +20,8 @@
Open these urls:
- http://localhost:5000/?d=syncbase // Alice
- http://localhost:5100/?d=syncbase // Bob
-
-### Syncing a list
-
-1. In Alice's window, create list "Groceries".
-2. Add todo items and tags (as desired).
-3. Click the status button, then type in Bob's email address.
-4. Copy the `/share/...` part of the url to the clipboard.
-5. Switch to Bob's window.
-6. Replace everything after `localhost:5100` with the copied path, hit enter.
-7. After a second, Bob should see the synced "Groceries" list.
-8. Add, edit, and remove todos and tags to your heart's content and watch sync
- do its magic.
+ http://<hostname>:5000/?d=syncbase // Alice
+ http://<hostname>:5100/?d=syncbase // Bob
## Two-machine setup
@@ -55,14 +40,25 @@
Open this url:
- http://localhost:5000/?d=syncbase
+ http://<hostname>:5000/?d=syncbase
-### Syncing a list
+## Syncing a list
1. In Alice's window, create list "Groceries".
2. Add todo items and tags (as desired).
3. Click the status button, then type in Bob's email address.
-4. Send Bob the entire url, and have him open that url.
+4. Copy the `/share/...` part of the url. The hex suffix encodes the syncgroup
+ name, which includes Alice's mount table name.
+5. In Bob's window, replace everything after `<hostname>:5000` with the copied
+ `/share/...` path.
5. After a second, Bob should see the synced "Groceries" list.
6. Add, edit, and remove todos and tags to your heart's content and watch sync
do its magic.
+
+Note, it's important to use `<hostname>` urls rather than `localhost` urls
+because the web app parses the url from which it was loaded and adds 1 to the
+port number to determine the local mount table name, which it uses as a prefix
+for all syncgroup names that it creates. If the host is `localhost:5000`, the
+app will use `/localhost:5001` as the mount table name, and remote peers will
+not be able to contact the syncgroup. If we switch to a "predefined, global
+mount table" model, this will no longer be an issue.
diff --git a/tools/start_services.sh b/tools/start_services.sh
index 6d6ac70..b302f62 100755
--- a/tools/start_services.sh
+++ b/tools/start_services.sh
@@ -41,6 +41,8 @@
--v23.credentials=${TMP}/creds &
./bin/syncbased \
+ --v=5 \
+ --alsologtostderr=false \
--root-dir=${TMP}/syncbase_${PORT} \
--name=syncbase \
--v23.namespace.root=/${MOUNTTABLED_ADDR} \