forked from mystiq/hydrogen-web
Use interface ILogItem
This commit is contained in:
parent
a7d059b3ed
commit
520e0f1b89
23 changed files with 155 additions and 114 deletions
|
@ -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";
|
||||
|
|
|
@ -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<LogItem> = new Set();
|
||||
protected _openItems: Set<ILogItem> = 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;
|
||||
|
||||
|
|
|
@ -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") {
|
||||
|
|
|
@ -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)
|
||||
});
|
||||
|
|
|
@ -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<unknown> | null): boolean {
|
||||
filter(item: ILogItem, children: Array<unknown> | null): boolean {
|
||||
if (this._parentFilter) {
|
||||
if (!this._parentFilter.filter(item, children)) {
|
||||
return false;
|
||||
|
|
|
@ -33,6 +33,30 @@ interface ISerializedItem {
|
|||
c?: Array<ISerializedItem>;
|
||||
};
|
||||
|
||||
export interface ILogItem {
|
||||
logger: any;
|
||||
level: typeof LogLevel;
|
||||
duration?: number;
|
||||
end?: number | null;
|
||||
start?: number;
|
||||
logLevel: LogLevel;
|
||||
children: Array<ILogItem> | 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");
|
||||
}
|
||||
|
|
|
@ -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,42 +49,49 @@ export class NullLogger {
|
|||
}
|
||||
}
|
||||
|
||||
export class NullLogItem {
|
||||
constructor(logger) {
|
||||
export class NullLogItem implements ILogItem {
|
||||
public readonly logger: NullLogger;
|
||||
public readonly logLevel: LogLevel;
|
||||
public children: Array<ILogItem> | 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);
|
||||
return this;
|
||||
}
|
||||
|
||||
wrapDetached(_, callback) {
|
||||
return this.refDetached(null, callback);
|
||||
wrapDetached(_: LabelOrValues, _callback: LogCallback): void {
|
||||
return this.refDetached();
|
||||
}
|
||||
|
||||
run(callback) {
|
||||
run(callback: LogCallback): unknown {
|
||||
return callback(this);
|
||||
}
|
||||
|
||||
refDetached() {}
|
||||
refDetached(): void {}
|
||||
|
||||
ensureRefId() {}
|
||||
ensureRefId(): void {}
|
||||
|
||||
get level() {
|
||||
get level(): typeof LogLevel {
|
||||
return LogLevel;
|
||||
}
|
||||
|
||||
get duration() {
|
||||
get duration(): 0 {
|
||||
return 0;
|
||||
}
|
||||
|
||||
catch(err) {
|
||||
catch(err: Error): Error {
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -93,7 +99,11 @@ export class NullLogItem {
|
|||
return this;
|
||||
}
|
||||
|
||||
finish() {}
|
||||
finish(): void {}
|
||||
|
||||
serialize() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export const Instance = new NullLogger();
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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([]);
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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<A,B> = (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 {
|
||||
|
|
|
@ -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<Storage> {
|
||||
async create(sessionId: string, log: ILogItem): Promise<Storage> {
|
||||
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<Export> {
|
||||
async export(sessionId: string, log: ILogItem): Promise<Export> {
|
||||
const db = await openDatabaseWithSessionId(sessionId, this._idbFactory, this._localStorage, log);
|
||||
return await exportSession(db);
|
||||
}
|
||||
|
||||
async import(sessionId: string, data: Export, log: LogItem): Promise<void> {
|
||||
async import(sessionId: string, data: Export, log: ILogItem): Promise<void> {
|
||||
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<void> {
|
||||
async function createStores(db: IDBDatabase, txn: IDBTransaction, oldVersion: number | null, version: number, localStorage: IDOMStorage, log: ILogItem): Promise<void> {
|
||||
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) {
|
||||
const migrationFunc = schema[i];
|
||||
await log.wrap(`v${i + 1}`, log => migrationFunc(db, txn, localStorage, log));
|
||||
await log.wrap(`v${i + 1}`, (log) =>
|
||||
migrationFunc(db, txn, localStorage, log), null, null
|
||||
);
|
||||
}
|
||||
}) as Promise<void>;
|
||||
},
|
||||
null,
|
||||
null
|
||||
) as Promise<void>;
|
||||
}
|
||||
|
|
|
@ -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<T> extends QueryTarget<T> {
|
|||
return new QueryTarget<T>(new QueryTargetWrapper<T>(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<T> extends QueryTarget<T> {
|
|||
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<boolean> {
|
||||
async tryAdd(value: T, log: ILogItem): Promise<boolean> {
|
||||
try {
|
||||
await reqAsPromise(this._idbStore.add(value));
|
||||
return true;
|
||||
|
@ -181,13 +181,13 @@ export class Store<T> extends QueryTarget<T> {
|
|||
}
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
|
|
@ -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<void> {
|
||||
async complete(log?: ILogItem): Promise<void> {
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -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> | void;
|
||||
export type MigrationFunc = (db: IDBDatabase, txn: IDBTransaction, localStorage: IDOMStorage, log: ILogItem) => Promise<void> | 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<SummaryData>(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.
|
||||
|
|
|
@ -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<boolean> {
|
||||
async tryRestoreE2EEIdentityFromLocalStorage(log: ILogItem): Promise<boolean> {
|
||||
let success = false;
|
||||
const lsPrefix = this._localStorageKeyPrefix;
|
||||
const prefix = lsPrefix + SESSION_E2EE_KEY_PREFIX;
|
||||
|
|
|
@ -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<boolean> {
|
||||
tryInsert(entry: TimelineEventEntry, log: ILogItem): Promise<boolean> {
|
||||
(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);
|
||||
|
|
|
@ -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<Storage> {
|
||||
|
|
Loading…
Reference in a new issue