Swap to async/await rather than promise chains
Since we do in fact support coroutines!
This commit is contained in:
parent
81d437ac1e
commit
bf887e82fe
|
@ -166,7 +166,7 @@ class IndexedDBLogStore {
|
||||||
* when the log file was created (the log ID). The objects have said log ID in an "id" field and "lines" which is a
|
* when the log file was created (the log ID). The objects have said log ID in an "id" field and "lines" which is a
|
||||||
* big string with all the new-line delimited logs.
|
* big string with all the new-line delimited logs.
|
||||||
*/
|
*/
|
||||||
consume(clearAll) {
|
async consume(clearAll) {
|
||||||
const MAX_LOG_SIZE = 1024 * 1024 * 50; // 50 MB
|
const MAX_LOG_SIZE = 1024 * 1024 * 50; // 50 MB
|
||||||
const db = this.db;
|
const db = this.db;
|
||||||
|
|
||||||
|
@ -223,65 +223,36 @@ class IndexedDBLogStore {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ideally we'd just use coroutines and a for loop but riot-web doesn't support async/await so instead
|
let allLogIds = await fetchLogIds();
|
||||||
// recursively fetch logs up to the given threshold. We can't cheat and fetch all the logs
|
let removeLogIds = [];
|
||||||
// from all time, but we may OOM if we do so.
|
let logs = [];
|
||||||
// Returns: Promise<Object[]> : Each object having 'id' and 'lines'. Same ordering as logIds.
|
let size = 0;
|
||||||
function fetchLogsToThreshold(logIds, threshold, logs) {
|
for (let i = 0; i < allLogIds.length; i++) {
|
||||||
// Base case: check log size and return if bigger than threshold
|
let lines = await fetchLogs(allLogIds[i]);
|
||||||
let size = 0;
|
logs.push({
|
||||||
logs.forEach((l) => {
|
lines: lines,
|
||||||
size += l.lines.length;
|
id: allLogIds[i],
|
||||||
});
|
});
|
||||||
if (size > threshold) {
|
size += lines.length;
|
||||||
return Promise.resolve(logs);
|
if (size > MAX_LOG_SIZE) {
|
||||||
|
// the remaining log IDs should be removed. If we go out of bounds this is just []
|
||||||
|
removeLogIds = allLogIds.slice(i + 1);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// fetch logs for the first element
|
|
||||||
let logId = logIds.shift();
|
|
||||||
if (!logId) {
|
|
||||||
// no more entries
|
|
||||||
return Promise.resolve(logs);
|
|
||||||
}
|
|
||||||
return fetchLogs(logId).then((lines) => {
|
|
||||||
// add result to logs
|
|
||||||
logs.push({
|
|
||||||
lines: lines,
|
|
||||||
id: logId,
|
|
||||||
});
|
|
||||||
// recurse with the next log ID. TODO: Stack overflow risk?
|
|
||||||
return fetchLogsToThreshold(logIds, threshold, logs);
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
if (clearAll) {
|
||||||
let allLogIds = [];
|
removeLogIds = allLogIds;
|
||||||
return fetchLogIds().then((logIds) => {
|
}
|
||||||
allLogIds = logIds.map((id) => id); // deep copy array as we'll modify it when fetching logs
|
if (removeLogIds.length > 0) {
|
||||||
return fetchLogsToThreshold(logIds, MAX_LOG_SIZE, []);
|
console.log("Removing logs: ", removeLogIds);
|
||||||
}).then((logs) => {
|
// Don't await this because it's non-fatal if we can't clean up logs.
|
||||||
// Remove all logs that are beyond the threshold (not in logs), or the entire logs if clearAll was set.
|
Promise.all(removeLogIds.map((id) => deleteLogs(id))).then(() => {
|
||||||
let removeLogIds = allLogIds;
|
console.log(`Removed ${removeLogIds.length} old logs.`);
|
||||||
if (!clearAll) {
|
}, (err) => {
|
||||||
removeLogIds = removeLogIds.filter((id) => {
|
console.error(err);
|
||||||
for (let i = 0; i < logs.length; i++) {
|
})
|
||||||
if (logs[i].id === id) {
|
}console.log("async consumeeeee");
|
||||||
return false; // do not remove logs that we're about to return to the caller.
|
return logs;
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (removeLogIds.length > 0) {
|
|
||||||
console.log("Removing logs: ", removeLogIds);
|
|
||||||
// Don't promise chain this because it's non-fatal if we can't clean up logs.
|
|
||||||
Promise.all(removeLogIds.map((id) => deleteLogs(id))).then(() => {
|
|
||||||
console.log(`Removed ${removeLogIds.length} old logs.`);
|
|
||||||
}, (err) => {
|
|
||||||
console.error(err);
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return logs;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_generateLogEntry(lines) {
|
_generateLogEntry(lines) {
|
||||||
|
@ -350,22 +321,22 @@ module.exports = {
|
||||||
* Force-flush the logs to storage.
|
* Force-flush the logs to storage.
|
||||||
* @return {Promise} Resolved when the logs have been flushed.
|
* @return {Promise} Resolved when the logs have been flushed.
|
||||||
*/
|
*/
|
||||||
flush: function() {
|
flush: async function() {
|
||||||
if (!store) {
|
if (!store) {
|
||||||
return Promise.resolve();
|
return;
|
||||||
}
|
}
|
||||||
return store.flush();
|
await store.flush();
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clean up old logs.
|
* Clean up old logs.
|
||||||
* @return Promise Resolves if cleaned logs.
|
* @return Promise Resolves if cleaned logs.
|
||||||
*/
|
*/
|
||||||
cleanup: function() {
|
cleanup: async function() {
|
||||||
if (!store) {
|
if (!store) {
|
||||||
return Promise.resolve();
|
return;
|
||||||
}
|
}
|
||||||
return store.consume(false);
|
await store.consume(false);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -373,45 +344,43 @@ module.exports = {
|
||||||
* @param {string} userText Any additional user input.
|
* @param {string} userText Any additional user input.
|
||||||
* @return {Promise} Resolved when the bug report is sent.
|
* @return {Promise} Resolved when the bug report is sent.
|
||||||
*/
|
*/
|
||||||
sendBugReport: function(userText) {
|
sendBugReport: async function(userText) {
|
||||||
if (!logger) {
|
if (!logger) {
|
||||||
return Promise.reject(new Error("No console logger, did you forget to call init()?"));
|
throw new Error("No console logger, did you forget to call init()?");
|
||||||
}
|
}
|
||||||
// If in incognito mode, store is null, but we still want bug report sending to work going off
|
// If in incognito mode, store is null, but we still want bug report sending to work going off
|
||||||
// the in-memory console logs.
|
// the in-memory console logs.
|
||||||
let promise = Promise.resolve([]);
|
let logs = [];
|
||||||
if (store) {
|
if (store) {
|
||||||
promise = store.consume(false); // TODO Swap to true to remove all logs
|
logs = await store.consume(false);
|
||||||
}
|
}
|
||||||
return promise.then((logs) => {
|
// and add the most recent console logs which won't be in the store yet.
|
||||||
// and add the most recent console logs which won't be in the store yet.
|
const consoleLogs = logger.flush(); // remove logs from console
|
||||||
const consoleLogs = logger.flush(); // remove logs from console
|
const currentId = store ? store.id : "-";
|
||||||
const currentId = store ? store.id : "-";
|
logs.unshift({
|
||||||
logs.unshift({
|
lines: consoleLogs,
|
||||||
lines: consoleLogs,
|
id: currentId,
|
||||||
id: currentId,
|
});
|
||||||
});
|
await new Promise((resolve, reject) => {
|
||||||
return new Promise((resolve, reject) => {
|
request({
|
||||||
request({
|
method: "POST",
|
||||||
method: "POST",
|
url: "http://localhost:1337",
|
||||||
url: "http://localhost:1337",
|
body: {
|
||||||
body: {
|
logs: logs,
|
||||||
logs: logs,
|
text: userText || "User did not supply any additional text.",
|
||||||
text: userText || "User did not supply any additional text.",
|
},
|
||||||
},
|
json: true,
|
||||||
json: true,
|
}, (err, res) => {
|
||||||
}, (err, res) => {
|
if (err) {
|
||||||
if (err) {
|
reject(err);
|
||||||
reject(err);
|
return;
|
||||||
return;
|
}
|
||||||
}
|
if (res.status < 200 || res.status >= 400) {
|
||||||
if (res.status < 200 || res.status >= 400) {
|
reject(new Error(`HTTP ${res.status}`));
|
||||||
reject(new Error(`HTTP ${res.status}`));
|
return;
|
||||||
return;
|
}
|
||||||
}
|
resolve();
|
||||||
resolve();
|
})
|
||||||
})
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue