basic session loading

This commit is contained in:
Bruno Windels 2019-02-07 00:20:27 +00:00
parent c115164822
commit 3f776129f5
10 changed files with 94 additions and 101 deletions

View file

@ -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();

View file

@ -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;
}
}

View file

@ -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"]});

View file

@ -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;
}
_queryTarget() {
throw new Error("override this");
}
}

View file

@ -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);

View file

@ -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;
}
}

View file

@ -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));
}
}

View file

@ -14,59 +14,19 @@ store contains:
avatarUrl
lastSynced
*/
class SessionStore {
export default class SessionStore {
constructor(sessionStore) {
this._sessionStore = sessionStore;
}
readSession() {
return this._session;
}
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();
async get() {
const session = await this._sessionStore.selectFirst(IDBKeyRange.only(1));
if (session) {
return session.value;
}
}
set(session) {
return this._sessionStore.put({key: 1, value: session});
}
}

View file

@ -1,5 +1,4 @@
import GapSortKey from "./gapsortkey";
import {select} from "./utils";
import SortKey from "../../sortkey.js";
class TimelineStore {
constructor(timelineStore) {

View file

@ -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() {