Add another store to keep last modified times

This makes it easier to get a list of all the log IDs. It also makes it possible
to order the logs by the *LAST* log line and not the first as was the case
previously, which is important in the case of long-running tabs.
This commit is contained in:
Kegan Dougal 2017-01-20 14:00:30 +00:00
parent 41c6294be2
commit 378126e746

View File

@ -96,7 +96,7 @@ class IndexedDBLogStore {
constructor(indexedDB, logger) { constructor(indexedDB, logger) {
this.indexedDB = indexedDB; this.indexedDB = indexedDB;
this.logger = logger; this.logger = logger;
this.id = "instance-" + Date.now(); this.id = "instance-" + Math.random() + Date.now();
this.index = 0; this.index = 0;
this.db = null; this.db = null;
} }
@ -125,22 +125,24 @@ class IndexedDBLogStore {
// First time: Setup the object store // First time: Setup the object store
req.onupgradeneeded = (event) => { req.onupgradeneeded = (event) => {
const db = event.target.result; const db = event.target.result;
const objectStore = db.createObjectStore("logs", { const logObjStore = db.createObjectStore("logs", {
keyPath: ["id", "index"] keyPath: ["id", "index"]
}); });
// Keys in the database look like: [ "instance-148938490", 0 ] // Keys in the database look like: [ "instance-148938490", 0 ]
// Later on we need to query for everything with index=0, and // Later on we need to query everything based on an instance id.
// query everything for an instance id. // In order to do this, we need to set up indexes "id".
// In order to do this, we need to set up indexes on both "id" logObjStore.createIndex("id", "id", { unique: false });
// and "index".
objectStore.createIndex("index", "index", { unique: false });
objectStore.createIndex("id", "id", { unique: false });
objectStore.add( logObjStore.add(
this._generateLogEntry( this._generateLogEntry(
new Date() + " ::: Log database was created." new Date() + " ::: Log database was created."
) )
); );
const lastModifiedStore = db.createObjectStore("logslastmod", {
keyPath: "id",
});
lastModifiedStore.add(this._generateLastModifiedTime());
} }
}); });
} }
@ -158,15 +160,17 @@ class IndexedDBLogStore {
return Promise.resolve(); return Promise.resolve();
} }
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
let txn = this.db.transaction("logs", "readwrite"); let txn = this.db.transaction(["logs", "logslastmod"], "readwrite");
let objStore = txn.objectStore("logs"); let objStore = txn.objectStore("logs");
objStore.add(this._generateLogEntry(lines)); objStore.add(this._generateLogEntry(lines));
let lastModStore = txn.objectStore("logslastmod");
lastModStore.put(this._generateLastModifiedTime());
txn.oncomplete = (event) => { txn.oncomplete = (event) => {
resolve(); resolve();
}; };
txn.onerror = (event) => { txn.onerror = (event) => {
console.error( console.error(
"Failed to flush logs : " + event.target.errorCode "Failed to flush logs : ", event
); );
reject( reject(
new Error("Failed to write logs: " + event.target.errorCode) new Error("Failed to write logs: " + event.target.errorCode)
@ -210,25 +214,28 @@ class IndexedDBLogStore {
// Returns: A sorted array of log IDs. (newest first) // Returns: A sorted array of log IDs. (newest first)
function fetchLogIds() { function fetchLogIds() {
// To gather all the log IDs, query for every log entry with index // To gather all the log IDs, query for all records in logslastmod.
// "0", this will let us know all the IDs from different const o = db.transaction("logslastmod", "readonly").objectStore(
// tabs/sessions. "logslastmod"
const o = db.transaction("logs", "readonly").objectStore("logs"); );
return selectQuery(o.index("index"), IDBKeyRange.only(0), return selectQuery(o, undefined, (cursor) => {
(cursor) => cursor.value.id).then((res) => { return {
// we know each entry has a unique ID, and we know IDs are id: cursor.value.id,
// timestamps, so accumulate all the IDs, ignoring the logs for ts: cursor.value.ts,
// now, and sort them to work out the correct log ID ordering, };
// newest first. }).then((res) => {
// E.g. [ "instance-1484827160051", "instance-1374827160051", // Sort IDs by timestamp (newest first)
// "instance-1000007160051"] return res.sort((a, b) => {
return res.sort().reverse(); return b.ts - a.ts;
}).map((a) => a.id);
}); });
} }
function deleteLogs(id) { function deleteLogs(id) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const txn = db.transaction("logs", "readwrite"); const txn = db.transaction(
["logs", "logslastmod"], "readwrite"
);
const o = txn.objectStore("logs"); const o = txn.objectStore("logs");
// only load the key path, not the data which may be huge // only load the key path, not the data which may be huge
const query = o.index("id").openKeyCursor(IDBKeyRange.only(id)); const query = o.index("id").openKeyCursor(IDBKeyRange.only(id));
@ -250,7 +257,10 @@ class IndexedDBLogStore {
`'${id}' : ${event.target.errorCode}` `'${id}' : ${event.target.errorCode}`
) )
); );
} };
// delete last modified entries
const lastModStore = txn.objectStore("logslastmod");
lastModStore.delete(id);
}); });
} }
@ -292,6 +302,13 @@ class IndexedDBLogStore {
index: this.index++ index: this.index++
}; };
} }
_generateLastModifiedTime() {
return {
id: this.id,
ts: Date.now(),
};
}
} }
/** /**