Skip to content

Commit

Permalink
Simulate two-phase commit for wake up state change
Browse files Browse the repository at this point in the history
Instead of implementing a real two-phase commit, and because we don't use
Ajax requests, change the browser's state only after the server durably
saved the state change. This way, we prevent data-loss if the person wakes
up, taps "Wake Up" and the server crashes / rejects the submit.
  • Loading branch information
francois committed Aug 5, 2016
1 parent 797f312 commit f9cd9a3
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 5 deletions.
3 changes: 2 additions & 1 deletion app.rb
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ def table_name_from_user_id(user_id)

@user_id = user_id
@app = :app
@wakeup = params[:wakeup] == "1"
erb :app, layout: :layout
end

Expand All @@ -126,7 +127,7 @@ def table_name_from_user_id(user_id)
halt 400, "Bad Request: unrecognized sleep_type" if sleep_type.nil?

DB[table_name_from_user_id(user_id)].insert(timezone: tz.name, start_at: start_at, end_at: end_at, sleep_type: sleep_type)
redirect "/me/#{user_id}"
redirect "/me/#{user_id}?wakeup=1"
end

get %r{\A/me/#{UUID_RE}/analytics} do |user_id|
Expand Down
16 changes: 12 additions & 4 deletions public/js/bundle.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ NoFrillsSleepTracker.renderAppAwake = function(rootNode, store, userId, sleepTab
store.setItem("start-nap-at-epoch", new Date().getTime());
store.setItem("state", "napping");

// remove any pending "wakeup=1" param from the URL
history.pushState(null, "", document.location.pathname);

// rerender the app's UI
setTimeout(NoFrillsSleepTracker.renderApp.bind(window, rootNode, store, userId), 0);
}));
Expand All @@ -70,6 +73,9 @@ NoFrillsSleepTracker.renderAppAwake = function(rootNode, store, userId, sleepTab
store.setItem("start-sleep-at-epoch", new Date().getTime());
store.setItem("state", "sleeping");

// remove any pending "wakeup=1" param from the URL
history.pushState(null, "", document.location.pathname);

// rerender the app's UI
setTimeout(NoFrillsSleepTracker.renderApp.bind(window, rootNode, store, userId), 0);
}));
Expand Down Expand Up @@ -108,8 +114,6 @@ NoFrillsSleepTracker.renderAppSleeping = function(rootNode, store, userId, sleep
form.addEventListener("submit", function(ev) {
clearInterval(timerId);
form.appendChild(NoFrillsSleepTracker.createHiddenInput("end_at", new Date().getTime()));
store.setItem("state", "awake");
store.removeItem("start-sleep-at-epoch");
});
form.appendChild(state);
form.appendChild(NoFrillsSleepTracker.createSubmitButton("Wake up!"));
Expand Down Expand Up @@ -143,15 +147,19 @@ NoFrillsSleepTracker.renderAppNapping = function(rootNode, store, userId) {
form.addEventListener("submit", function(ev) {
clearInterval(timerId);
form.appendChild(NoFrillsSleepTracker.createHiddenInput("end_at", new Date().getTime()));
store.setItem("state", "awake");
store.removeItem("start-nap-at-epoch");
});
form.appendChild(state);
form.appendChild(NoFrillsSleepTracker.createSubmitButton("Wake from nap"));

rootNode.appendChild(form);
}

NoFrillsSleepTracker.wakeUp = function(store) {
store.setItem("state", "awake");
store.removeItem("start-nap-at-epoch");
store.removeItem("start-sleep-at-epoch");
}

NoFrillsSleepTracker.renderApp = function(rootNode, store, userId, sleepTable) {
var timezone = store.getItem("timezone") || "America/New_York";
var state = store.getItem("state") || "awake";
Expand Down
8 changes: 8 additions & 0 deletions views/app.erb
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,14 @@
if (params[0] === "timezone") NoFrillsSleepTracker.setTimezone(window.localStorage, param[1]);
}

if (<%= @wakeup %>) {
// Reset state when the server tells us to do so
// Since we don't do 2 phase commit, or use an Ajax request to change the server's state,
// we have to wait until the server acknowledges the state change before resetting our
// localStorage state.
NoFrillsSleepTracker.wakeUp(window.localStorage);
}

NoFrillsSleepTracker.renderApp(document.getElementById("app"), window.localStorage, userId, <%= @last5.to_json %>);
} else {
NoFrillsSleepTracker.renderLocalStorageDisabled(document.getElementById("app"));
Expand Down

0 comments on commit f9cd9a3

Please sign in to comment.