Use interface ILogItem

This commit is contained in:
RMidhunSuresh 2021-11-15 17:29:08 +05:30
parent a7d059b3ed
commit 520e0f1b89
23 changed files with 155 additions and 114 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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 => {
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<void>;
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<void>;
}

View file

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

View file

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

View file

@ -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.

View file

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

View file

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

View file

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