Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(core/biblio-db): Move from indexedDB to idb #2228

Merged
merged 21 commits into from
Aug 3, 2019
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
176 changes: 45 additions & 131 deletions src/core/biblio-db.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,63 +8,27 @@
*
*/
import { flatten } from "./utils.js";
import { importIdb } from "./idb.js";
import { pub } from "./pubsubhub.js";
export const name = "core/biblio-db";

const ALLOWED_TYPES = new Set(["alias", "reference"]);
/**
* Database initialization tracker
* @type {Promise<IDBDatabase>}
*/
const readyPromise = new Promise((resolve, reject) => {
let request;
try {
request = window.indexedDB.open("respec-biblio2", 12);
} catch (err) {
return reject(err);
}
request.onerror = () => {
reject(new DOMException(request.error.message, request.error.name));
};
request.onsuccess = () => {
resolve(request.result);
};
request.onupgradeneeded = async () => {
const db = request.result;
Array.from(db.objectStoreNames).map(storeName =>
db.deleteObjectStore(storeName)
);
const promisesToCreateSchema = [
new Promise((resolve, reject) => {
try {
const store = db.createObjectStore("alias", { keyPath: "id" });
store.createIndex("aliasOf", "aliasOf", { unique: false });
store.transaction.oncomplete = resolve;
store.transaction.onerror = reject;
} catch (err) {
reject(err);
}
}),
new Promise((resolve, reject) => {
try {
const transaction = db.createObjectStore("reference", {
keyPath: "id",
}).transaction;
transaction.oncomplete = resolve;
transaction.onerror = reject;
} catch (err) {
reject(err);
}
}),
];
try {
await Promise.all(promisesToCreateSchema);
resolve();
} catch (err) {
reject(err);
}
};
});
/* Database initialization tracker */
const readyPromise = openIdb();

async function openIdb() {
const { openDB } = await importIdb();
return await openDB("respec-biblio2", 12, {
upgrade(db) {
Array.from(db.objectStoreNames).map(storeName =>
db.deleteObjectStore(storeName)
);
const store = db.createObjectStore("alias", { keyPath: "id" });
store.createIndex("aliasOf", "aliasOf", { unique: false });
db.createObjectStore("reference", { keyPath: "id" });
},
});
}

export const biblioDB = {
get ready() {
Expand All @@ -81,7 +45,7 @@ export const biblioDB = {
if (await this.isAlias(id)) {
id = await this.resolveAlias(id);
}
return this.get("reference", id);
return await this.get("reference", id);
marcoscaceres marked this conversation as resolved.
Show resolved Hide resolved
},
/**
* Checks if the database has an id for a given type.
Expand All @@ -98,17 +62,10 @@ export const biblioDB = {
throw new TypeError("id is required");
}
const db = await this.ready;
return new Promise((resolve, reject) => {
const objectStore = db.transaction([type], "readonly").objectStore(type);
const range = IDBKeyRange.only(id);
const request = objectStore.openCursor(range);
request.onsuccess = () => {
resolve(!!request.result);
};
request.onerror = () => {
reject(new DOMException(request.error.message, request.error.name));
};
});
const objectStore = db.transaction([type], "readonly").objectStore(type);
const range = IDBKeyRange.only(id);
const result = await objectStore.openCursor(range);
return !!result;
},
/**
* Checks if a given id is an alias.
Expand All @@ -121,19 +78,12 @@ export const biblioDB = {
throw new TypeError("id is required");
}
const db = await this.ready;
return new Promise((resolve, reject) => {
const objectStore = db
.transaction(["alias"], "readonly")
.objectStore("alias");
const range = IDBKeyRange.only(id);
const request = objectStore.openCursor(range);
request.onsuccess = () => {
resolve(!!request.result);
};
request.onerror = () => {
reject(new DOMException(request.error.message, request.error.name));
};
});
const objectStore = db
.transaction(["alias"], "readonly")
.objectStore("alias");
const range = IDBKeyRange.only(id);
const result = await objectStore.openCursor(range);
return !!result;
},
/**
* Resolves an alias to its corresponding reference id.
Expand All @@ -146,22 +96,13 @@ export const biblioDB = {
throw new TypeError("id is required");
}
const db = await this.ready;
return new Promise((resolve, reject) => {
const objectStore = db
.transaction("alias", "readonly")
.objectStore("alias");
const range = IDBKeyRange.only(id);
const request = objectStore.openCursor(range);
request.onsuccess = () => {
if (request.result === null) {
return resolve(null);
}
resolve(request.result.value.aliasOf);
};
request.onerror = () => {
reject(new DOMException(request.error.message, request.error.name));
};
});

const objectStore = db
.transaction("alias", "readonly")
.objectStore("alias");
const range = IDBKeyRange.only(id);
const result = await objectStore.openCursor(range);
return result ? result.value.aliasOf : result;
},
/**
* Get a reference or alias out of the database.
Expand All @@ -178,20 +119,10 @@ export const biblioDB = {
throw new TypeError("id is required");
}
const db = await this.ready;
return new Promise((resolve, reject) => {
const objectStore = db.transaction([type], "readonly").objectStore(type);
const range = IDBKeyRange.only(id);
const request = objectStore.openCursor(range);
request.onsuccess = () => {
if (request.result === null) {
return resolve(null);
}
resolve(request.result.value);
};
request.onerror = () => {
reject(new DOMException(request.error.message, request.error.name));
};
});
const objectStore = db.transaction([type], "readonly").objectStore(type);
const range = IDBKeyRange.only(id);
const result = await objectStore.openCursor(range);
return result ? result.value : result;
},
/**
* Adds references and aliases to database. This is usually the data from
Expand Down Expand Up @@ -253,15 +184,9 @@ export const biblioDB = {
}
const db = await this.ready;
const isInDB = await this.has(type, details.id);
return new Promise((resolve, reject) => {
const store = db.transaction([type], "readwrite").objectStore(type);
// update or add, depending of already having it in db
const request = isInDB ? store.put(details) : store.add(details);
request.onsuccess = resolve;
request.onerror = () => {
reject(new DOMException(request.error.message, request.error.name));
};
});
const store = db.transaction([type], "readwrite").objectStore(type);
// update or add, depending of already having it in db
return isInDB ? await store.put(details) : await store.add(details);
},
/**
* Closes the underlying database.
Expand All @@ -279,21 +204,10 @@ export const biblioDB = {
async clear() {
const db = await this.ready;
const storeNames = [...ALLOWED_TYPES];
const stores = await new Promise((resolve, reject) => {
const transaction = db.transaction(storeNames, "readwrite");
transaction.onerror = () => {
reject(
new DOMException(transaction.error.message, transaction.error.name)
);
};
resolve(transaction);
});
const stores = await db.transaction(storeNames, "readwrite");
const clearStorePromises = storeNames.map(name => {
return new Promise(resolve => {
const request = stores.objectStore(name).clear();
request.onsuccess = resolve;
});
return stores.objectStore(name).clear();
});
Promise.all(clearStorePromises);
await Promise.all(clearStorePromises);
},
};
10 changes: 10 additions & 0 deletions src/core/idb.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/**
* Temporary workaround until browsers get import-maps
*/
export async function importIdb() {
try {
return await import("idb");
} catch {
return await import("../../node_modules/idb/build/esm/index.js");
}
}
12 changes: 1 addition & 11 deletions src/core/xref-db.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// @ts-check
import { IDBKeyVal } from "./utils.js";
import { importIdb } from "./idb.js";

/**
* @typedef {import('core/xref').RequestEntry} RequestEntry
Expand All @@ -9,17 +10,6 @@ import { IDBKeyVal } from "./utils.js";

const CACHE_MAX_AGE = 86400000; // 24 hours

/**
* Temporary workaround until browsers get import-maps
*/
async function importIdb() {
try {
return await import("idb");
} catch {
return await import("../../node_modules/idb/build/esm/index.js");
}
}

async function getIdbCache() {
const { openDB } = await importIdb();
const idb = await openDB("xref", 1, {
Expand Down