Skip to content

Commit bacd975

Browse files
Use LogWriter to write messages to logs in IndexedDbProvider
1 parent 8887bee commit bacd975

File tree

5 files changed

+188
-32
lines changed

5 files changed

+188
-32
lines changed

karma.browser.conf.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ module.exports = (config) => {
66
files: [
77
{ pattern: "dist/ObjectStoreProvider.spec.js" },
88
{ pattern: "dist/SortedBTree.spec.js" },
9+
{ pattern: "dist/LogWriter.spec.js" },
910
],
1011
customLaunchers: {
1112
FirefoxHeadless: {

src/IndexedDbProvider.ts

Lines changed: 72 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ import {
5757
TransactionToken,
5858
TransactionLockHelper,
5959
} from "./TransactionLockHelper";
60+
import { LogWriter } from "./LogWriter";
6061

6162
const IndexPrefix = "nsp_i_";
6263

@@ -80,7 +81,7 @@ export class IndexedDbProvider extends DbProvider {
8081
private _handleOnClose: OnCloseHandler | undefined = undefined;
8182

8283
private _lockHelper: TransactionLockHelper | undefined;
83-
private logger: IObjectStoreProviderLogger;
84+
private logWriter: LogWriter;
8485

8586
// By default, it uses the in-browser indexed db factory, but you can pass in an explicit factory. Currently only used for unit tests.
8687
constructor(
@@ -91,7 +92,7 @@ export class IndexedDbProvider extends DbProvider {
9192
) {
9293
super();
9394

94-
this.logger = logger ? logger : console;
95+
this.logWriter = new LogWriter(logger ? logger : console);
9596

9697
if (explicitDbFactory) {
9798
this._dbFactory = explicitDbFactory;
@@ -156,27 +157,28 @@ export class IndexedDbProvider extends DbProvider {
156157
if (!this._dbFactory) {
157158
// Couldn't even find a supported indexeddb object on the browser...
158159
const message = `No support for IndexedDB in this browser, returning`;
159-
this.logger.error(message);
160+
this.logWriter.error(message);
160161
return Promise.reject<void>(message);
161162
}
162163

163164
if (wipeIfExists) {
164-
this.logger.log(`Wiping db: ${dbName}`);
165+
this.logWriter.log(`Wiping db`, { dbName });
165166
try {
166167
let req = this._dbFactory.deleteDatabase(dbName);
167168
await IndexedDbProvider.WrapRequest(req);
168169
} catch (e: any) {
169170
// Don't care
170-
this.logger.error(
171-
`Wiping db: ${dbName} failed, message: ${e?.message}. Ignoring and proceeding further`
171+
this.logWriter.error(
172+
`Wiping db failed, message: ${e?.message}. Ignoring and proceeding further`,
173+
{ dbName }
172174
);
173175
}
174-
this.logger.log(`Wiping db: ${dbName} success`);
176+
this.logWriter.log(`Wiping db success`, { dbName });
175177
}
176178

177179
this._lockHelper = new TransactionLockHelper(schema, true);
178180

179-
this.logger.log(`Opening db: ${dbName}, version: ${schema.version}`);
181+
this.logWriter.log(`Opening db, version: ${schema.version}`, { dbName });
180182
const dbOpen = this._dbFactory.open(dbName, schema.version);
181183

182184
let migrationPutters: Promise<void>[] = [];
@@ -187,11 +189,11 @@ export class IndexedDbProvider extends DbProvider {
187189
const trans = target.transaction;
188190

189191
if (!trans) {
190-
this.logger.error(`No transaction, unable to do upgrade`);
192+
this.logWriter.error(`No transaction, unable to do upgrade`);
191193
throw new Error("onupgradeneeded: target is null!");
192194
}
193195

194-
this.logger.log(`Upgrade needed for db: ${dbName}`);
196+
this.logWriter.log(`Upgrade needed for db`, { dbName });
195197

196198
// Avoid clearing object stores when event.oldVersion returns 0.
197199
// oldVersion returns 0 if db doesn't exist yet: https://developer.mozilla.org/en-US/docs/Web/API/IDBVersionChangeEvent/oldVersion
@@ -201,8 +203,8 @@ export class IndexedDbProvider extends DbProvider {
201203
event.oldVersion < schema.lastUsableVersion
202204
) {
203205
// Clear all stores if it's past the usable version
204-
this.logger.log(
205-
"Old version detected (" + event.oldVersion + "), clearing all data"
206+
this.logWriter.log(
207+
`Old version detected (${event.oldVersion}), clearing all data`
206208
);
207209
each(db.objectStoreNames, (name) => {
208210
db.deleteObjectStore(name);
@@ -215,10 +217,12 @@ export class IndexedDbProvider extends DbProvider {
215217
db.deleteObjectStore(storeName);
216218
}
217219
});
220+
221+
this.logWriter.log(`Deleted all object stores`, { dbName });
218222
}
219223

220224
// Create all stores
221-
this.logger.log(`Creating stores as part of upgrade process`);
225+
this.logWriter.log(`Creating stores as part of upgrade process`);
222226
each(schema.stores, (storeSchema) => {
223227
let store: IDBObjectStore;
224228
const storeExistedBefore = includes(
@@ -234,6 +238,10 @@ export class IndexedDbProvider extends DbProvider {
234238
}
235239

236240
// Any is to fix a lib.d.ts issue in TS 2.0.3 - it doesn't realize that keypaths can be compound for some reason...
241+
this.logWriter.log(`Store doesn't exist, creating object store`, {
242+
dbName,
243+
storeName: storeSchema.name,
244+
});
237245
store = db.createObjectStore(storeSchema.name, {
238246
keyPath: primaryKeyPath,
239247
} as any);
@@ -273,6 +281,11 @@ export class IndexedDbProvider extends DbProvider {
273281
}
274282

275283
if (nuke) {
284+
this.logWriter.log(`Index no longer exists, deleting`, {
285+
dbName,
286+
storeName: storeSchema.name,
287+
indexName,
288+
});
276289
store.deleteIndex(indexName);
277290
}
278291
});
@@ -291,6 +304,10 @@ export class IndexedDbProvider extends DbProvider {
291304
throw new Error("Can't use multiEntry and compound keys");
292305
} else {
293306
// Create an object store for the index
307+
this.logWriter.log(`Creating object store and index`, {
308+
dbName,
309+
storeName: storeSchema.name,
310+
});
294311
let indexStore = db.createObjectStore(
295312
storeSchema.name + "_" + indexSchema.name,
296313
{ autoIncrement: true }
@@ -304,6 +321,11 @@ export class IndexedDbProvider extends DbProvider {
304321
}
305322
} else if (isCompoundKeyPath(keyPath)) {
306323
// Going to have to hack the compound index into a column, so here it is.
324+
this.logWriter.log(`Creating index`, {
325+
dbName,
326+
storeName: storeSchema.name,
327+
indexName: indexSchema.name,
328+
});
307329
store.createIndex(
308330
indexSchema.name,
309331
IndexPrefix + indexSchema.name,
@@ -312,11 +334,21 @@ export class IndexedDbProvider extends DbProvider {
312334
}
313335
);
314336
} else {
337+
this.logWriter.log(`Creating index`, {
338+
dbName,
339+
storeName: storeSchema.name,
340+
indexName: indexSchema.name,
341+
});
315342
store.createIndex(indexSchema.name, keyPath, {
316343
unique: indexSchema.unique,
317344
});
318345
}
319346
} else if (indexSchema.fullText) {
347+
this.logWriter.log(`Creating index`, {
348+
dbName,
349+
storeName: storeSchema.name,
350+
indexName: indexSchema.name,
351+
});
320352
store.createIndex(
321353
indexSchema.name,
322354
IndexPrefix + indexSchema.name,
@@ -330,6 +362,11 @@ export class IndexedDbProvider extends DbProvider {
330362
needsMigrate = true;
331363
}
332364
} else {
365+
this.logWriter.log(`Creating index`, {
366+
dbName,
367+
storeName: storeSchema.name,
368+
indexName: indexSchema.name,
369+
});
333370
store.createIndex(indexSchema.name, keyPath, {
334371
unique: indexSchema.unique,
335372
multiEntry: indexSchema.multiEntry,
@@ -351,15 +388,15 @@ export class IndexedDbProvider extends DbProvider {
351388
fakeToken,
352389
schema,
353390
this._fakeComplicatedKeys,
354-
this.logger
391+
this.logWriter
355392
);
356393
const tStore = iTrans.getStore(storeSchema.name);
357394

358395
const cursorReq = store.openCursor();
359396
let thisIndexPutters: Promise<void>[] = [];
360-
this.logger.log(
361-
`Adding store: ${storeSchema.name} to migrationPutters`
362-
);
397+
this.logWriter.log(`Adding store to migrationPutters`, {
398+
storeName: storeSchema.name,
399+
});
363400
migrationPutters.push(
364401
IndexedDbIndex.iterateOverCursorRequest(cursorReq, (cursor) => {
365402
const err = attempt(() => {
@@ -376,8 +413,9 @@ export class IndexedDbProvider extends DbProvider {
376413
}).then(
377414
() => Promise.all(thisIndexPutters).then(noop),
378415
(err) => {
379-
this.logger.error(
380-
`Error when iterating over cursor on idb index, message: ${err?.message}`
416+
this.logWriter.error(
417+
`Error when iterating over cursor on idb index, message: ${err?.message}`,
418+
{ storeName: storeSchema.name }
381419
);
382420
}
383421
)
@@ -390,11 +428,12 @@ export class IndexedDbProvider extends DbProvider {
390428

391429
return promise.then(
392430
(db) => {
393-
this.logger.log(
394-
`Waiting for migrationPutters: ${migrationPutters.length} to complete for db: ${dbName}`
431+
this.logWriter.log(
432+
`Waiting for migrationPutters: ${migrationPutters.length} to complete for db`,
433+
{ dbName }
395434
);
396435
return Promise.all(migrationPutters).then(() => {
397-
this.logger.log(`Opening db: ${dbName} success`);
436+
this.logWriter.log(`Opening db success`, { dbName });
398437
this._db = db;
399438
this._db.onclose = (event: Event) => {
400439
if (this._handleOnClose) {
@@ -435,17 +474,18 @@ export class IndexedDbProvider extends DbProvider {
435474
err.target.error.name === "VersionError"
436475
) {
437476
if (!wipeIfExists) {
438-
this.logger.log(
439-
"Database version too new, Wiping: " +
440-
(err.target.error.message || err.target.error.name)
477+
this.logWriter.log(
478+
`Database version too new, Wiping: ${
479+
err.target.error.message || err.target.error.name
480+
}`
441481
);
442482

443483
return this.open(dbName, schema, true, verbose);
444484
}
445485
}
446-
this.logger.error(
447-
`Error opening db: ${dbName}, message: ${err?.message}`
448-
);
486+
this.logWriter.error(`Error opening db, message: ${err?.message}`, {
487+
dbName,
488+
});
449489
return Promise.reject<void>(err);
450490
}
451491
);
@@ -549,7 +589,7 @@ export class IndexedDbProvider extends DbProvider {
549589
transToken,
550590
this._schema!!!,
551591
this._fakeComplicatedKeys,
552-
this.logger
592+
this.logWriter
553593
)
554594
);
555595
}
@@ -567,7 +607,7 @@ class IndexedDbTransaction implements DbTransaction {
567607
private _transToken: TransactionToken,
568608
private _schema: DbSchema,
569609
private _fakeComplicatedKeys: boolean,
570-
private logger: IObjectStoreProviderLogger
610+
private logWriter: LogWriter
571611
) {
572612
this._stores = map(this._transToken.storeNames, (storeName) =>
573613
this._trans.objectStore(storeName)
@@ -595,7 +635,7 @@ class IndexedDbTransaction implements DbTransaction {
595635
);
596636

597637
if (history.length > 1) {
598-
this.logger.warn(
638+
this.logWriter.warn(
599639
"IndexedDbTransaction Errored after Resolution, Swallowing. Error: " +
600640
(this._trans.error ? this._trans.error.message : undefined) +
601641
", History: " +
@@ -619,7 +659,7 @@ class IndexedDbTransaction implements DbTransaction {
619659
);
620660

621661
if (history.length > 1) {
622-
this.logger.warn(
662+
this.logWriter.warn(
623663
"IndexedDbTransaction Aborted after Resolution, Swallowing. Error: " +
624664
(this._trans.error ? this._trans.error.message : undefined) +
625665
", History: " +

src/LogWriter.ts

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import { IObjectStoreProviderLogger } from "./ObjectStoreProvider";
2+
3+
export interface ILoggerContext {
4+
dbName?: string;
5+
storeName?: string;
6+
indexName?: string;
7+
}
8+
9+
export class LogWriter {
10+
constructor(public logger: IObjectStoreProviderLogger) {}
11+
12+
public log(message: string, context?: ILoggerContext) {
13+
const messageToWrite = this.computeMessageToWrite(message, context);
14+
this.logger.log(messageToWrite);
15+
}
16+
17+
public error(message: string, context?: ILoggerContext) {
18+
const messageToWrite = this.computeMessageToWrite(message, context);
19+
this.logger.error(messageToWrite);
20+
}
21+
22+
public warn(message: string, context?: ILoggerContext) {
23+
const messageToWrite = this.computeMessageToWrite(message, context);
24+
this.logger.warn(messageToWrite);
25+
}
26+
27+
private computeMessageToWrite(message: string, context?: ILoggerContext) {
28+
let contextMessages: string[] = [];
29+
if (context) {
30+
for (const key in context) {
31+
const value = context[key as keyof ILoggerContext];
32+
if (!value) {
33+
continue;
34+
}
35+
contextMessages.push(`${key}: ${value}`);
36+
}
37+
}
38+
if (!contextMessages.length) {
39+
return message;
40+
}
41+
return `${message}. ${contextMessages.join(", ")}`;
42+
}
43+
}

0 commit comments

Comments
 (0)