forked from mystiq/hydrogen-web
pass logger to Storage and make it available in Transaction
This commit is contained in:
parent
cce7606960
commit
aeedb948cc
5 changed files with 41 additions and 19 deletions
|
@ -150,7 +150,9 @@ export class SessionPickerViewModel extends ViewModel {
|
||||||
|
|
||||||
async _exportData(id) {
|
async _exportData(id) {
|
||||||
const sessionInfo = await this.platform.sessionInfoStorage.get(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};
|
const data = {sessionInfo, stores};
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
@ -161,7 +163,9 @@ export class SessionPickerViewModel extends ViewModel {
|
||||||
const {sessionInfo} = data;
|
const {sessionInfo} = data;
|
||||||
sessionInfo.comment = `Imported on ${new Date().toLocaleString()} from id ${sessionInfo.id}.`;
|
sessionInfo.comment = `Imported on ${new Date().toLocaleString()} from id ${sessionInfo.id}.`;
|
||||||
sessionInfo.id = this._createSessionContainer().createNewSessionId();
|
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);
|
await this.platform.sessionInfoStorage.add(sessionInfo);
|
||||||
this._sessions.set(new SessionItemViewModel(sessionInfo, this));
|
this._sessions.set(new SessionItemViewModel(sessionInfo, this));
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|
|
@ -231,4 +231,8 @@ export class LogItem {
|
||||||
this._children.push(item);
|
this._children.push(item);
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get logger() {
|
||||||
|
return this._logger;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,20 +17,23 @@ limitations under the License.
|
||||||
import {Transaction} from "./Transaction";
|
import {Transaction} from "./Transaction";
|
||||||
import { STORE_NAMES, StoreNames, StorageError } from "../common";
|
import { STORE_NAMES, StoreNames, StorageError } from "../common";
|
||||||
import { reqAsPromise } from "./utils";
|
import { reqAsPromise } from "./utils";
|
||||||
|
import { BaseLogger } from "../../../logging/BaseLogger.js";
|
||||||
|
|
||||||
const WEBKITEARLYCLOSETXNBUG_BOGUS_KEY = "782rh281re38-boguskey";
|
const WEBKITEARLYCLOSETXNBUG_BOGUS_KEY = "782rh281re38-boguskey";
|
||||||
|
|
||||||
export class Storage {
|
export class Storage {
|
||||||
private _db: IDBDatabase;
|
private _db: IDBDatabase;
|
||||||
private _hasWebkitEarlyCloseTxnBug: boolean;
|
private _hasWebkitEarlyCloseTxnBug: boolean;
|
||||||
private _IDBKeyRange: typeof IDBKeyRange
|
readonly logger: BaseLogger;
|
||||||
storeNames: typeof StoreNames;
|
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._db = idbDatabase;
|
||||||
this._IDBKeyRange = _IDBKeyRange;
|
this.IDBKeyRange = _IDBKeyRange;
|
||||||
this._hasWebkitEarlyCloseTxnBug = hasWebkitEarlyCloseTxnBug;
|
this._hasWebkitEarlyCloseTxnBug = hasWebkitEarlyCloseTxnBug;
|
||||||
this.storeNames = StoreNames;
|
this.storeNames = StoreNames;
|
||||||
|
this.logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
_validateStoreNames(storeNames: StoreNames[]): void {
|
_validateStoreNames(storeNames: StoreNames[]): void {
|
||||||
|
@ -49,7 +52,7 @@ export class Storage {
|
||||||
if (this._hasWebkitEarlyCloseTxnBug) {
|
if (this._hasWebkitEarlyCloseTxnBug) {
|
||||||
await reqAsPromise(txn.objectStore(storeNames[0]).get(WEBKITEARLYCLOSETXNBUG_BOGUS_KEY));
|
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) {
|
} catch(err) {
|
||||||
throw new StorageError("readTxn failed", err);
|
throw new StorageError("readTxn failed", err);
|
||||||
}
|
}
|
||||||
|
@ -64,7 +67,7 @@ export class Storage {
|
||||||
if (this._hasWebkitEarlyCloseTxnBug) {
|
if (this._hasWebkitEarlyCloseTxnBug) {
|
||||||
await reqAsPromise(txn.objectStore(storeNames[0]).get(WEBKITEARLYCLOSETXNBUG_BOGUS_KEY));
|
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) {
|
} catch(err) {
|
||||||
throw new StorageError("readWriteTxn failed", err);
|
throw new StorageError("readWriteTxn failed", err);
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,9 +20,10 @@ import { exportSession, importSession, Export } from "./export";
|
||||||
import { schema } from "./schema";
|
import { schema } from "./schema";
|
||||||
import { detectWebkitEarlyCloseTxnBug } from "./quirks";
|
import { detectWebkitEarlyCloseTxnBug } from "./quirks";
|
||||||
import { BaseLogger } from "../../../logging/BaseLogger.js";
|
import { BaseLogger } from "../../../logging/BaseLogger.js";
|
||||||
|
import { LogItem } from "../../../logging/LogItem.js";
|
||||||
|
|
||||||
const sessionName = (sessionId: string) => `hydrogen_session_${sessionId}`;
|
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);
|
const create = (db, txn, oldVersion, version) => createStores(db, txn, oldVersion, version, log);
|
||||||
return openDatabase(sessionName(sessionId), create, schema.length, idbFactory);
|
return openDatabase(sessionName(sessionId), create, schema.length, idbFactory);
|
||||||
}
|
}
|
||||||
|
@ -59,7 +60,7 @@ export class StorageFactory {
|
||||||
this._IDBKeyRange = _IDBKeyRange;
|
this._IDBKeyRange = _IDBKeyRange;
|
||||||
}
|
}
|
||||||
|
|
||||||
async create(sessionId: string, log?: BaseLogger): Promise<Storage> {
|
async create(sessionId: string, log: LogItem): Promise<Storage> {
|
||||||
await this._serviceWorkerHandler?.preventConcurrentSessionAccess(sessionId);
|
await this._serviceWorkerHandler?.preventConcurrentSessionAccess(sessionId);
|
||||||
requestPersistedStorage().then(persisted => {
|
requestPersistedStorage().then(persisted => {
|
||||||
// Firefox lies here though, and returns true even if the user denied the request
|
// 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 hasWebkitEarlyCloseTxnBug = await detectWebkitEarlyCloseTxnBug(this._idbFactory);
|
||||||
const db = await openDatabaseWithSessionId(sessionId, this._idbFactory, log);
|
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> {
|
delete(sessionId: string): Promise<IDBDatabase> {
|
||||||
|
@ -79,18 +80,18 @@ export class StorageFactory {
|
||||||
return reqAsPromise(req);
|
return reqAsPromise(req);
|
||||||
}
|
}
|
||||||
|
|
||||||
async export(sessionId: string): Promise<Export> {
|
async export(sessionId: string, log: LogItem): Promise<Export> {
|
||||||
const db = await openDatabaseWithSessionId(sessionId, this._idbFactory);
|
const db = await openDatabaseWithSessionId(sessionId, this._idbFactory, log);
|
||||||
return await exportSession(db);
|
return await exportSession(db);
|
||||||
}
|
}
|
||||||
|
|
||||||
async import(sessionId: string, data: Export): Promise<void> {
|
async import(sessionId: string, data: Export, log: LogItem): Promise<void> {
|
||||||
const db = await openDatabaseWithSessionId(sessionId, this._idbFactory);
|
const db = await openDatabaseWithSessionId(sessionId, this._idbFactory, log);
|
||||||
return await importSession(db, data);
|
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;
|
const startIdx = oldVersion || 0;
|
||||||
return log.wrap({l: "storage migration", oldVersion, version}, async log => {
|
return log.wrap({l: "storage migration", oldVersion, version}, async log => {
|
||||||
for(let i = startIdx; i < version; ++i) {
|
for(let i = startIdx; i < version; ++i) {
|
||||||
|
|
|
@ -35,18 +35,28 @@ import {OutboundGroupSessionStore} from "./stores/OutboundGroupSessionStore";
|
||||||
import {GroupSessionDecryptionStore} from "./stores/GroupSessionDecryptionStore";
|
import {GroupSessionDecryptionStore} from "./stores/GroupSessionDecryptionStore";
|
||||||
import {OperationStore} from "./stores/OperationStore";
|
import {OperationStore} from "./stores/OperationStore";
|
||||||
import {AccountDataStore} from "./stores/AccountDataStore";
|
import {AccountDataStore} from "./stores/AccountDataStore";
|
||||||
|
import {BaseLogger} from "../../../logging/BaseLogger.js";
|
||||||
|
|
||||||
export class Transaction {
|
export class Transaction {
|
||||||
private _txn: IDBTransaction;
|
private _txn: IDBTransaction;
|
||||||
private _allowedStoreNames: StoreNames[];
|
private _allowedStoreNames: StoreNames[];
|
||||||
private _stores: { [storeName in StoreNames]?: any };
|
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._txn = txn;
|
||||||
this._allowedStoreNames = allowedStoreNames;
|
this._allowedStoreNames = allowedStoreNames;
|
||||||
this._stores = {};
|
this._stores = {};
|
||||||
// @ts-ignore
|
this._storage = storage;
|
||||||
this.IDBKeyRange = IDBKeyRange;
|
this._writeErrors = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
get IDBKeyRange(): typeof IDBKeyRange {
|
||||||
|
return this._storage.IDBKeyRange;
|
||||||
|
}
|
||||||
|
|
||||||
|
get logger(): BaseLogger {
|
||||||
|
return this._storage.logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
_idbStore(name: StoreNames): Store<any> {
|
_idbStore(name: StoreNames): Store<any> {
|
||||||
|
|
Loading…
Reference in a new issue