store session values as individual values in store

so we don't have to write the whole object every time something changes
we'll use this to store the olm account
This commit is contained in:
Bruno Windels 2020-08-27 14:28:40 +02:00
parent 25f3dfbb75
commit 14b27f81fe
3 changed files with 61 additions and 34 deletions

View file

@ -24,7 +24,8 @@ export class Session {
constructor({storage, hsApi, sessionInfo}) {
this._storage = storage;
this._hsApi = hsApi;
this._session = null;
this._syncToken = null;
this._syncFilterId = null;
this._sessionInfo = sessionInfo;
this._rooms = new ObservableMap();
this._sendScheduler = new SendScheduler({hsApi, backoff: new RateLimitingBackoff()});
@ -42,11 +43,12 @@ export class Session {
this._storage.storeNames.pendingEvents,
]);
// restore session object
this._session = await txn.session.get();
if (!this._session) {
this._session = {};
return;
}
const [syncToken, syncFilterId] = await Promise.all([
txn.session.get("syncToken"),
txn.session.get("syncFilterId")
]);
this._syncToken = syncToken;
this._syncFilterId = syncFilterId;
const pendingEventsByRoomId = await this._getPendingEventsByRoom(txn);
// load rooms
const rooms = await txn.roomSummary.getAll();
@ -70,11 +72,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 +115,28 @@ 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) {
// don't modify `this` because transaction might still fail
txn.session.set("syncToken", syncToken);
txn.session.set("syncFilterId", syncFilterId);
return {syncToken, syncFilterId};
}
}
afterSync(newSessionData) {
if (newSessionData) {
afterSync(changes) {
if (changes) {
// sync transaction succeeded, modify object state now
this._session = newSessionData;
this._syncToken = changes.syncToken;
this._syncFilterId = changes.syncFilterId;
}
}
get syncToken() {
return this._session.syncToken;
return this._syncToken;
}
get syncFilterId() {
return this._session.syncFilterId;
return this._syncFilterId;
}
get user() {
@ -149,8 +150,8 @@ export function tests() {
readTxn() {
return Promise.resolve({
session: {
get() {
return Promise.resolve(Object.assign({}, session));
get(key) {
return Promise.resolve(session[key]);
}
},
pendingEvents: {
@ -176,18 +177,24 @@ export function tests() {
syncFilterId: 5,
}), sessionInfo: {userId: ""}});
await session.load();
let txnSetCalled = false;
let syncTokenSet = false;
let syncFilterIdSet = false;
const syncTxn = {
session: {
set({syncToken, syncFilterId}) {
txnSetCalled = true;
assert.equal(syncToken, "b");
assert.equal(syncFilterId, 6);
set(key, value) {
if (key === "syncToken") {
assert.equal(value, "b");
syncTokenSet = true;
} else if (key === "syncFilterId") {
assert.equal(value, 6);
syncFilterIdSet = true;
}
}
}
};
const newSessionData = session.writeSync("b", 6, {}, syncTxn);
assert(txnSetCalled);
assert(syncTokenSet);
assert(syncFilterIdSet);
assert.equal(session.syncToken, "a");
assert.equal(session.syncFilterId, 5);
session.afterSync(newSessionData);

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 store = new SessionStore(session);
for (const [key, value] of Object.entries(entry.value)) {
store.set(key, value);
}
}
} 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});
}
}