Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@ export {
OnCloseHandler,
openListOfProviders,
IObjectStoreProviderLogger,
UpgradeStatus,
StoreUpgradeStep,
UpgradeStep,
UpgradeMetadata,
UpgradeDetails,
UpgradeCallback,
} from "./src/ObjectStoreProvider";
export {
isIE,
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.7.1",
"version": "0.7.2",
"description": "A cross-browser object store library",
"author": "Mukundan Kavanur Kidambi <mukav@microsoft.com>",
"scripts": {
Expand Down
88 changes: 87 additions & 1 deletion src/IndexedDbProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ import {
IDBCloseConnectionPayload,
OnCloseHandler,
IObjectStoreProviderLogger,
UpgradeCallback,
UpgradeStep,
UpgradeMetadata,
} from "./ObjectStoreProvider";
import { ItemType, KeyPathType, KeyType } from "./ObjectStoreProvider";
import {
Expand Down Expand Up @@ -79,6 +82,7 @@ export class IndexedDbProvider extends DbProvider {
private _dbFactory: IDBFactory;
private _fakeComplicatedKeys: boolean;
private _handleOnClose: OnCloseHandler | undefined = undefined;
private _upgradeCallback: UpgradeCallback | undefined = undefined;

private _lockHelper: TransactionLockHelper | undefined;
private logWriter: LogWriter;
Expand All @@ -88,7 +92,8 @@ export class IndexedDbProvider extends DbProvider {
explicitDbFactory?: IDBFactory,
explicitDbFactorySupportsCompoundKeys?: boolean,
handleOnClose?: OnCloseHandler,
logger?: IObjectStoreProviderLogger
logger?: IObjectStoreProviderLogger,
upgradeCallback?: UpgradeCallback
) {
super();

Expand Down Expand Up @@ -118,6 +123,10 @@ export class IndexedDbProvider extends DbProvider {
if (handleOnClose) {
this._handleOnClose = handleOnClose;
}

if (upgradeCallback) {
this._upgradeCallback = upgradeCallback;
}
}

/**
Expand Down Expand Up @@ -181,8 +190,22 @@ export class IndexedDbProvider extends DbProvider {
const dbOpen = this._dbFactory.open(dbName, schema.version);

let migrationPutters: Promise<void>[] = [];
const upgradeSteps: UpgradeStep[] = [];
let upgradeMetadata: UpgradeMetadata = {
oldVersion: 0,
newVersion: 0,
upgradeStartTimePerformanceMarker: 0,
upgradeScenarioStartTime: 0,
};

dbOpen.onupgradeneeded = (event) => {
upgradeMetadata = {
oldVersion: event.oldVersion,
newVersion: schema.version,
upgradeScenarioStartTime: Date.now(),
upgradeStartTimePerformanceMarker: performance.now(),
};

const db: IDBDatabase = dbOpen.result;
const target = <IDBOpenDBRequest>(event.currentTarget || event.target);
const trans = target.transaction;
Expand All @@ -208,13 +231,23 @@ export class IndexedDbProvider extends DbProvider {
);
each(db.objectStoreNames, (name) => {
db.deleteObjectStore(name);
upgradeSteps.push({
step: "DeleteOldVersion",
storeName: name,
timestamp: performance.now(),
});
});
}

// Delete dead stores
each(db.objectStoreNames, (storeName) => {
if (!some(schema.stores, (store) => store.name === storeName)) {
db.deleteObjectStore(storeName);
upgradeSteps.push({
step: "DeleteDeadStores",
storeName,
timestamp: performance.now(),
});
}
});

Expand Down Expand Up @@ -245,6 +278,13 @@ export class IndexedDbProvider extends DbProvider {
store = db.createObjectStore(storeSchema.name, {
keyPath: primaryKeyPath,
} as any);

upgradeSteps.push({
step: "CreatingIndex",
storeName: storeSchema.name,
storeExistedBefore: false,
timestamp: performance.now(),
});
} else {
// store exists, might need to update indexes and migrate the data
store = trans.objectStore(storeSchema.name);
Expand Down Expand Up @@ -286,6 +326,12 @@ export class IndexedDbProvider extends DbProvider {
storeName: storeSchema.name,
indexName,
});
upgradeSteps.push({
step: "DeletingIndex",
storeName: storeSchema.name,
indexName,
timestamp: performance.now(),
});
store.deleteIndex(indexName);
}
});
Expand All @@ -296,6 +342,12 @@ export class IndexedDbProvider extends DbProvider {
let needsMigrate = false;
// Check any indexes in the schema that need to be created
each(storeSchema.indexes, (indexSchema) => {
upgradeSteps.push({
step: "CreatingIndex",
storeName: storeSchema.name,
indexName: indexSchema.name,
timestamp: performance.now(),
});
if (!includes(store.indexNames, indexSchema.name)) {
const keyPath = indexSchema.keyPath;
if (this._fakeComplicatedKeys) {
Expand Down Expand Up @@ -380,6 +432,12 @@ export class IndexedDbProvider extends DbProvider {
});

if (needsMigrate) {
upgradeSteps.push({
step: "CopyingData",
timestamp: performance.now(),
storeName: storeSchema.name,
});

// Walk every element in the store and re-put it to fill out the new index.
const fakeToken: TransactionToken = {
storeNames: [storeSchema.name],
Expand Down Expand Up @@ -444,6 +502,20 @@ export class IndexedDbProvider extends DbProvider {
if (isActualMigration) {
this.logWriter.log(`Opening db success`, { dbName });
}

if (this._upgradeCallback && upgradeSteps.length > 0) {
upgradeSteps.push({
step: "DBUpgradeComplete",
timestamp: performance.now(),
});
this._upgradeCallback({
status: "Success",
isCopyRequired: isActualMigration,
upgradeSteps,
...upgradeMetadata,
});
}

this._db = db;
this._db.onclose = (event: Event) => {
if (this._handleOnClose) {
Expand Down Expand Up @@ -499,6 +571,20 @@ export class IndexedDbProvider extends DbProvider {
dbName,
}
);

// Invoke the upgradeCallback with error details
if (this._upgradeCallback) {
this._upgradeCallback({
status: "Error",
isCopyRequired: false,
upgradeSteps,
...upgradeMetadata,
errorMessage: err
? `${err?.message} ${err?.target?.error} ${err?.target?.error?.name}`
: "Unknown error occurred during upgrade",
});
}

return Promise.reject<void>(err);
}
);
Expand Down
33 changes: 33 additions & 0 deletions src/ObjectStoreProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,39 @@ export type DBClosure = "unexpectedClosure" | "expectedClosure";

export type OnCloseHandler = (payload: IDBCloseConnectionPayload) => void;

export type UpgradeStatus = "Success" | "Error";
export type StoreUpgradeStep =
| "DeleteOldVersion"
| "DeleteDeadStores"
| "DeletingIndex"
| "CreatingIndex"
| "CopyingData"
| "DBUpgradeComplete";

export type UpgradeStep = {
timestamp: number;
step: StoreUpgradeStep;
storeName?: string;
storeExistedBefore?: boolean;
indexName?: string;
};

export type UpgradeMetadata = {
oldVersion: number;
newVersion: number;
upgradeScenarioStartTime: number;
upgradeStartTimePerformanceMarker: number;
};

export type UpgradeDetails = UpgradeMetadata & {
status: UpgradeStatus;
upgradeSteps: UpgradeStep[];
isCopyRequired: boolean;
errorMessage?: string;
};

export type UpgradeCallback = (upgradeDetails: UpgradeDetails) => void;

// Interface type describing an index being opened for querying.
export interface DbIndex {
getAll(
Expand Down
Loading
Loading