Skip to content

Commit

Permalink
Merge pull request #54 from microsoft/bviswanathan/db_open_log
Browse files Browse the repository at this point in the history
Add log statements to IndexedDbProvider open
  • Loading branch information
M1Les authored Oct 9, 2023
2 parents 2735dda + bacd975 commit c7cc245
Show file tree
Hide file tree
Showing 6 changed files with 201 additions and 16 deletions.
1 change: 1 addition & 0 deletions karma.browser.conf.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ module.exports = (config) => {
files: [
{ pattern: "dist/ObjectStoreProvider.spec.js" },
{ pattern: "dist/SortedBTree.spec.js" },
{ pattern: "dist/LogWriter.spec.js" },
],
customLaunchers: {
FirefoxHeadless: {
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@microsoft/objectstoreprovider",
"version": "0.6.42",
"version": "0.6.43",
"description": "A cross-browser object store library",
"author": "Mukundan Kavanur Kidambi <[email protected]>",
"scripts": {
Expand Down
99 changes: 84 additions & 15 deletions src/IndexedDbProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ import {
TransactionToken,
TransactionLockHelper,
} from "./TransactionLockHelper";
import { LogWriter } from "./LogWriter";

const IndexPrefix = "nsp_i_";

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

private _lockHelper: TransactionLockHelper | undefined;
private logger: IObjectStoreProviderLogger;
private logWriter: LogWriter;

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

this.logger = logger ? logger : console;
this.logWriter = new LogWriter(logger ? logger : console);

if (explicitDbFactory) {
this._dbFactory = explicitDbFactory;
Expand Down Expand Up @@ -155,20 +156,29 @@ export class IndexedDbProvider extends DbProvider {

if (!this._dbFactory) {
// Couldn't even find a supported indexeddb object on the browser...
return Promise.reject<void>("No support for IndexedDB in this browser");
const message = `No support for IndexedDB in this browser, returning`;
this.logWriter.error(message);
return Promise.reject<void>(message);
}

if (wipeIfExists) {
this.logWriter.log(`Wiping db`, { dbName });
try {
let req = this._dbFactory.deleteDatabase(dbName);
await IndexedDbProvider.WrapRequest(req);
} catch (e) {
} catch (e: any) {
// Don't care
this.logWriter.error(
`Wiping db failed, message: ${e?.message}. Ignoring and proceeding further`,
{ dbName }
);
}
this.logWriter.log(`Wiping db success`, { dbName });
}

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

this.logWriter.log(`Opening db, version: ${schema.version}`, { dbName });
const dbOpen = this._dbFactory.open(dbName, schema.version);

let migrationPutters: Promise<void>[] = [];
Expand All @@ -179,9 +189,12 @@ export class IndexedDbProvider extends DbProvider {
const trans = target.transaction;

if (!trans) {
this.logWriter.error(`No transaction, unable to do upgrade`);
throw new Error("onupgradeneeded: target is null!");
}

this.logWriter.log(`Upgrade needed for db`, { dbName });

// Avoid clearing object stores when event.oldVersion returns 0.
// oldVersion returns 0 if db doesn't exist yet: https://developer.mozilla.org/en-US/docs/Web/API/IDBVersionChangeEvent/oldVersion
if (event.oldVersion) {
Expand All @@ -190,8 +203,8 @@ export class IndexedDbProvider extends DbProvider {
event.oldVersion < schema.lastUsableVersion
) {
// Clear all stores if it's past the usable version
this.logger.log(
"Old version detected (" + event.oldVersion + "), clearing all data"
this.logWriter.log(
`Old version detected (${event.oldVersion}), clearing all data`
);
each(db.objectStoreNames, (name) => {
db.deleteObjectStore(name);
Expand All @@ -204,9 +217,12 @@ export class IndexedDbProvider extends DbProvider {
db.deleteObjectStore(storeName);
}
});

this.logWriter.log(`Deleted all object stores`, { dbName });
}

// Create all stores
this.logWriter.log(`Creating stores as part of upgrade process`);
each(schema.stores, (storeSchema) => {
let store: IDBObjectStore;
const storeExistedBefore = includes(
Expand All @@ -222,6 +238,10 @@ export class IndexedDbProvider extends DbProvider {
}

// 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...
this.logWriter.log(`Store doesn't exist, creating object store`, {
dbName,
storeName: storeSchema.name,
});
store = db.createObjectStore(storeSchema.name, {
keyPath: primaryKeyPath,
} as any);
Expand Down Expand Up @@ -261,6 +281,11 @@ export class IndexedDbProvider extends DbProvider {
}

if (nuke) {
this.logWriter.log(`Index no longer exists, deleting`, {
dbName,
storeName: storeSchema.name,
indexName,
});
store.deleteIndex(indexName);
}
});
Expand All @@ -279,6 +304,10 @@ export class IndexedDbProvider extends DbProvider {
throw new Error("Can't use multiEntry and compound keys");
} else {
// Create an object store for the index
this.logWriter.log(`Creating object store and index`, {
dbName,
storeName: storeSchema.name,
});
let indexStore = db.createObjectStore(
storeSchema.name + "_" + indexSchema.name,
{ autoIncrement: true }
Expand All @@ -292,6 +321,11 @@ export class IndexedDbProvider extends DbProvider {
}
} else if (isCompoundKeyPath(keyPath)) {
// Going to have to hack the compound index into a column, so here it is.
this.logWriter.log(`Creating index`, {
dbName,
storeName: storeSchema.name,
indexName: indexSchema.name,
});
store.createIndex(
indexSchema.name,
IndexPrefix + indexSchema.name,
Expand All @@ -300,11 +334,21 @@ export class IndexedDbProvider extends DbProvider {
}
);
} else {
this.logWriter.log(`Creating index`, {
dbName,
storeName: storeSchema.name,
indexName: indexSchema.name,
});
store.createIndex(indexSchema.name, keyPath, {
unique: indexSchema.unique,
});
}
} else if (indexSchema.fullText) {
this.logWriter.log(`Creating index`, {
dbName,
storeName: storeSchema.name,
indexName: indexSchema.name,
});
store.createIndex(
indexSchema.name,
IndexPrefix + indexSchema.name,
Expand All @@ -318,6 +362,11 @@ export class IndexedDbProvider extends DbProvider {
needsMigrate = true;
}
} else {
this.logWriter.log(`Creating index`, {
dbName,
storeName: storeSchema.name,
indexName: indexSchema.name,
});
store.createIndex(indexSchema.name, keyPath, {
unique: indexSchema.unique,
multiEntry: indexSchema.multiEntry,
Expand All @@ -339,12 +388,15 @@ export class IndexedDbProvider extends DbProvider {
fakeToken,
schema,
this._fakeComplicatedKeys,
this.logger
this.logWriter
);
const tStore = iTrans.getStore(storeSchema.name);

const cursorReq = store.openCursor();
let thisIndexPutters: Promise<void>[] = [];
this.logWriter.log(`Adding store to migrationPutters`, {
storeName: storeSchema.name,
});
migrationPutters.push(
IndexedDbIndex.iterateOverCursorRequest(cursorReq, (cursor) => {
const err = attempt(() => {
Expand All @@ -358,7 +410,15 @@ export class IndexedDbProvider extends DbProvider {
if (err) {
thisIndexPutters.push(Promise.reject<void>(err));
}
}).then(() => Promise.all(thisIndexPutters).then(noop))
}).then(
() => Promise.all(thisIndexPutters).then(noop),
(err) => {
this.logWriter.error(
`Error when iterating over cursor on idb index, message: ${err?.message}`,
{ storeName: storeSchema.name }
);
}
)
);
}
});
Expand All @@ -368,7 +428,12 @@ export class IndexedDbProvider extends DbProvider {

return promise.then(
(db) => {
this.logWriter.log(
`Waiting for migrationPutters: ${migrationPutters.length} to complete for db`,
{ dbName }
);
return Promise.all(migrationPutters).then(() => {
this.logWriter.log(`Opening db success`, { dbName });
this._db = db;
this._db.onclose = (event: Event) => {
if (this._handleOnClose) {
Expand Down Expand Up @@ -409,14 +474,18 @@ export class IndexedDbProvider extends DbProvider {
err.target.error.name === "VersionError"
) {
if (!wipeIfExists) {
this.logger.log(
"Database version too new, Wiping: " +
(err.target.error.message || err.target.error.name)
this.logWriter.log(
`Database version too new, Wiping: ${
err.target.error.message || err.target.error.name
}`
);

return this.open(dbName, schema, true, verbose);
}
}
this.logWriter.error(`Error opening db, message: ${err?.message}`, {
dbName,
});
return Promise.reject<void>(err);
}
);
Expand Down Expand Up @@ -520,7 +589,7 @@ export class IndexedDbProvider extends DbProvider {
transToken,
this._schema!!!,
this._fakeComplicatedKeys,
this.logger
this.logWriter
)
);
}
Expand All @@ -538,7 +607,7 @@ class IndexedDbTransaction implements DbTransaction {
private _transToken: TransactionToken,
private _schema: DbSchema,
private _fakeComplicatedKeys: boolean,
private logger: IObjectStoreProviderLogger
private logWriter: LogWriter
) {
this._stores = map(this._transToken.storeNames, (storeName) =>
this._trans.objectStore(storeName)
Expand Down Expand Up @@ -566,7 +635,7 @@ class IndexedDbTransaction implements DbTransaction {
);

if (history.length > 1) {
this.logger.warn(
this.logWriter.warn(
"IndexedDbTransaction Errored after Resolution, Swallowing. Error: " +
(this._trans.error ? this._trans.error.message : undefined) +
", History: " +
Expand All @@ -590,7 +659,7 @@ class IndexedDbTransaction implements DbTransaction {
);

if (history.length > 1) {
this.logger.warn(
this.logWriter.warn(
"IndexedDbTransaction Aborted after Resolution, Swallowing. Error: " +
(this._trans.error ? this._trans.error.message : undefined) +
", History: " +
Expand Down
43 changes: 43 additions & 0 deletions src/LogWriter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { IObjectStoreProviderLogger } from "./ObjectStoreProvider";

export interface ILoggerContext {
dbName?: string;
storeName?: string;
indexName?: string;
}

export class LogWriter {
constructor(public logger: IObjectStoreProviderLogger) {}

public log(message: string, context?: ILoggerContext) {
const messageToWrite = this.computeMessageToWrite(message, context);
this.logger.log(messageToWrite);
}

public error(message: string, context?: ILoggerContext) {
const messageToWrite = this.computeMessageToWrite(message, context);
this.logger.error(messageToWrite);
}

public warn(message: string, context?: ILoggerContext) {
const messageToWrite = this.computeMessageToWrite(message, context);
this.logger.warn(messageToWrite);
}

private computeMessageToWrite(message: string, context?: ILoggerContext) {
let contextMessages: string[] = [];
if (context) {
for (const key in context) {
const value = context[key as keyof ILoggerContext];
if (!value) {
continue;
}
contextMessages.push(`${key}: ${value}`);
}
}
if (!contextMessages.length) {
return message;
}
return `${message}. ${contextMessages.join(", ")}`;
}
}
Loading

0 comments on commit c7cc245

Please sign in to comment.