Enable lint rules for Promise handling to discourage misuse of them. (#2607)

* Enable lint rules for Promise handling to discourage misuse of them.
Squashed all of Hugh's commits into one.

---------

Co-authored-by: Hugh Nimmo-Smith <hughns@element.io>
This commit is contained in:
Timo
2024-09-10 09:49:35 +02:00
committed by GitHub
parent c30c8ac7d6
commit c3edd3e25e
35 changed files with 369 additions and 241 deletions

View File

@@ -9,6 +9,7 @@ import { FC, useCallback } from "react";
import { randomString } from "matrix-js-sdk/src/randomstring";
import { useTranslation } from "react-i18next";
import { Button } from "@vector-im/compound-web";
import { logger } from "matrix-js-sdk/src/logger";
import { FieldRow, InputField, ErrorMessage } from "../input/Input";
import { useSubmitRageshake, useRageshakeRequest } from "./submit-rageshake";
@@ -41,6 +42,8 @@ export const FeedbackSettingsTab: FC<Props> = ({ roomId }) => {
sendLogs,
rageshakeRequestId,
roomId,
}).catch((e) => {
logger.error("Failed to send feedback rageshake", e);
});
if (roomId && sendLogs) {

View File

@@ -8,6 +8,7 @@ Please see LICENSE in the repository root for full details.
import { FC, useCallback, useEffect, useMemo, useRef } from "react";
import { MatrixClient } from "matrix-js-sdk/src/client";
import { useTranslation } from "react-i18next";
import { logger } from "matrix-js-sdk/src/logger";
import { useProfile } from "../profile/useProfile";
import { FieldRow, InputField, ErrorMessage } from "../input/Input";
@@ -61,6 +62,8 @@ export const ProfileSettingsTab: FC<Props> = ({ client }) => {
// @ts-ignore
avatar: avatar && avatarSize > 0 ? avatar : undefined,
removeAvatar: removeAvatar.current && (!avatar || avatarSize === 0),
}).catch((e) => {
logger.error("Failed to save profile", e);
});
}
};

View File

@@ -8,6 +8,7 @@ Please see LICENSE in the repository root for full details.
import { useTranslation } from "react-i18next";
import { FC, useCallback } from "react";
import { Button } from "@vector-im/compound-web";
import { logger } from "matrix-js-sdk/src/logger";
import { Config } from "../config/Config";
import styles from "./RageshakeButton.module.css";
@@ -25,6 +26,8 @@ export const RageshakeButton: FC<Props> = ({ description }) => {
submitRageshake({
description,
sendLogs: true,
}).catch((e) => {
logger.error("Failed to send rageshake", e);
});
}, [submitRageshake, description]);

View File

@@ -128,13 +128,17 @@ class IndexedDBLogStore {
this.id = "instance-" + randomString(16);
loggerInstance.on(ConsoleLoggerEvent.Log, this.onLoggerLog);
window.addEventListener("beforeunload", this.flush);
window.addEventListener("beforeunload", () => {
this.flush().catch((e) =>
logger.error("Failed to flush logs before unload", e),
);
});
}
/**
* @return {Promise} Resolves when the store is ready.
*/
public connect(): Promise<void> {
public async connect(): Promise<void> {
const req = this.indexedDB.open("logs");
return new Promise((resolve, reject) => {
req.onsuccess = (): void => {
@@ -190,16 +194,10 @@ class IndexedDBLogStore {
// Throttled function to flush logs. We use throttle rather
// than debounce as we want logs to be written regularly, otherwise
// if there's a constant stream of logging, we'd never write anything.
private throttledFlush = throttle(
() => {
this.flush();
},
MAX_FLUSH_INTERVAL_MS,
{
leading: false,
trailing: true,
},
);
private throttledFlush = throttle(() => this.flush, MAX_FLUSH_INTERVAL_MS, {
leading: false,
trailing: true,
});
/**
* Flush logs to disk.
@@ -220,7 +218,7 @@ class IndexedDBLogStore {
*
* @return {Promise} Resolved when the logs have been flushed.
*/
public flush = (): Promise<void> => {
public flush = async (): Promise<void> => {
// check if a flush() operation is ongoing
if (this.flushPromise) {
if (this.flushAgainPromise) {
@@ -228,13 +226,9 @@ class IndexedDBLogStore {
return this.flushAgainPromise;
}
// queue up a flush to occur immediately after the pending one completes.
this.flushAgainPromise = this.flushPromise
.then(() => {
return this.flush();
})
.then(() => {
this.flushAgainPromise = undefined;
});
this.flushAgainPromise = this.flushPromise.then(this.flush).then(() => {
this.flushAgainPromise = undefined;
});
return this.flushAgainPromise;
}
// there is no flush promise or there was but it has finished, so do
@@ -286,7 +280,7 @@ class IndexedDBLogStore {
// Returns: a string representing the concatenated logs for this ID.
// Stops adding log fragments when the size exceeds maxSize
function fetchLogs(id: string, maxSize: number): Promise<string> {
async function fetchLogs(id: string, maxSize: number): Promise<string> {
const objectStore = db!
.transaction("logs", "readonly")
.objectStore("logs");
@@ -316,7 +310,7 @@ class IndexedDBLogStore {
}
// Returns: A sorted array of log IDs. (newest first)
function fetchLogIds(): Promise<string[]> {
async function fetchLogIds(): Promise<string[]> {
// To gather all the log IDs, query for all records in logslastmod.
const o = db!
.transaction("logslastmod", "readonly")
@@ -336,7 +330,7 @@ class IndexedDBLogStore {
});
}
function deleteLogs(id: number): Promise<void> {
async function deleteLogs(id: number): Promise<void> {
return new Promise<void>((resolve, reject) => {
const txn = db!.transaction(["logs", "logslastmod"], "readwrite");
const o = txn.objectStore("logs");
@@ -394,7 +388,7 @@ class IndexedDBLogStore {
logger.log("Removing logs: ", removeLogIds);
// Don't await this because it's non-fatal if we can't clean up
// logs.
Promise.all(removeLogIds.map((id) => deleteLogs(id))).then(
Promise.all(removeLogIds.map(async (id) => deleteLogs(id))).then(
() => {
logger.log(`Removed ${removeLogIds.length} old logs.`);
},
@@ -432,7 +426,7 @@ class IndexedDBLogStore {
* @return {Promise<T[]>} Resolves to an array of whatever you returned from
* resultMapper.
*/
function selectQuery<T>(
async function selectQuery<T>(
store: IDBObjectStore,
keyRange: IDBKeyRange | undefined,
resultMapper: (cursor: IDBCursorWithValue) => T,
@@ -461,7 +455,7 @@ declare global {
// eslint-disable-next-line no-var, camelcase
var mx_rage_logger: ConsoleLogger;
// eslint-disable-next-line no-var, camelcase
var mx_rage_initStoragePromise: Promise<void>;
var mx_rage_initStoragePromise: Promise<void> | undefined;
}
/**
@@ -471,7 +465,7 @@ declare global {
* be set up immediately for the logs.
* @return {Promise} Resolves when set up.
*/
export function init(): Promise<void> {
export async function init(): Promise<void> {
global.mx_rage_logger = new ConsoleLogger();
setLogExtension(global.mx_rage_logger.log);
@@ -483,7 +477,7 @@ export function init(): Promise<void> {
* then this no-ops.
* @return {Promise} Resolves when complete.
*/
function tryInitStorage(): Promise<void> {
async function tryInitStorage(): Promise<void> {
if (global.mx_rage_initStoragePromise) {
return global.mx_rage_initStoragePromise;
}

View File

@@ -300,10 +300,14 @@ export function useRageshakeRequest(): (
const sendRageshakeRequest = useCallback(
(roomId: string, rageshakeRequestId: string) => {
// @ts-expect-error - org.matrix.rageshake_request is not part of `keyof TimelineEvents` but it is okay to sent a custom event.
client!.sendEvent(roomId, "org.matrix.rageshake_request", {
request_id: rageshakeRequestId,
});
client!
// @ts-expect-error - org.matrix.rageshake_request is not part of `keyof TimelineEvents` but it is okay to sent a custom event.
.sendEvent(roomId, "org.matrix.rageshake_request", {
request_id: rageshakeRequestId,
})
.catch((e) => {
logger.error("Failed to send org.matrix.rageshake_request event", e);
});
},
[client],
);