diff --git a/src/domain/session/room/timeline/ReactionsViewModel.js b/src/domain/session/room/timeline/ReactionsViewModel.js index 25d74b49..3a47aaa0 100644 --- a/src/domain/session/room/timeline/ReactionsViewModel.js +++ b/src/domain/session/room/timeline/ReactionsViewModel.js @@ -184,7 +184,7 @@ import {Clock as MockClock} from "../../../../mocks/Clock.js"; import {createMockStorage} from "../../../../mocks/Storage"; import {ListObserver} from "../../../../mocks/ListObserver.js"; import {createEvent, withTextBody, withContent} from "../../../../mocks/event.js"; -import {NullLogItem, NullLogger} from "../../../../logging/NullLogger.js"; +import {NullLogItem, NullLogger} from "../../../../logging/NullLogger"; import {HomeServer as MockHomeServer} from "../../../../mocks/HomeServer.js"; // other imports import {BaseMessageTile} from "./tiles/BaseMessageTile.js"; diff --git a/src/logging/BaseLogger.ts b/src/logging/BaseLogger.ts index 9865355a..e420c0df 100644 --- a/src/logging/BaseLogger.ts +++ b/src/logging/BaseLogger.ts @@ -17,14 +17,14 @@ limitations under the License. import {LogItem} from "./LogItem"; import {LogLevel, LogFilter} from "./LogFilter"; -import type {FilterCreator, LabelOrValues, LogCallback} from "./LogItem"; +import type {FilterCreator, LabelOrValues, LogCallback, ILogItem} from "./LogItem"; import type {LogLevelOrNull} from "./LogFilter"; // todo: should this import be here just for getting the type? should it instead be done when Platform.js --> Platform.ts? import type {Platform} from "../platform/web/Platform.js"; export abstract class BaseLogger { - protected _openItems: Set = new Set(); + protected _openItems: Set = new Set(); protected _platform: Platform; constructor({platform}) { @@ -38,7 +38,7 @@ export abstract class BaseLogger { } /** if item is a log item, wrap the callback in a child of it, otherwise start a new root log item. */ - wrapOrRun(item: LogItem, labelOrValues: LabelOrValues, callback: LogCallback, logLevel: LogLevelOrNull = null, filterCreator: FilterCreator = null): unknown { + wrapOrRun(item: ILogItem, labelOrValues: LabelOrValues, callback: LogCallback, logLevel: LogLevelOrNull = null, filterCreator: FilterCreator = null): unknown { if (item) { return item.wrap(labelOrValues, callback, logLevel, filterCreator); } else { @@ -51,7 +51,7 @@ export abstract class BaseLogger { Useful to pair with LogItem.refDetached. @return {LogItem} the log item added, useful to pass to LogItem.refDetached */ - runDetached(labelOrValues: LabelOrValues, callback: LogCallback, logLevel: LogLevelOrNull = null, filterCreator: FilterCreator = null): LogItem { + runDetached(labelOrValues: LabelOrValues, callback: LogCallback, logLevel: LogLevelOrNull = null, filterCreator: FilterCreator = null): ILogItem { // todo: Remove jsdoc type? if (logLevel === null) { logLevel = LogLevel.Info; @@ -72,7 +72,7 @@ export abstract class BaseLogger { return this._run(item, callback, logLevel!, filterCreator, true); } - _run(item: LogItem, callback: LogCallback, logLevel: LogLevel, filterCreator: FilterCreator, shouldThrow: boolean): unknown { + _run(item: ILogItem, callback: LogCallback, logLevel: LogLevel, filterCreator: FilterCreator, shouldThrow: boolean): unknown { this._openItems.add(item); const finishItem = () => { @@ -135,7 +135,7 @@ export abstract class BaseLogger { this._openItems.clear(); } - abstract _persistItem(item: LogItem, filter?: LogFilter, forced?: boolean): void; + abstract _persistItem(item: ILogItem, filter?: LogFilter, forced?: boolean): void; abstract export(): void; diff --git a/src/logging/ConsoleLogger.ts b/src/logging/ConsoleLogger.ts index 5b709bb1..d8693e38 100644 --- a/src/logging/ConsoleLogger.ts +++ b/src/logging/ConsoleLogger.ts @@ -14,10 +14,10 @@ See the License for the specific language governing permissions and limitations under the License. */ import {BaseLogger} from "./BaseLogger"; -import type {LogItem, LogItemValues} from "./LogItem"; +import type {ILogItem, LogItemValues} from "./LogItem"; export class ConsoleLogger extends BaseLogger { - _persistItem(item: LogItem): void { + _persistItem(item: ILogItem): void { printToConsole(item); } @@ -41,7 +41,7 @@ function filterValues(values: LogItemValues): LogItemValues | null { }, null); } -function printToConsole(item: LogItem): void { +function printToConsole(item: ILogItem): void { const label = `${itemCaption(item)} (${item.duration}ms)`; const filteredValues = filterValues(item.values); const shouldGroup = item.children || filteredValues; @@ -74,7 +74,7 @@ function printToConsole(item: LogItem): void { } } -function itemCaption(item: LogItem): string { +function itemCaption(item: ILogItem): string { if (item.values.t === "network") { return `${item.values.method} ${item.values.url}`; } else if (item.values.l && typeof item.values.id !== "undefined") { diff --git a/src/logging/IDBLogger.ts b/src/logging/IDBLogger.ts index 3283dd0d..960db0da 100644 --- a/src/logging/IDBLogger.ts +++ b/src/logging/IDBLogger.ts @@ -26,7 +26,7 @@ import {BaseLogger} from "./BaseLogger"; import type {Interval} from "../platform/web/dom/Clock"; import type {Platform} from "../platform/web/Platform.js"; import type {BlobHandle} from "../platform/web/dom/BlobHandle.js"; -import type {LogItem} from "./LogItem"; +import type {ILogItem} from "./LogItem"; import type {LogFilter} from "./LogFilter"; type QueuedItem = { @@ -116,8 +116,8 @@ export class IDBLogger extends BaseLogger { return openDatabase(this._name, db => db.createObjectStore("logs", {keyPath: "id", autoIncrement: true}), 1); } - _persistItem(logItem: LogItem, filter: LogFilter, forced: boolean): void { - const serializedItem = logItem.serialize(filter, undefined, forced); + _persistItem(logItem: ILogItem, filter: LogFilter, forced: boolean): void { + const serializedItem = logItem.serialize(filter, null, forced); this._queuedItems.push({ json: JSON.stringify(serializedItem) }); diff --git a/src/logging/LogFilter.ts b/src/logging/LogFilter.ts index 480e92db..dc415ede 100644 --- a/src/logging/LogFilter.ts +++ b/src/logging/LogFilter.ts @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import type {LogItem} from "./LogItem"; +import type {ILogItem} from "./LogItem"; export enum LogLevel { All = 1, @@ -37,7 +37,7 @@ export class LogFilter { this._parentFilter = parentFilter; } - filter(item: LogItem, children: Array | null): boolean { + filter(item: ILogItem, children: Array | null): boolean { if (this._parentFilter) { if (!this._parentFilter.filter(item, children)) { return false; diff --git a/src/logging/LogItem.ts b/src/logging/LogItem.ts index 051b0353..54957347 100644 --- a/src/logging/LogItem.ts +++ b/src/logging/LogItem.ts @@ -33,6 +33,30 @@ interface ISerializedItem { c?: Array; }; +export interface ILogItem { + logger: any; + level: typeof LogLevel; + duration?: number; + end?: number | null; + start?: number; + logLevel: LogLevel; + children: Array | null; + values: LogItemValues; + error: Error | null; + wrap(labelOrValues: LabelOrValues, callback: LogCallback, level: LogLevelOrNull, filterCreator: FilterCreator): unknown; + log(labelOrValues: LabelOrValues, logLevel: LogLevelOrNull): void; + set(key: string | object, value: unknown): void; + run(callback: LogCallback): unknown; + runDetached(labelOrValues: LabelOrValues, callback: LogCallback, logLevel: LogLevelOrNull, filterCreator: FilterCreator): ILogItem; + wrapDetached(labelOrValues: LabelOrValues, callback: LogCallback, logLevel: LogLevelOrNull, filterCreator: FilterCreator): void; + refDetached(logItem: ILogItem, logLevel: LogLevelOrNull): void; + ensureRefId(): void; + catch(err: Error): Error; + finish(): void; + child(labelOrValues: LabelOrValues, logLevel: LogLevelOrNull, filterCreator: FilterCreator): ILogItem; + serialize(filter: LogFilter, parentStartTime: number | null, forced: boolean): ISerializedItem | null; +} + export type LogItemValues = { l?: string; t?: string; @@ -44,10 +68,10 @@ export type LogItemValues = { } export type LabelOrValues = string | LogItemValues; -export type FilterCreator = ((filter: LogFilter, item: LogItem) => LogFilter) | null; -export type LogCallback = (item: LogItem) => unknown; +export type FilterCreator = ((filter: LogFilter, item: ILogItem) => LogFilter) | null; +export type LogCallback = (item: ILogItem) => unknown; -export class LogItem { +export class LogItem implements ILogItem { public readonly start: number; public logLevel: LogLevel; public error: Error | null; @@ -70,7 +94,7 @@ export class LogItem { } /** start a new root log item and run it detached mode, see BaseLogger.runDetached */ - runDetached(labelOrValues: LabelOrValues, callback: LogCallback, logLevel: LogLevelOrNull, filterCreator: FilterCreator): LogItem { + runDetached(labelOrValues: LabelOrValues, callback: LogCallback, logLevel: LogLevelOrNull, filterCreator: FilterCreator): ILogItem { return this._logger.runDetached(labelOrValues, callback, logLevel, filterCreator); } @@ -81,9 +105,9 @@ export class LogItem { /** logs a reference to a different log item, usually obtained from runDetached. This is useful if the referenced operation can't be awaited. */ - refDetached(logItem: LogItem, logLevel: LogLevelOrNull = null): void { + refDetached(logItem: ILogItem, logLevel: LogLevelOrNull = null): void { logItem.ensureRefId(); - this.log({ref: logItem._values.refId as number}, logLevel); + this.log({ref: (logItem as LogItem)._values.refId}, logLevel); } ensureRefId(): void { @@ -267,7 +291,7 @@ export class LogItem { return err; } - child(labelOrValues: LabelOrValues, logLevel: LogLevelOrNull, filterCreator: FilterCreator): LogItem { + child(labelOrValues: LabelOrValues, logLevel: LogLevelOrNull, filterCreator: FilterCreator): ILogItem { if (this.end !== null) { console.trace("log item is finished, additional logs will likely not be recorded"); } diff --git a/src/logging/NullLogger.js b/src/logging/NullLogger.ts similarity index 57% rename from src/logging/NullLogger.js rename to src/logging/NullLogger.ts index 12eec5c9..285ea1e4 100644 --- a/src/logging/NullLogger.js +++ b/src/logging/NullLogger.ts @@ -14,18 +14,17 @@ See the License for the specific language governing permissions and limitations under the License. */ import {LogLevel} from "./LogFilter"; +import type {ILogItem, LabelOrValues, LogCallback, LogItemValues} from "./LogItem"; -function noop () {} +function noop (): void {} export class NullLogger { - constructor() { - this.item = new NullLogItem(this); - } + public readonly item: ILogItem = new NullLogItem(this); - log() {} + log(): void {} - run(_, callback) { + run(_: null, callback) { return callback(this.item); } @@ -50,50 +49,61 @@ export class NullLogger { } } -export class NullLogItem { - constructor(logger) { +export class NullLogItem implements ILogItem { + public readonly logger: NullLogger; + public readonly logLevel: LogLevel; + public children: Array | null = null; + public values: LogItemValues; + public error: Error | null = null; + + constructor(logger: NullLogger) { this.logger = logger; } - wrap(_, callback) { + wrap(_: LabelOrValues, callback: LogCallback): unknown { return callback(this); } - log() {} - set() {} + log(): void {} + set(): void {} - runDetached(_, callback) { + runDetached(_: LabelOrValues, callback: LogCallback): ILogItem { new Promise(r => r(callback(this))).then(noop, noop); - } - - wrapDetached(_, callback) { - return this.refDetached(null, callback); - } - - run(callback) { - return callback(this); - } - - refDetached() {} - - ensureRefId() {} - - get level() { - return LogLevel; - } - - get duration() { - return 0; - } - - catch(err) { - return err; - } - - child() { return this; } - finish() {} + wrapDetached(_: LabelOrValues, _callback: LogCallback): void { + return this.refDetached(); + } + + run(callback: LogCallback): unknown { + return callback(this); + } + + refDetached(): void {} + + ensureRefId(): void {} + + get level(): typeof LogLevel { + return LogLevel; + } + + get duration(): 0 { + return 0; + } + + catch(err: Error): Error { + return err; + } + + child() { + return this; + } + + finish(): void {} + + serialize() { + return null; + } } export const Instance = new NullLogger(); diff --git a/src/logging/utils.js b/src/logging/utils.js index 3da9aa5d..659df055 100644 --- a/src/logging/utils.js +++ b/src/logging/utils.js @@ -1,7 +1,7 @@ // these are helper functions if you can't assume you always have a log item (e.g. some code paths call with one set, others don't) // if you know you always have a log item, better to use the methods on the log item than these utility functions. -import {Instance as NullLoggerInstance} from "./NullLogger.js"; +import {Instance as NullLoggerInstance} from "./NullLogger"; export function wrapOrRunNullLogger(logItem, labelOrValues, callback, logLevel = null, filterCreator = null) { if (logItem) { diff --git a/src/matrix/e2ee/megolm/Decryption.ts b/src/matrix/e2ee/megolm/Decryption.ts index 842d423d..4cb66971 100644 --- a/src/matrix/e2ee/megolm/Decryption.ts +++ b/src/matrix/e2ee/megolm/Decryption.ts @@ -26,7 +26,7 @@ import type {OlmWorker} from "../OlmWorker"; import type {Transaction} from "../../storage/idb/Transaction"; import type {TimelineEvent} from "../../storage/types"; import type {DecryptionResult} from "../DecryptionResult"; -import type {LogItem} from "../../../logging/LogItem"; +import type {ILogItem} from "../../../logging/LogItem"; export class Decryption { private keyLoader: KeyLoader; @@ -136,7 +136,7 @@ export class Decryption { * Extracts room keys from decrypted device messages. * The key won't be persisted yet, you need to call RoomKey.write for that. */ - roomKeysFromDeviceMessages(decryptionResults: DecryptionResult[], log: LogItem): IncomingRoomKey[] { + roomKeysFromDeviceMessages(decryptionResults: DecryptionResult[], log: ILogItem): IncomingRoomKey[] { const keys: IncomingRoomKey[] = []; for (const dr of decryptionResults) { if (dr.event?.type !== "m.room_key" || dr.event.content?.algorithm !== MEGOLM_ALGORITHM) { @@ -152,7 +152,7 @@ export class Decryption { log.logLevel = log.level.Warn; log.set("invalid", true); } - }, log.level.Detail); + }, log.level.Detail, null); } return keys; } diff --git a/src/matrix/room/Invite.js b/src/matrix/room/Invite.js index 1bf802dd..da721c77 100644 --- a/src/matrix/room/Invite.js +++ b/src/matrix/room/Invite.js @@ -244,7 +244,7 @@ export class Invite extends EventEmitter { } } -import {NullLogItem} from "../../logging/NullLogger.js"; +import {NullLogItem} from "../../logging/NullLogger"; import {Clock as MockClock} from "../../mocks/Clock.js"; import {default as roomInviteFixture} from "../../fixtures/matrix/invites/room.js"; import {default as dmInviteFixture} from "../../fixtures/matrix/invites/dm.js"; diff --git a/src/matrix/room/sending/SendQueue.js b/src/matrix/room/sending/SendQueue.js index 28408e34..896100c7 100644 --- a/src/matrix/room/sending/SendQueue.js +++ b/src/matrix/room/sending/SendQueue.js @@ -353,7 +353,7 @@ export class SendQueue { import {HomeServer as MockHomeServer} from "../../../mocks/HomeServer.js"; import {createMockStorage} from "../../../mocks/Storage"; import {ListObserver} from "../../../mocks/ListObserver.js"; -import {NullLogger, NullLogItem} from "../../../logging/NullLogger.js"; +import {NullLogger, NullLogItem} from "../../../logging/NullLogger"; import {createEvent, withTextBody, withTxnId} from "../../../mocks/event.js"; import {poll} from "../../../mocks/poll.js"; import {createAnnotation} from "../timeline/relations.js"; diff --git a/src/matrix/room/timeline/Timeline.js b/src/matrix/room/timeline/Timeline.js index 4e6fe40c..bd89ee8d 100644 --- a/src/matrix/room/timeline/Timeline.js +++ b/src/matrix/room/timeline/Timeline.js @@ -346,7 +346,7 @@ import {Clock as MockClock} from "../../../mocks/Clock.js"; import {createMockStorage} from "../../../mocks/Storage"; import {ListObserver} from "../../../mocks/ListObserver.js"; import {createEvent, withTextBody, withContent, withSender} from "../../../mocks/event.js"; -import {NullLogItem} from "../../../logging/NullLogger.js"; +import {NullLogItem} from "../../../logging/NullLogger"; import {EventEntry} from "./entries/EventEntry.js"; import {User} from "../../User.js"; import {PendingEvent} from "../sending/PendingEvent.js"; diff --git a/src/matrix/room/timeline/persistence/GapWriter.js b/src/matrix/room/timeline/persistence/GapWriter.js index 7794b797..3e520608 100644 --- a/src/matrix/room/timeline/persistence/GapWriter.js +++ b/src/matrix/room/timeline/persistence/GapWriter.js @@ -205,7 +205,7 @@ import {FragmentIdComparer} from "../FragmentIdComparer.js"; import {RelationWriter} from "./RelationWriter.js"; import {createMockStorage} from "../../../../mocks/Storage"; import {FragmentBoundaryEntry} from "../entries/FragmentBoundaryEntry.js"; -import {NullLogItem} from "../../../../logging/NullLogger.js"; +import {NullLogItem} from "../../../../logging/NullLogger"; import {TimelineMock, eventIds, eventId} from "../../../../mocks/TimelineMock.ts"; import {SyncWriter} from "./SyncWriter.js"; import {MemberWriter} from "./MemberWriter.js"; diff --git a/src/matrix/room/timeline/persistence/RelationWriter.js b/src/matrix/room/timeline/persistence/RelationWriter.js index c0d3d369..60a2b618 100644 --- a/src/matrix/room/timeline/persistence/RelationWriter.js +++ b/src/matrix/room/timeline/persistence/RelationWriter.js @@ -257,7 +257,7 @@ import {createMockStorage} from "../../../../mocks/Storage"; import {createEvent, withTextBody, withRedacts, withContent} from "../../../../mocks/event.js"; import {createAnnotation} from "../relations.js"; import {FragmentIdComparer} from "../FragmentIdComparer.js"; -import {NullLogItem} from "../../../../logging/NullLogger.js"; +import {NullLogItem} from "../../../../logging/NullLogger"; export function tests() { const fragmentIdComparer = new FragmentIdComparer([]); diff --git a/src/matrix/room/timeline/persistence/SyncWriter.js b/src/matrix/room/timeline/persistence/SyncWriter.js index 749c3392..dc5ae3a8 100644 --- a/src/matrix/room/timeline/persistence/SyncWriter.js +++ b/src/matrix/room/timeline/persistence/SyncWriter.js @@ -258,7 +258,7 @@ export class SyncWriter { import {createMockStorage} from "../../../../mocks/Storage"; import {createEvent, withTextBody} from "../../../../mocks/event.js"; -import {Instance as nullLogger} from "../../../../logging/NullLogger.js"; +import {Instance as nullLogger} from "../../../../logging/NullLogger"; export function tests() { const roomId = "!abc:hs.tld"; return { diff --git a/src/matrix/storage/idb/QueryTarget.ts b/src/matrix/storage/idb/QueryTarget.ts index 03fe66bc..7519beac 100644 --- a/src/matrix/storage/idb/QueryTarget.ts +++ b/src/matrix/storage/idb/QueryTarget.ts @@ -16,7 +16,7 @@ limitations under the License. import {iterateCursor, DONE, NOT_DONE, reqAsPromise} from "./utils"; import {StorageError} from "../common"; -import {LogItem} from "../../../logging/LogItem"; +import {ILogItem} from "../../../logging/LogItem"; import {IDBKey} from "./Transaction"; // this is the part of the Transaction class API that is used here and in the Store subclass, @@ -25,7 +25,7 @@ export interface ITransaction { idbFactory: IDBFactory; IDBKeyRange: typeof IDBKeyRange; databaseName: string; - addWriteError(error: StorageError, refItem: LogItem | undefined, operationName: string, keys: IDBKey[] | undefined); + addWriteError(error: StorageError, refItem: ILogItem | undefined, operationName: string, keys: IDBKey[] | undefined); } type Reducer = (acc: B, val: A) => B @@ -277,7 +277,7 @@ export function tests() { class MockTransaction extends MockIDBImpl { get databaseName(): string { return "mockdb"; } - addWriteError(error: StorageError, refItem: LogItem | undefined, operationName: string, keys: IDBKey[] | undefined) {} + addWriteError(error: StorageError, refItem: ILogItem | undefined, operationName: string, keys: IDBKey[] | undefined) {} } interface TestEntry { diff --git a/src/matrix/storage/idb/StorageFactory.ts b/src/matrix/storage/idb/StorageFactory.ts index f8cc192d..5ca6bce4 100644 --- a/src/matrix/storage/idb/StorageFactory.ts +++ b/src/matrix/storage/idb/StorageFactory.ts @@ -21,10 +21,10 @@ import { exportSession, importSession, Export } from "./export"; import { schema } from "./schema"; import { detectWebkitEarlyCloseTxnBug } from "./quirks"; import { BaseLogger } from "../../../logging/BaseLogger"; -import { LogItem } from "../../../logging/LogItem"; +import { ILogItem } from "../../../logging/LogItem"; const sessionName = (sessionId: string) => `hydrogen_session_${sessionId}`; -const openDatabaseWithSessionId = function(sessionId: string, idbFactory: IDBFactory, localStorage: IDOMStorage, log: LogItem) { +const openDatabaseWithSessionId = function(sessionId: string, idbFactory: IDBFactory, localStorage: IDOMStorage, log: ILogItem) { const create = (db, txn, oldVersion, version) => createStores(db, txn, oldVersion, version, localStorage, log); return openDatabase(sessionName(sessionId), create, schema.length, idbFactory); } @@ -63,7 +63,7 @@ export class StorageFactory { this._localStorage = localStorage; } - async create(sessionId: string, log: LogItem): Promise { + async create(sessionId: string, log: ILogItem): Promise { await this._serviceWorkerHandler?.preventConcurrentSessionAccess(sessionId); requestPersistedStorage().then(persisted => { // Firefox lies here though, and returns true even if the user denied the request @@ -83,23 +83,30 @@ export class StorageFactory { return reqAsPromise(req); } - async export(sessionId: string, log: LogItem): Promise { + async export(sessionId: string, log: ILogItem): Promise { const db = await openDatabaseWithSessionId(sessionId, this._idbFactory, this._localStorage, log); return await exportSession(db); } - async import(sessionId: string, data: Export, log: LogItem): Promise { + async import(sessionId: string, data: Export, log: ILogItem): Promise { const db = await openDatabaseWithSessionId(sessionId, this._idbFactory, this._localStorage, log); return await importSession(db, data); } } -async function createStores(db: IDBDatabase, txn: IDBTransaction, oldVersion: number | null, version: number, localStorage: IDOMStorage, log: LogItem): Promise { +async function createStores(db: IDBDatabase, txn: IDBTransaction, oldVersion: number | null, version: number, localStorage: IDOMStorage, log: ILogItem): Promise { const startIdx = oldVersion || 0; - return log.wrap({l: "storage migration", oldVersion, version}, async log => { - for(let i = startIdx; i < version; ++i) { - const migrationFunc = schema[i]; - await log.wrap(`v${i + 1}`, log => migrationFunc(db, txn, localStorage, log)); - } - }) as Promise; + return log.wrap( + { l: "storage migration", oldVersion, version }, + async (log) => { + for (let i = startIdx; i < version; ++i) { + const migrationFunc = schema[i]; + await log.wrap(`v${i + 1}`, (log) => + migrationFunc(db, txn, localStorage, log), null, null + ); + } + }, + null, + null + ) as Promise; } diff --git a/src/matrix/storage/idb/Store.ts b/src/matrix/storage/idb/Store.ts index 74de2afa..5a2a9abc 100644 --- a/src/matrix/storage/idb/Store.ts +++ b/src/matrix/storage/idb/Store.ts @@ -18,7 +18,7 @@ import {QueryTarget, IDBQuery, ITransaction} from "./QueryTarget"; import {IDBRequestError, IDBRequestAttemptError} from "./error"; import {reqAsPromise} from "./utils"; import {Transaction, IDBKey} from "./Transaction"; -import {LogItem} from "../../../logging/LogItem"; +import {ILogItem} from "../../../logging/LogItem"; const LOG_REQUESTS = false; @@ -145,7 +145,7 @@ export class Store extends QueryTarget { return new QueryTarget(new QueryTargetWrapper(this._idbStore.index(indexName)), this._transaction); } - put(value: T, log?: LogItem): void { + put(value: T, log?: ILogItem): void { // If this request fails, the error will bubble up to the transaction and abort it, // which is the behaviour we want. Therefore, it is ok to not create a promise for this // request and await it. @@ -160,13 +160,13 @@ export class Store extends QueryTarget { this._prepareErrorLog(request, log, "put", undefined, value); } - add(value: T, log?: LogItem): void { + add(value: T, log?: ILogItem): void { // ok to not monitor result of request, see comment in `put`. const request = this._idbStore.add(value); this._prepareErrorLog(request, log, "add", undefined, value); } - async tryAdd(value: T, log: LogItem): Promise { + async tryAdd(value: T, log: ILogItem): Promise { try { await reqAsPromise(this._idbStore.add(value)); return true; @@ -181,13 +181,13 @@ export class Store extends QueryTarget { } } - delete(keyOrKeyRange: IDBValidKey | IDBKeyRange, log?: LogItem): void { + delete(keyOrKeyRange: IDBValidKey | IDBKeyRange, log?: ILogItem): void { // ok to not monitor result of request, see comment in `put`. const request = this._idbStore.delete(keyOrKeyRange); this._prepareErrorLog(request, log, "delete", keyOrKeyRange, undefined); } - private _prepareErrorLog(request: IDBRequest, log: LogItem | undefined, operationName: string, key: IDBKey | undefined, value: T | undefined) { + private _prepareErrorLog(request: IDBRequest, log: ILogItem | undefined, operationName: string, key: IDBKey | undefined, value: T | undefined) { if (log) { log.ensureRefId(); } diff --git a/src/matrix/storage/idb/Transaction.ts b/src/matrix/storage/idb/Transaction.ts index 0d9e55a5..721ee711 100644 --- a/src/matrix/storage/idb/Transaction.ts +++ b/src/matrix/storage/idb/Transaction.ts @@ -36,7 +36,7 @@ import {OutboundGroupSessionStore} from "./stores/OutboundGroupSessionStore"; import {GroupSessionDecryptionStore} from "./stores/GroupSessionDecryptionStore"; import {OperationStore} from "./stores/OperationStore"; import {AccountDataStore} from "./stores/AccountDataStore"; -import {LogItem} from "../../../logging/LogItem"; +import {ILogItem} from "../../../logging/LogItem"; import {BaseLogger} from "../../../logging/BaseLogger"; export type IDBKey = IDBValidKey | IDBKeyRange; @@ -44,7 +44,7 @@ export type IDBKey = IDBValidKey | IDBKeyRange; class WriteErrorInfo { constructor( public readonly error: StorageError, - public readonly refItem: LogItem | undefined, + public readonly refItem: ILogItem | undefined, public readonly operationName: string, public readonly keys: IDBKey[] | undefined, ) {} @@ -169,7 +169,7 @@ export class Transaction { return this._store(StoreNames.accountData, idbStore => new AccountDataStore(idbStore)); } - async complete(log?: LogItem): Promise { + async complete(log?: ILogItem): Promise { try { await txnAsPromise(this._txn); } catch (err) { @@ -190,7 +190,7 @@ export class Transaction { return error; } - abort(log?: LogItem): void { + abort(log?: ILogItem): void { // TODO: should we wrap the exception in a StorageError? try { this._txn.abort(); @@ -202,14 +202,14 @@ export class Transaction { } } - addWriteError(error: StorageError, refItem: LogItem | undefined, operationName: string, keys: IDBKey[] | undefined) { + addWriteError(error: StorageError, refItem: ILogItem | undefined, operationName: string, keys: IDBKey[] | undefined) { // don't log subsequent `AbortError`s if (error.errcode !== "AbortError" || this._writeErrors.length === 0) { this._writeErrors.push(new WriteErrorInfo(error, refItem, operationName, keys)); } } - private _logWriteErrors(parentItem: LogItem | undefined) { + private _logWriteErrors(parentItem: ILogItem | undefined) { const callback = errorGroupItem => { // we don't have context when there is no parentItem, so at least log stores if (!parentItem) { @@ -226,7 +226,7 @@ export class Transaction { }; const label = `${this._writeErrors.length} storage write operation(s) failed`; if (parentItem) { - parentItem.wrap(label, callback); + parentItem.wrap(label, callback, null, null); } else { this.logger.run(label, callback); } diff --git a/src/matrix/storage/idb/schema.ts b/src/matrix/storage/idb/schema.ts index a9c4e2e4..62a4cea1 100644 --- a/src/matrix/storage/idb/schema.ts +++ b/src/matrix/storage/idb/schema.ts @@ -11,10 +11,10 @@ import {SessionStore} from "./stores/SessionStore"; import {Store} from "./Store"; import {encodeScopeTypeKey} from "./stores/OperationStore"; import {MAX_UNICODE} from "./stores/common"; -import {LogItem} from "../../../logging/LogItem"; +import {ILogItem} from "../../../logging/LogItem"; -export type MigrationFunc = (db: IDBDatabase, txn: IDBTransaction, localStorage: IDOMStorage, log: LogItem) => Promise | void; +export type MigrationFunc = (db: IDBDatabase, txn: IDBTransaction, localStorage: IDOMStorage, log: ILogItem) => Promise | void; // FUNCTIONS SHOULD ONLY BE APPENDED!! // the index in the array is the database version export const schema: MigrationFunc[] = [ @@ -166,7 +166,7 @@ function createTimelineRelationsStore(db: IDBDatabase) : void { } //v11 doesn't change the schema, but ensures all userIdentities have all the roomIds they should (see #470) -async function fixMissingRoomsInUserIdentities(db: IDBDatabase, txn: IDBTransaction, localStorage: IDOMStorage, log: LogItem) { +async function fixMissingRoomsInUserIdentities(db: IDBDatabase, txn: IDBTransaction, localStorage: IDOMStorage, log: ILogItem) { const roomSummaryStore = txn.objectStore("roomSummary"); const trackedRoomIds: string[] = []; await iterateCursor(roomSummaryStore.openCursor(), roomSummary => { @@ -196,7 +196,7 @@ async function fixMissingRoomsInUserIdentities(db: IDBDatabase, txn: IDBTransact const updatedIdentity = addRoomToIdentity(identity, userId, roomId); if (updatedIdentity) { log.log({l: `fixing up`, id: userId, - roomsBefore: originalRoomCount, roomsAfter: updatedIdentity.roomIds.length}); + roomsBefore: originalRoomCount, roomsAfter: updatedIdentity.roomIds.length}, null); userIdentitiesStore.put(updatedIdentity); foundMissing = true; } @@ -207,7 +207,7 @@ async function fixMissingRoomsInUserIdentities(db: IDBDatabase, txn: IDBTransact // so we'll create a new one on the next message that will be properly shared outboundGroupSessionsStore.delete(roomId); } - }); + }, null, null); } } @@ -220,7 +220,7 @@ async function changeSSSSKeyPrefix(db: IDBDatabase, txn: IDBTransaction) { } } // v13 -async function backupAndRestoreE2EEAccountToLocalStorage(db: IDBDatabase, txn: IDBTransaction, localStorage: IDOMStorage, log: LogItem) { +async function backupAndRestoreE2EEAccountToLocalStorage(db: IDBDatabase, txn: IDBTransaction, localStorage: IDOMStorage, log: ILogItem) { const session = txn.objectStore("session"); // the Store object gets passed in several things through the Transaction class (a wrapper around IDBTransaction), // the only thing we should need here is the databaseName though, so we mock it out. diff --git a/src/matrix/storage/idb/stores/SessionStore.ts b/src/matrix/storage/idb/stores/SessionStore.ts index 6bf87e9b..dd133b45 100644 --- a/src/matrix/storage/idb/stores/SessionStore.ts +++ b/src/matrix/storage/idb/stores/SessionStore.ts @@ -16,7 +16,7 @@ limitations under the License. import {Store} from "../Store"; import {IDOMStorage} from "../types"; import {SESSION_E2EE_KEY_PREFIX} from "../../../e2ee/common.js"; -import {LogItem} from "../../../../logging/LogItem"; +import {ILogItem} from "../../../../logging/LogItem"; import {parse, stringify} from "../../../../utils/typedJSON"; export interface SessionEntry { @@ -64,7 +64,7 @@ export class SessionStore { }); } - async tryRestoreE2EEIdentityFromLocalStorage(log: LogItem): Promise { + async tryRestoreE2EEIdentityFromLocalStorage(log: ILogItem): Promise { let success = false; const lsPrefix = this._localStorageKeyPrefix; const prefix = lsPrefix + SESSION_E2EE_KEY_PREFIX; diff --git a/src/matrix/storage/idb/stores/TimelineEventStore.ts b/src/matrix/storage/idb/stores/TimelineEventStore.ts index 3c101701..b3663c29 100644 --- a/src/matrix/storage/idb/stores/TimelineEventStore.ts +++ b/src/matrix/storage/idb/stores/TimelineEventStore.ts @@ -20,7 +20,7 @@ import { encodeUint32, decodeUint32 } from "../utils"; import {KeyLimits} from "../../common"; import {Store} from "../Store"; import {TimelineEvent, StateEvent} from "../../types"; -import {LogItem} from "../../../../logging/LogItem"; +import {ILogItem} from "../../../../logging/LogItem"; interface Annotation { count: number; @@ -286,7 +286,7 @@ export class TimelineEventStore { * * Returns if the event was not yet known and the entry was written. */ - tryInsert(entry: TimelineEventEntry, log: LogItem): Promise { + tryInsert(entry: TimelineEventEntry, log: ILogItem): Promise { (entry as TimelineEventStorageEntry).key = encodeKey(entry.roomId, entry.fragmentId, entry.eventIndex); (entry as TimelineEventStorageEntry).eventIdKey = encodeEventIdKey(entry.roomId, entry.event.event_id); return this._timelineStore.tryAdd(entry as TimelineEventStorageEntry, log); @@ -320,7 +320,7 @@ export class TimelineEventStore { import {createMockStorage} from "../../../../mocks/Storage"; import {createEvent, withTextBody} from "../../../../mocks/event.js"; import {createEventEntry} from "../../../room/timeline/persistence/common.js"; -import {Instance as logItem} from "../../../../logging/NullLogger.js"; +import {Instance as nullLogger} from "../../../../logging/NullLogger"; export function tests() { @@ -368,7 +368,7 @@ export function tests() { let eventKey = EventKey.defaultFragmentKey(109); for (const insertedId of insertedIds) { const entry = createEventEntry(eventKey.nextKey(), roomId, createEventWithId(insertedId)); - assert(await txn.timelineEvents.tryInsert(entry, logItem)); + assert(await txn.timelineEvents.tryInsert(entry, nullLogger.item)); eventKey = eventKey.nextKey(); } const eventKeyMap = await txn.timelineEvents.getEventKeysForIds(roomId, checkedIds); diff --git a/src/mocks/Storage.ts b/src/mocks/Storage.ts index 5dba796a..a5a30ffd 100644 --- a/src/mocks/Storage.ts +++ b/src/mocks/Storage.ts @@ -18,7 +18,7 @@ import {FDBFactory, FDBKeyRange} from "../../lib/fake-indexeddb/index.js"; import {StorageFactory} from "../matrix/storage/idb/StorageFactory"; import {IDOMStorage} from "../matrix/storage/idb/types"; import {Storage} from "../matrix/storage/idb/Storage"; -import {Instance as nullLogger} from "../logging/NullLogger.js"; +import {Instance as nullLogger} from "../logging/NullLogger"; import {openDatabase, CreateObjectStore} from "../matrix/storage/idb/utils"; export function createMockStorage(): Promise {