Merge pull request #71 from vector-im/bwindels/splitup-session-values
Store session values as separate entries in store
This commit is contained in:
commit
a53c061f27
4 changed files with 52 additions and 37 deletions
|
@ -24,7 +24,7 @@ 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._syncInfo = 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 +42,7 @@ export class Session {
|
||||||
this._storage.storeNames.pendingEvents,
|
this._storage.storeNames.pendingEvents,
|
||||||
]);
|
]);
|
||||||
// restore session object
|
// restore session object
|
||||||
this._session = await txn.session.get();
|
this._syncInfo = await txn.session.get("sync");
|
||||||
if (!this._session) {
|
|
||||||
this._session = {};
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
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 +66,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 +109,27 @@ 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
|
const syncInfo = {token: syncToken, filterId: syncFilterId};
|
||||||
const newSessionData = Object.assign({}, this._session, {syncToken, syncFilterId});
|
// don't modify `this` because transaction might still fail
|
||||||
txn.session.set(newSessionData);
|
txn.session.set("sync", syncInfo);
|
||||||
return newSessionData;
|
return syncInfo;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
afterSync(newSessionData) {
|
afterSync(syncInfo) {
|
||||||
if (newSessionData) {
|
if (syncInfo) {
|
||||||
// sync transaction succeeded, modify object state now
|
// sync transaction succeeded, modify object state now
|
||||||
this._session = newSessionData;
|
this._syncInfo = syncInfo;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
get syncToken() {
|
get syncToken() {
|
||||||
return this._session.syncToken;
|
return this._syncInfo?.token;
|
||||||
}
|
}
|
||||||
|
|
||||||
get syncFilterId() {
|
get syncFilterId() {
|
||||||
return this._session.syncFilterId;
|
return this._syncInfo?.filterId;
|
||||||
}
|
}
|
||||||
|
|
||||||
get user() {
|
get user() {
|
||||||
|
@ -149,8 +143,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: {
|
||||||
|
@ -172,22 +166,23 @@ export function tests() {
|
||||||
return {
|
return {
|
||||||
"session data is not modified until after sync": async (assert) => {
|
"session data is not modified until after sync": async (assert) => {
|
||||||
const session = new Session({storage: createStorageMock({
|
const session = new Session({storage: createStorageMock({
|
||||||
syncToken: "a",
|
sync: {token: "a", filterId: 5}
|
||||||
syncFilterId: 5,
|
|
||||||
}), sessionInfo: {userId: ""}});
|
}), sessionInfo: {userId: ""}});
|
||||||
await session.load();
|
await session.load();
|
||||||
let txnSetCalled = false;
|
let syncSet = false;
|
||||||
const syncTxn = {
|
const syncTxn = {
|
||||||
session: {
|
session: {
|
||||||
set({syncToken, syncFilterId}) {
|
set(key, value) {
|
||||||
txnSetCalled = true;
|
if (key === "sync") {
|
||||||
assert.equal(syncToken, "b");
|
assert.equal(value.token, "b");
|
||||||
assert.equal(syncFilterId, 6);
|
assert.equal(value.filterId, 6);
|
||||||
|
syncSet = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const newSessionData = session.writeSync("b", 6, {}, syncTxn);
|
const newSessionData = session.writeSync("b", 6, {}, syncTxn);
|
||||||
assert(txnSetCalled);
|
assert(syncSet);
|
||||||
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);
|
||||||
|
|
|
@ -263,7 +263,7 @@ export function tests() {
|
||||||
"membership trigger change": function(assert) {
|
"membership trigger change": function(assert) {
|
||||||
const summary = new RoomSummary("id");
|
const summary = new RoomSummary("id");
|
||||||
let written = false;
|
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(changes);
|
||||||
assert(written);
|
assert(written);
|
||||||
assert.equal(changes.membership, "join");
|
assert.equal(changes.membership, "join");
|
||||||
|
|
|
@ -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 {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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Reference in a new issue