forked from mystiq/hydrogen-web
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:
parent
25f3dfbb75
commit
14b27f81fe
3 changed files with 61 additions and 34 deletions
|
@ -24,7 +24,8 @@ export class Session {
|
||||||
constructor({storage, hsApi, sessionInfo}) {
|
constructor({storage, hsApi, sessionInfo}) {
|
||||||
this._storage = storage;
|
this._storage = storage;
|
||||||
this._hsApi = hsApi;
|
this._hsApi = hsApi;
|
||||||
this._session = null;
|
this._syncToken = null;
|
||||||
|
this._syncFilterId = null;
|
||||||
this._sessionInfo = sessionInfo;
|
this._sessionInfo = sessionInfo;
|
||||||
this._rooms = new ObservableMap();
|
this._rooms = new ObservableMap();
|
||||||
this._sendScheduler = new SendScheduler({hsApi, backoff: new RateLimitingBackoff()});
|
this._sendScheduler = new SendScheduler({hsApi, backoff: new RateLimitingBackoff()});
|
||||||
|
@ -42,11 +43,12 @@ export class Session {
|
||||||
this._storage.storeNames.pendingEvents,
|
this._storage.storeNames.pendingEvents,
|
||||||
]);
|
]);
|
||||||
// restore session object
|
// restore session object
|
||||||
this._session = await txn.session.get();
|
const [syncToken, syncFilterId] = await Promise.all([
|
||||||
if (!this._session) {
|
txn.session.get("syncToken"),
|
||||||
this._session = {};
|
txn.session.get("syncFilterId")
|
||||||
return;
|
]);
|
||||||
}
|
this._syncToken = syncToken;
|
||||||
|
this._syncFilterId = syncFilterId;
|
||||||
const pendingEventsByRoomId = await this._getPendingEventsByRoom(txn);
|
const pendingEventsByRoomId = await this._getPendingEventsByRoom(txn);
|
||||||
// load rooms
|
// load rooms
|
||||||
const rooms = await txn.roomSummary.getAll();
|
const rooms = await txn.roomSummary.getAll();
|
||||||
|
@ -70,11 +72,9 @@ export class Session {
|
||||||
const txn = await this._storage.readWriteTxn([
|
const txn = await this._storage.readWriteTxn([
|
||||||
this._storage.storeNames.session
|
this._storage.storeNames.session
|
||||||
]);
|
]);
|
||||||
const newSessionData = Object.assign({}, this._session, {serverVersions: lastVersionResponse});
|
txn.session.set("serverVersions", lastVersionResponse);
|
||||||
txn.session.set(newSessionData);
|
|
||||||
// TODO: what can we do if this throws?
|
// TODO: what can we do if this throws?
|
||||||
await txn.complete();
|
await txn.complete();
|
||||||
this._session = newSessionData;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this._sendScheduler.start();
|
this._sendScheduler.start();
|
||||||
|
@ -115,27 +115,28 @@ export class Session {
|
||||||
}
|
}
|
||||||
|
|
||||||
writeSync(syncToken, syncFilterId, accountData, txn) {
|
writeSync(syncToken, syncFilterId, accountData, txn) {
|
||||||
if (syncToken !== this._session.syncToken) {
|
if (syncToken !== this._syncToken) {
|
||||||
// don't modify this._session because transaction might still fail
|
// don't modify `this` because transaction might still fail
|
||||||
const newSessionData = Object.assign({}, this._session, {syncToken, syncFilterId});
|
txn.session.set("syncToken", syncToken);
|
||||||
txn.session.set(newSessionData);
|
txn.session.set("syncFilterId", syncFilterId);
|
||||||
return newSessionData;
|
return {syncToken, syncFilterId};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
afterSync(newSessionData) {
|
afterSync(changes) {
|
||||||
if (newSessionData) {
|
if (changes) {
|
||||||
// sync transaction succeeded, modify object state now
|
// sync transaction succeeded, modify object state now
|
||||||
this._session = newSessionData;
|
this._syncToken = changes.syncToken;
|
||||||
|
this._syncFilterId = changes.syncFilterId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
get syncToken() {
|
get syncToken() {
|
||||||
return this._session.syncToken;
|
return this._syncToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
get syncFilterId() {
|
get syncFilterId() {
|
||||||
return this._session.syncFilterId;
|
return this._syncFilterId;
|
||||||
}
|
}
|
||||||
|
|
||||||
get user() {
|
get user() {
|
||||||
|
@ -149,8 +150,8 @@ export function tests() {
|
||||||
readTxn() {
|
readTxn() {
|
||||||
return Promise.resolve({
|
return Promise.resolve({
|
||||||
session: {
|
session: {
|
||||||
get() {
|
get(key) {
|
||||||
return Promise.resolve(Object.assign({}, session));
|
return Promise.resolve(session[key]);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
pendingEvents: {
|
pendingEvents: {
|
||||||
|
@ -176,18 +177,24 @@ export function tests() {
|
||||||
syncFilterId: 5,
|
syncFilterId: 5,
|
||||||
}), sessionInfo: {userId: ""}});
|
}), sessionInfo: {userId: ""}});
|
||||||
await session.load();
|
await session.load();
|
||||||
let txnSetCalled = false;
|
let syncTokenSet = false;
|
||||||
|
let syncFilterIdSet = false;
|
||||||
const syncTxn = {
|
const syncTxn = {
|
||||||
session: {
|
session: {
|
||||||
set({syncToken, syncFilterId}) {
|
set(key, value) {
|
||||||
txnSetCalled = true;
|
if (key === "syncToken") {
|
||||||
assert.equal(syncToken, "b");
|
assert.equal(value, "b");
|
||||||
assert.equal(syncFilterId, 6);
|
syncTokenSet = true;
|
||||||
|
} else if (key === "syncFilterId") {
|
||||||
|
assert.equal(value, 6);
|
||||||
|
syncFilterIdSet = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const newSessionData = session.writeSync("b", 6, {}, syncTxn);
|
const newSessionData = session.writeSync("b", 6, {}, syncTxn);
|
||||||
assert(txnSetCalled);
|
assert(syncTokenSet);
|
||||||
|
assert(syncFilterIdSet);
|
||||||
assert.equal(session.syncToken, "a");
|
assert.equal(session.syncToken, "a");
|
||||||
assert.equal(session.syncFilterId, 5);
|
assert.equal(session.syncFilterId, 5);
|
||||||
session.afterSync(newSessionData);
|
session.afterSync(newSessionData);
|
||||||
|
|
|
@ -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 {RoomMember, EVENT_TYPE as MEMBER_EVENT_TYPE} from "../../room/members/RoomMember.js";
|
||||||
import {RoomMemberStore} from "./stores/RoomMemberStore.js";
|
import {RoomMemberStore} from "./stores/RoomMemberStore.js";
|
||||||
|
import {SessionStore} from "./stores/SessionStore.js";
|
||||||
|
|
||||||
// FUNCTIONS SHOULD ONLY BE APPENDED!!
|
// FUNCTIONS SHOULD ONLY BE APPENDED!!
|
||||||
// the index in the array is the database version
|
// the index in the array is the database version
|
||||||
export const schema = [
|
export const schema = [
|
||||||
createInitialStores,
|
createInitialStores,
|
||||||
createMemberStore,
|
createMemberStore,
|
||||||
|
migrateSession,
|
||||||
];
|
];
|
||||||
// TODO: how to deal with git merge conflicts of this array?
|
// 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -35,14 +35,14 @@ export class SessionStore {
|
||||||
this._sessionStore = sessionStore;
|
this._sessionStore = sessionStore;
|
||||||
}
|
}
|
||||||
|
|
||||||
async get() {
|
async get(key) {
|
||||||
const session = await this._sessionStore.selectFirst(IDBKeyRange.only(1));
|
const entry = await this._sessionStore.get(key);
|
||||||
if (session) {
|
if (entry) {
|
||||||
return session.value;
|
return entry.value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
set(session) {
|
set(key, value) {
|
||||||
return this._sessionStore.put({key: 1, value: session});
|
return this._sessionStore.put({key, value});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue