From 3f776129f5a2366a3c681c183359727602330c1c Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Thu, 7 Feb 2019 00:20:27 +0000 Subject: [PATCH] basic session loading --- src/main.js | 10 ++++-- src/session.js | 37 +++++++++++++++----- src/storage/idb/create.js | 2 +- src/storage/idb/query-target.js | 27 +++++++------- src/storage/idb/storage.js | 6 ++-- src/storage/idb/store-index.js | 11 ------ src/storage/idb/store.js | 18 +++++++--- src/storage/idb/stores/session.js | 56 +++++------------------------- src/storage/idb/stores/timeline.js | 3 +- src/storage/idb/transaction.js | 25 ++++++++----- 10 files changed, 94 insertions(+), 101 deletions(-) delete mode 100644 src/storage/idb/store-index.js diff --git a/src/main.js b/src/main.js index b7398b2b..d118a263 100644 --- a/src/main.js +++ b/src/main.js @@ -30,12 +30,18 @@ async function main() { let sessionId = getSessionId("@bruno1:localhost"); let loginData; if (!sessionId) { - ({sessionId, loginData} = await login("bruno1", "testtest", "http://localhost:8008")); + ({sessionId, loginData} = await login("bruno1", "testtest", HOMESERVER)); } const storage = await createIdbStorage(`morpheus_session_${sessionId}`); console.log("database created", storage); - const session = new Session(loginData, storage); + const session = new Session(storage); + if (loginData) { + await session.setLoginData(loginData); + } await session.load(); + console.log("session loaded", session); + return; + const network = new Network(HOMESERVER, session.accessToken); const sync = new Sync(network, session, storage); await sync.start(); diff --git a/src/session.js b/src/session.js index ccd0b998..9bae825b 100644 --- a/src/session.js +++ b/src/session.js @@ -1,14 +1,25 @@ export default class Session { - // sessionData has device_id, user_id, home_server (not access_token, that is for network) - constructor(sessionData, storage) { - this._sessionData = sessionData; + // loginData has device_id, user_id, home_server, access_token + constructor(storage) { this._storage = storage; - this._rooms = {}; - this._syncToken = null; + this._session = null; + this._rooms = null; + } + // should be called before load + async setLoginData(loginData) { + const txn = this._storage.readWriteTxn([this._storage.storeNames.session]); + const session = {loginData}; + txn.session.set(session); + await txn.complete(); } - load() { - // what is the PK for a session [user_id, device_id], a uuid? + async load() { + const txn = this._storage.readTxn([this._storage.storeNames.session]); + this._session = await txn.session.get(); + if (!this._session) { + throw new Error("session store is empty"); + } + // load rooms } getRoom(roomId) { @@ -22,7 +33,15 @@ export default class Session { } applySync(syncToken, accountData, txn) { - this._syncToken = syncToken; - txn.session.setSyncToken(syncToken); + this._session.syncToken = syncToken; + txn.session.setSession(this._session); + } + + get syncToken() { + return this._session.syncToken; + } + + get accessToken() { + return this._session.loginData.access_token; } } \ No newline at end of file diff --git a/src/storage/idb/create.js b/src/storage/idb/create.js index 7074c437..a87636da 100644 --- a/src/storage/idb/create.js +++ b/src/storage/idb/create.js @@ -7,7 +7,7 @@ export default async function createIdbStorage(databaseName) { } function createStores(db) { - db.createObjectStore("sync"); //sync token + db.createObjectStore("session", {keyPath: "key"}); // any way to make keys unique here? db.createObjectStore("roomSummary", {keyPath: "room_id"}); const timeline = db.createObjectStore("roomTimeline", {keyPath: ["room_id", "sort_key"]}); diff --git a/src/storage/idb/query-target.js b/src/storage/idb/query-target.js index b0fbf538..0d792c61 100644 --- a/src/storage/idb/query-target.js +++ b/src/storage/idb/query-target.js @@ -1,6 +1,10 @@ -import {iterateCursor} from "./utils"; +import {iterateCursor} from "./utils.js"; export default class QueryTarget { + constructor(target) { + this._target = target; + } + reduce(range, reducer, initialValue) { return this._reduce(range, reducer, initialValue, "next"); } @@ -26,7 +30,7 @@ export default class QueryTarget { } selectAll(range) { - const cursor = this._queryTarget().openCursor(range, direction); + const cursor = this._target.openCursor(range, direction); const results = []; return iterateCursor(cursor, (value) => { results.push(value); @@ -52,7 +56,7 @@ export default class QueryTarget { _reduce(range, reducer, initialValue, direction) { let reducedValue = initialValue; - const cursor = this._queryTarget().openCursor(range, direction); + const cursor = this._target.openCursor(range, direction); return iterateCursor(cursor, (value) => { reducedValue = reducer(reducedValue, value); return true; @@ -66,7 +70,7 @@ export default class QueryTarget { } _selectWhile(range, predicate, direction) { - const cursor = this._queryTarget().openCursor(range, direction); + const cursor = this._target.openCursor(range, direction); const results = []; return iterateCursor(cursor, (value) => { results.push(value); @@ -75,20 +79,17 @@ export default class QueryTarget { } async _find(range, predicate, direction) { - const cursor = this._queryTarget().openCursor(range, direction); + const cursor = this._target.openCursor(range, direction); let result; const found = await iterateCursor(cursor, (value) => { - if (predicate(value)) { + const found = predicate(value); + if (found) { result = value; } + return found; }); - if (!found) { - throw new Error("not found"); + if (found) { + return result; } - return result; - } - - _queryTarget() { - throw new Error("override this"); } } \ No newline at end of file diff --git a/src/storage/idb/storage.js b/src/storage/idb/storage.js index ada97bac..fe13a5ab 100644 --- a/src/storage/idb/storage.js +++ b/src/storage/idb/storage.js @@ -1,3 +1,5 @@ +import Transaction from "./transaction.js"; + export const STORE_NAMES = ["session", "roomState", "roomSummary", "roomTimeline"]; export default class Storage { @@ -17,13 +19,13 @@ export default class Storage { } } - startReadOnlyTxn(storeNames) { + readTxn(storeNames) { this._validateStoreNames(storeNames); const txn = this._db.transaction(storeNames, "readonly"); return new Transaction(txn, storeNames); } - startReadWriteTxn(storeNames) { + readWriteTxn(storeNames) { this._validateStoreNames(storeNames); const txn = this._db.transaction(storeNames, "readwrite"); return new Transaction(txn, storeNames); diff --git a/src/storage/idb/store-index.js b/src/storage/idb/store-index.js deleted file mode 100644 index 0062364f..00000000 --- a/src/storage/idb/store-index.js +++ /dev/null @@ -1,11 +0,0 @@ -import QueryTarget from "./query-target.js"; - -export default class StoreIndex extends QueryTarget { - constructor(index) { - this._index = index; - } - - _queryTarget() { - return this._index; - } -} \ No newline at end of file diff --git a/src/storage/idb/store.js b/src/storage/idb/store.js index d3ecb1b2..0d2e2385 100644 --- a/src/storage/idb/store.js +++ b/src/storage/idb/store.js @@ -1,16 +1,24 @@ import QueryTarget from "./query-target.js"; -import StoreIndex from "./store-index.js"; +import { reqAsPromise } from "./utils.js"; export default class Store extends QueryTarget { constructor(store) { - this._store = store; + super(store); } - _queryTarget() { - return this._store; + get _store() { + return this._target; } index(indexName) { - return new StoreIndex(this._store.index(indexName)); + return new QueryTarget(this._store.index(indexName)); + } + + put(value) { + return reqAsPromise(this._store.put(value)); + } + + add(value) { + return reqAsPromise(this._store.add(value)); } } \ No newline at end of file diff --git a/src/storage/idb/stores/session.js b/src/storage/idb/stores/session.js index 1ebd6020..405f9794 100644 --- a/src/storage/idb/stores/session.js +++ b/src/storage/idb/stores/session.js @@ -14,59 +14,19 @@ store contains: avatarUrl lastSynced */ -class SessionStore { - +export default class SessionStore { constructor(sessionStore) { this._sessionStore = sessionStore; } - readSession() { - return this._session; + async get() { + const session = await this._sessionStore.selectFirst(IDBKeyRange.only(1)); + if (session) { + return session.value; + } } - writeSession(session) { - - } - - // or dedicated set sync_token method? - async setAvatar(avatar) { - - } - - async setDisplayName(displayName) { - - } - - - getSyncStatus() { - return this._db.store("sync").selectFirst(); - } - - setSyncStatus(syncToken, lastSynced) { - return this._db.store("sync").updateFirst({sync_token: syncToken, last_synced: lastSynced}); - // return updateSingletonStore(this._db, "sync", {sync_token: syncToken, last_synced: lastSynced}); - } - - setAccessToken(accessToken) { - } - - async addRoom(room) { - - } - - async removeRoom(roomId) { - - } - - async getRoomStores() { - - } - - async getRoomStore(roomId) { - - } - - async startSyncTransaction() { - return this._db.startSyncTxn(); + set(session) { + return this._sessionStore.put({key: 1, value: session}); } } diff --git a/src/storage/idb/stores/timeline.js b/src/storage/idb/stores/timeline.js index f50e7378..7a1eeadd 100644 --- a/src/storage/idb/stores/timeline.js +++ b/src/storage/idb/stores/timeline.js @@ -1,5 +1,4 @@ -import GapSortKey from "./gapsortkey"; -import {select} from "./utils"; +import SortKey from "../../sortkey.js"; class TimelineStore { constructor(timelineStore) { diff --git a/src/storage/idb/transaction.js b/src/storage/idb/transaction.js index bcfe596b..872fcc9c 100644 --- a/src/storage/idb/transaction.js +++ b/src/storage/idb/transaction.js @@ -1,6 +1,7 @@ -import {txnAsPromise} from "./utils"; +import {txnAsPromise} from "./utils.js"; import Store from "./store.js"; -import TimelineStore from "./stores/timeline.js"; +// import TimelineStore from "./stores/timeline.js"; +import SessionStore from "./stores/session.js"; export default class Transaction { constructor(txn, allowedStoreNames) { @@ -19,15 +20,23 @@ export default class Transaction { // more specific error? this is a bug, so maybe not ... throw new Error(`Invalid store for transaction: ${name}, only ${this._allowedStoreNames.join(", ")} are allowed.`); } - return new Store(this._txn.getObjectStore(name)); + return new Store(this._txn.objectStore(name)); } - get roomTimeline() { - if (!this._stores.roomTimeline) { - const idbStore = this._idbStore("roomTimeline"); - this._stores.roomTimeline = new TimelineStore(idbStore); + _store(name, mapStore) { + if (!this._stores[name]) { + const idbStore = this._idbStore(name); + this._stores[name] = mapStore(idbStore); } - return this._stores.roomTimeline; + return this._stores[name]; + } + + // get roomTimeline() { + // return this._store("roomTimeline", idbStore => new TimelineStore(idbStore)); + // } + + get session() { + return this._store("session", idbStore => new SessionStore(idbStore)); } complete() {