only apply sync changes in session once txn is committed

This commit is contained in:
Bruno Windels 2020-03-14 20:45:36 +01:00
parent 177b03915d
commit fc741272ba
2 changed files with 63 additions and 5 deletions

View file

@ -77,11 +77,19 @@ export default class Session {
return room; return room;
} }
persistSync(syncToken, syncFilterId, accountData, txn) { writeSync(syncToken, syncFilterId, accountData, txn) {
if (syncToken !== this._session.syncToken) { if (syncToken !== this._session.syncToken) {
this._session.syncToken = syncToken; // don't modify this._session because transaction might still fail
this._session.syncFilterId = syncFilterId; const newSessionData = Object.assign({}, this._session, {syncToken, syncFilterId});
txn.session.set(this._session); txn.session.set(newSessionData);
return newSessionData;
}
}
afterSync(newSessionData) {
if (newSessionData) {
// sync transaction succeeded, modify object state now
this._session = newSessionData;
} }
} }
@ -97,3 +105,51 @@ export default class Session {
return this._user; return this._user;
} }
} }
export function tests() {
function createStorageMock(session, pendingEvents) {
return {
readTxn() {
return Promise.resolve({
session: {
get() {
return Promise.resolve(Object.assign({}, session));
}
},
pendingEvents: {
getAll() {
return Promise.resolve(pendingEvents);
}
}
});
}
};
}
return {
"session data is not modified until after sync": async (assert) => {
const session = new Session({storage: createStorageMock({
syncToken: "a",
syncFilterId: 5,
})});
await session.load();
let txnSetCalled = false;
const syncTxn = {
session: {
set({syncToken, syncFilterId}) {
txnSetCalled = true;
assert.equals(syncToken, "b");
assert.equals(syncFilterId, 6);
}
}
};
const newSessionData = session.writeSync("b", 6, {}, syncTxn);
assert(txnSetCalled);
assert.equals(session.syncToken, "a");
assert.equals(session.syncFilterId, 5);
session.afterSync(newSessionData);
assert.equals(session.syncToken, "b");
assert.equals(session.syncFilterId, 6);
}
}
}

View file

@ -85,8 +85,9 @@ export default class Sync extends EventEmitter {
storeNames.pendingEvents, storeNames.pendingEvents,
]); ]);
const roomChanges = []; const roomChanges = [];
let sessionChanges;
try { try {
this._session.persistSync(syncToken, syncFilterId, response.account_data, syncTxn); sessionChanges = this._session.writeSync(syncToken, syncFilterId, response.account_data, syncTxn);
// to_device // to_device
// presence // presence
if (response.rooms) { if (response.rooms) {
@ -116,6 +117,7 @@ export default class Sync extends EventEmitter {
console.error("unable to commit sync tranaction"); console.error("unable to commit sync tranaction");
throw err; throw err;
} }
this._session.afterSync(sessionChanges);
// emit room related events after txn has been closed // emit room related events after txn has been closed
for(let {room, changes} of roomChanges) { for(let {room, changes} of roomChanges) {
room.emitSync(changes); room.emitSync(changes);