Skip to content

Commit

Permalink
Skeleton implementation of closed-loop unsaved detection (#56).
Browse files Browse the repository at this point in the history
Periodically creates new Firepad.Headless, loads the text and compares
to current editor content.
Also checks Firebase's online status for better messages.

After a couple days of torturing, this seems to reliably detect
#85 borked firepad state and warn "Online but unsaved — BUG?".
Problems:
- False positives during typing (saw this) or incoming changes (theoretical).
  Needs debouncing after a period of quiet...
- Currently for easy testing runs the check *every second*!
  Should increase testSyncIntervalMs to 30-60sec before landing.
  - If only to avoid constant 1-5% CPU usage.
- Performance concerns: after a day of holding and torture-editing
  2 chrome tabs, things crawled to unusably slow stuck-after-every-press.
  Their combined memory usage grew to ~1.5GB! (plus ~1GB for their dev tools)
  And at some point CPU usage grew to 100%.
  - Near the end, I timed Headless getText to take >3 seconds!
    Initially it's ~1ms for existing Headless and ~230ms for new Headless!
    This explains 100% CPU - 1sec timer should be after prev timer finished
    execution, but alas getText() returns immediately.
  - AFAICT, snapshots were being taken so it's not op composition overhead.
  - It seems memory leak does not happen in current mathdown.net version
    (0f69d29).
  • Loading branch information
cben committed Jun 4, 2015
1 parent 416afd6 commit 0e8a2d4
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 8 deletions.
6 changes: 6 additions & 0 deletions mathdown.css
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@
-webkit-transition: all 2s cubic-bezier(0,.3,.85,0);
transition: all 2s cubic-bezier(0,.3,.85,0); /* slow appear */
}
#status.warning {
color: black; background-color: orange;
opacity: 0.8; visibility: visible;
-webkit-transition: all 2s cubic-bezier(0,.3,.85,0);
transition: all 2s cubic-bezier(0,.3,.85,0); /* slow appear */
}

@media print { #header { display: none; } }

Expand Down
69 changes: 61 additions & 8 deletions mathdown.js
Original file line number Diff line number Diff line change
Expand Up @@ -222,16 +222,67 @@ function setupFirepad(editor, firepad) {
editor.renderAllMath();
});
});
}

function timestampMs() {
return new Date().getTime();
}

// firepadRef.child("
function setupUnsavedWarning(connectedRef, editor, firepad, firepadRef) {
var loaded = false, connected = false, believedSynced = true, testedSynced = true;
var testSyncIntervalMs = 1*1000;

firepad.on("ready", function() {
loaded = true;
updateStatus();
});
connectedRef.on("value", function(snapshot) {
connected = snapshot.val();
updateStatus();
});
firepad.on("synced", function(isSynced) {
log("synced", isSynced);
if(!isSynced) {
setStatus("info", "Unsaved!");
} else {
setStatus("", "saved");
believedSynced = isSynced;
updateStatus();
});
setInterval(function () {
if(connected) { // no point computing
var headless = new Firepad.Headless(firepadRef);
headless.getText(function(fetchedText) {
var editorText = editor.getValue();
// This is not reliable during typing (by the time we
// reconstruct from firebase editor text might have changed),
// as well as during *incoming* changes from other editor.
testedSynced = (fetchedText === editorText);
updateStatus();
});
}
}, testSyncIntervalMs);

function updateStatus() {
log("loaded = ", loaded, "connected =", connected,
"believedSynced = ", believedSynced, "testedSynced =", testedSynced);
if(!loaded) {
return; // don't disturb "loading..." message (there can be no unsaved state yet). TODO: OFFLINE TYPING?
}
if(connected) {
if(believedSynced) {
if(testedSynced) {
setStatus("", "saved");
} else {
setStatus("warning", "Online but unsaved — BUG?");
}
} else {
setStatus("info", "Unsaved!");
}
} else { // not connected.
if(believedSynced) {
setStatus("info", "Offline");
} else {
setStatus("warning", "Offline — Unsaved changes!");
}
}
})
}
}

// URL parameters => load document
Expand Down Expand Up @@ -261,13 +312,15 @@ if(doc === undefined) {
window.location.search = "?doc=about";
} else {
var rootRef = new Firebase("https://mathdown.firebaseIO.com/");
var firepadsRef = rootRef.child("firepads");
var firepadRef = firepadsRef.child(doc);
var firepadRef = rootRef.child("firepads").child(doc);
log("firebase ref:", firepadRef.toString());

var editor = createEditor(docDirection);
setupEditor(editor);

var firepad = Firepad.fromCodeMirror(firepadRef, editor);
setupFirepad(editor, firepad);

var connectedRef = rootRef.child(".info/connected");
setupUnsavedWarning(connectedRef, editor, firepad, firepadRef);
}

0 comments on commit 0e8a2d4

Please sign in to comment.