Merge pull request #71 from vector-im/bwindels/splitup-session-values

Store session values as separate entries in store
This commit is contained in:
Bruno Windels 2020-08-27 12:40:19 +00:00 committed by GitHub
commit a53c061f27
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 52 additions and 37 deletions

View File

@ -24,7 +24,7 @@ export class Session {
constructor({storage, hsApi, sessionInfo}) {
this._storage = storage;
this._hsApi = hsApi;
this._session = null;
this._syncInfo = null;
this._sessionInfo = sessionInfo;
this._rooms = new ObservableMap();
this._sendScheduler = new SendScheduler({hsApi, backoff: new RateLimitingBackoff()});
@ -42,11 +42,7 @@ export class Session {
this._storage.storeNames.pendingEvents,
]);
// restore session object
this._session = await txn.session.get();
if (!this._session) {
this._session = {};
return;
}
this._syncInfo = await txn.session.get("sync");
const pendingEventsByRoomId = await this._getPendingEventsByRoom(txn);
// load rooms
const rooms = await txn.roomSummary.getAll();
@ -70,11 +66,9 @@ export class Session {
const txn = await this._storage.readWriteTxn([
this._storage.storeNames.session
]);
const newSessionData = Object.assign({}, this._session, {serverVersions: lastVersionResponse});
txn.session.set(newSessionData);
txn.session.set("serverVersions", lastVersionResponse);
// TODO: what can we do if this throws?
await txn.complete();
this._session = newSessionData;
}
this._sendScheduler.start();
@ -115,27 +109,27 @@ export class Session {
}
writeSync(syncToken, syncFilterId, accountData, txn) {
if (syncToken !== this._session.syncToken) {
// don't modify this._session because transaction might still fail
const newSessionData = Object.assign({}, this._session, {syncToken, syncFilterId});
txn.session.set(newSessionData);
return newSessionData;
if (syncToken !== this.syncToken) {
const syncInfo = {token: syncToken, filterId: syncFilterId};
// don't modify `this` because transaction might still fail
txn.session.set("sync", syncInfo);
return syncInfo;
}
}
afterSync(newSessionData) {
if (newSessionData) {
afterSync(syncInfo) {
if (syncInfo) {
// sync transaction succeeded, modify object state now
this._session = newSessionData;
this._syncInfo = syncInfo;
}
}
get syncToken() {
return this._session.syncToken;
return this._syncInfo?.token;
}
get syncFilterId() {
return this._session.syncFilterId;
return this._syncInfo?.filterId;
}
get user() {
@ -149,8 +143,8 @@ export function tests() {
readTxn() {
return Promise.resolve({
session: {
get() {
return Promise.resolve(Object.assign({}, session));
get(key) {
return Promise.resolve(session[key]);
}
},
pendingEvents: {
@ -172,22 +166,23 @@ export function tests() {
return {
"session data is not modified until after sync": async (assert) => {
const session = new Session({storage: createStorageMock({
syncToken: "a",
syncFilterId: 5,
sync: {token: "a", filterId: 5}
}), sessionInfo: {userId: ""}});
await session.load();
let txnSetCalled = false;
let syncSet = false;
const syncTxn = {
session: {
set({syncToken, syncFilterId}) {
txnSetCalled = true;
assert.equal(syncToken, "b");
assert.equal(syncFilterId, 6);
set(key, value) {
if (key === "sync") {
assert.equal(value.token, "b");
assert.equal(value.filterId, 6);
syncSet = true;
}
}
}
};
const newSessionData = session.writeSync("b", 6, {}, syncTxn);
assert(txnSetCalled);
assert(syncSet);
assert.equal(session.syncToken, "a");
assert.equal(session.syncFilterId, 5);
session.afterSync(newSessionData);

View File

@ -263,7 +263,7 @@ export function tests() {
"membership trigger change": function(assert) {
const summary = new RoomSummary("id");
let written = false;
const changes = summary.writeSync({}, "join", {roomSummary: {set: () => { written = true; }}});
const changes = summary.writeSync({}, "join", false, false, {roomSummary: {set: () => { written = true; }}});
assert(changes);
assert(written);
assert.equal(changes.membership, "join");

View File

@ -1,12 +1,14 @@
import {iterateCursor} from "./utils.js";
import {iterateCursor, reqAsPromise} from "./utils.js";
import {RoomMember, EVENT_TYPE as MEMBER_EVENT_TYPE} from "../../room/members/RoomMember.js";
import {RoomMemberStore} from "./stores/RoomMemberStore.js";
import {SessionStore} from "./stores/SessionStore.js";
// FUNCTIONS SHOULD ONLY BE APPENDED!!
// the index in the array is the database version
export const schema = [
createInitialStores,
createMemberStore,
migrateSession,
];
// TODO: how to deal with git merge conflicts of this array?
@ -44,3 +46,21 @@ async function createMemberStore(db, txn) {
}
});
}
async function migrateSession(db, txn) {
const session = txn.objectStore("session");
try {
const PRE_MIGRATION_KEY = 1;
const entry = await reqAsPromise(session.get(PRE_MIGRATION_KEY));
if (entry) {
session.delete(PRE_MIGRATION_KEY);
const {syncToken, syncFilterId, serverVersions} = entry.value;
const store = new SessionStore(session);
store.set("sync", {token: syncToken, filterId: syncFilterId});
store.set("serverVersions", serverVersions);
}
} catch (err) {
txn.abort();
console.error("could not migrate session", err.stack);
}
}

View File

@ -35,14 +35,14 @@ export class SessionStore {
this._sessionStore = sessionStore;
}
async get() {
const session = await this._sessionStore.selectFirst(IDBKeyRange.only(1));
if (session) {
return session.value;
async get(key) {
const entry = await this._sessionStore.get(key);
if (entry) {
return entry.value;
}
}
set(session) {
return this._sessionStore.put({key: 1, value: session});
set(key, value) {
return this._sessionStore.put({key, value});
}
}