pass logger to Storage and make it available in Transaction

This commit is contained in:
Bruno Windels 2021-09-17 18:19:26 +02:00
parent cce7606960
commit aeedb948cc
5 changed files with 41 additions and 19 deletions

View file

@ -150,7 +150,9 @@ export class SessionPickerViewModel extends ViewModel {
async _exportData(id) {
const sessionInfo = await this.platform.sessionInfoStorage.get(id);
const stores = await this.platform.storageFactory.export(id);
const stores = await this.logger.run("export", log => {
return this.platform.storageFactory.export(id, log);
});
const data = {sessionInfo, stores};
return data;
}
@ -161,7 +163,9 @@ export class SessionPickerViewModel extends ViewModel {
const {sessionInfo} = data;
sessionInfo.comment = `Imported on ${new Date().toLocaleString()} from id ${sessionInfo.id}.`;
sessionInfo.id = this._createSessionContainer().createNewSessionId();
await this.platform.storageFactory.import(sessionInfo.id, data.stores);
await this.logger.run("import", log => {
return this.platform.storageFactory.import(sessionInfo.id, data.stores, log);
});
await this.platform.sessionInfoStorage.add(sessionInfo);
this._sessions.set(new SessionItemViewModel(sessionInfo, this));
} catch (err) {

View file

@ -231,4 +231,8 @@ export class LogItem {
this._children.push(item);
return item;
}
get logger() {
return this._logger;
}
}

View file

@ -17,20 +17,23 @@ limitations under the License.
import {Transaction} from "./Transaction";
import { STORE_NAMES, StoreNames, StorageError } from "../common";
import { reqAsPromise } from "./utils";
import { BaseLogger } from "../../../logging/BaseLogger.js";
const WEBKITEARLYCLOSETXNBUG_BOGUS_KEY = "782rh281re38-boguskey";
export class Storage {
private _db: IDBDatabase;
private _hasWebkitEarlyCloseTxnBug: boolean;
private _IDBKeyRange: typeof IDBKeyRange
storeNames: typeof StoreNames;
readonly logger: BaseLogger;
readonly IDBKeyRange: typeof IDBKeyRange;
readonly storeNames: typeof StoreNames;
constructor(idbDatabase: IDBDatabase, _IDBKeyRange: typeof IDBKeyRange, hasWebkitEarlyCloseTxnBug: boolean) {
constructor(idbDatabase: IDBDatabase, _IDBKeyRange: typeof IDBKeyRange, hasWebkitEarlyCloseTxnBug: boolean, logger: BaseLogger) {
this._db = idbDatabase;
this._IDBKeyRange = _IDBKeyRange;
this.IDBKeyRange = _IDBKeyRange;
this._hasWebkitEarlyCloseTxnBug = hasWebkitEarlyCloseTxnBug;
this.storeNames = StoreNames;
this.logger = logger;
}
_validateStoreNames(storeNames: StoreNames[]): void {
@ -49,7 +52,7 @@ export class Storage {
if (this._hasWebkitEarlyCloseTxnBug) {
await reqAsPromise(txn.objectStore(storeNames[0]).get(WEBKITEARLYCLOSETXNBUG_BOGUS_KEY));
}
return new Transaction(txn, storeNames, this._IDBKeyRange);
return new Transaction(txn, storeNames, this);
} catch(err) {
throw new StorageError("readTxn failed", err);
}
@ -64,7 +67,7 @@ export class Storage {
if (this._hasWebkitEarlyCloseTxnBug) {
await reqAsPromise(txn.objectStore(storeNames[0]).get(WEBKITEARLYCLOSETXNBUG_BOGUS_KEY));
}
return new Transaction(txn, storeNames, this._IDBKeyRange);
return new Transaction(txn, storeNames, this);
} catch(err) {
throw new StorageError("readWriteTxn failed", err);
}

View file

@ -20,9 +20,10 @@ import { exportSession, importSession, Export } from "./export";
import { schema } from "./schema";
import { detectWebkitEarlyCloseTxnBug } from "./quirks";
import { BaseLogger } from "../../../logging/BaseLogger.js";
import { LogItem } from "../../../logging/LogItem.js";
const sessionName = (sessionId: string) => `hydrogen_session_${sessionId}`;
const openDatabaseWithSessionId = function(sessionId: string, idbFactory: IDBFactory, log?: BaseLogger) {
const openDatabaseWithSessionId = function(sessionId: string, idbFactory: IDBFactory, log: LogItem) {
const create = (db, txn, oldVersion, version) => createStores(db, txn, oldVersion, version, log);
return openDatabase(sessionName(sessionId), create, schema.length, idbFactory);
}
@ -59,7 +60,7 @@ export class StorageFactory {
this._IDBKeyRange = _IDBKeyRange;
}
async create(sessionId: string, log?: BaseLogger): Promise<Storage> {
async create(sessionId: string, log: LogItem): Promise<Storage> {
await this._serviceWorkerHandler?.preventConcurrentSessionAccess(sessionId);
requestPersistedStorage().then(persisted => {
// Firefox lies here though, and returns true even if the user denied the request
@ -70,7 +71,7 @@ export class StorageFactory {
const hasWebkitEarlyCloseTxnBug = await detectWebkitEarlyCloseTxnBug(this._idbFactory);
const db = await openDatabaseWithSessionId(sessionId, this._idbFactory, log);
return new Storage(db, this._IDBKeyRange, hasWebkitEarlyCloseTxnBug);
return new Storage(db, this._IDBKeyRange, hasWebkitEarlyCloseTxnBug, log.logger);
}
delete(sessionId: string): Promise<IDBDatabase> {
@ -79,18 +80,18 @@ export class StorageFactory {
return reqAsPromise(req);
}
async export(sessionId: string): Promise<Export> {
const db = await openDatabaseWithSessionId(sessionId, this._idbFactory);
async export(sessionId: string, log: LogItem): Promise<Export> {
const db = await openDatabaseWithSessionId(sessionId, this._idbFactory, log);
return await exportSession(db);
}
async import(sessionId: string, data: Export): Promise<void> {
const db = await openDatabaseWithSessionId(sessionId, this._idbFactory);
async import(sessionId: string, data: Export, log: LogItem): Promise<void> {
const db = await openDatabaseWithSessionId(sessionId, this._idbFactory, log);
return await importSession(db, data);
}
}
async function createStores(db: IDBDatabase, txn: IDBTransaction, oldVersion: number | null, version: number, log?: BaseLogger): Promise<void> {
async function createStores(db: IDBDatabase, txn: IDBTransaction, oldVersion: number | null, version: number, log: LogItem): Promise<void> {
const startIdx = oldVersion || 0;
return log.wrap({l: "storage migration", oldVersion, version}, async log => {
for(let i = startIdx; i < version; ++i) {

View file

@ -35,18 +35,28 @@ import {OutboundGroupSessionStore} from "./stores/OutboundGroupSessionStore";
import {GroupSessionDecryptionStore} from "./stores/GroupSessionDecryptionStore";
import {OperationStore} from "./stores/OperationStore";
import {AccountDataStore} from "./stores/AccountDataStore";
import {BaseLogger} from "../../../logging/BaseLogger.js";
export class Transaction {
private _txn: IDBTransaction;
private _allowedStoreNames: StoreNames[];
private _stores: { [storeName in StoreNames]?: any };
private _storage: Storage;
constructor(txn: IDBTransaction, allowedStoreNames: StoreNames[], IDBKeyRange) {
constructor(txn: IDBTransaction, allowedStoreNames: StoreNames[], storage: Storage) {
this._txn = txn;
this._allowedStoreNames = allowedStoreNames;
this._stores = {};
// @ts-ignore
this.IDBKeyRange = IDBKeyRange;
this._storage = storage;
this._writeErrors = [];
}
get IDBKeyRange(): typeof IDBKeyRange {
return this._storage.IDBKeyRange;
}
get logger(): BaseLogger {
return this._storage.logger;
}
_idbStore(name: StoreNames): Store<any> {