From 6b135ac54dd9d8e4c9948be92edcfa907d419940 Mon Sep 17 00:00:00 2001 From: SwiftHawk Date: Mon, 8 Jul 2024 16:50:38 +0500 Subject: [PATCH] fix: add timeout in publishing updated app data and sending notifications --- src/utils/nostr.ts | 62 ++++++++++++++++++++++++++++++++-------------- src/utils/utils.ts | 15 +++++++++++ 2 files changed, 59 insertions(+), 18 deletions(-) diff --git a/src/utils/nostr.ts b/src/utils/nostr.ts index aab520a..34f7d52 100644 --- a/src/utils/nostr.ts +++ b/src/utils/nostr.ts @@ -29,6 +29,7 @@ import store from '../store/store' import { Meta, SignedEvent, UserAppData } from '../types' import { getHash } from './hash' import { parseJson, removeLeadingSlash } from './string' +import { timeout } from './utils' /** * @param hexKey hex private or public key @@ -555,20 +556,28 @@ export const updateUsersAppData = async (meta: Meta) => { const relayMap = (store.getState().relays as RelaysState).map! const writeRelays = Object.keys(relayMap).filter((key) => relayMap[key].write) - const publishResult = await nostrController - .publishEvent(signedEvent, writeRelays) - .catch((errResults) => { - console.log('err :>> ', errResults) - toast.error('An error occurred while publishing App data') - - errResults.forEach((errResult: any) => { + console.log(`publishing event kind: ${kinds.Application}`) + const publishResult = await Promise.race([ + nostrController.publishEvent(signedEvent, writeRelays), + timeout(1000 * 60 * 2) + ]).catch((err) => { + console.log('err :>> ', err) + if (err.message === 'Timeout') { + toast.error('Timeout occurred in publishing updated app data') + } else if (Array.isArray(err)) { + err.forEach((errResult) => { toast.error( `Publishing to ${errResult.relay} caused the following error: ${errResult.error}` ) }) + } else { + toast.error( + 'An unexpected error occurred in publishing updated app data ' + ) + } - return null - }) + return null + }) if (!publishResult) return null @@ -666,6 +675,8 @@ const uploadUserAppDataToBlossom = async ( } const getUserAppDataFromBlossom = async (url: string, privateKey: string) => { + let errorCode = 0 + const encrypted = await axios .get(url, { responseType: 'blob' @@ -679,9 +690,21 @@ const getUserAppDataFromBlossom = async (url: string, privateKey: string) => { console.error(`error occurred in getting file from ${url}`, err) toast.error(err.message || `error occurred in getting file from ${url}`) + if (err.request) { + const { status } = err.request + errorCode = status + } + return null }) + if (errorCode === 404) { + return { + sigits: {}, + processedGiftWraps: [] + } + } + if (!encrypted) return null const secret = hexToBytes(privateKey) @@ -818,15 +841,18 @@ export const sendNotification = async (receiver: string, meta: Meta) => { // Ensure relay list is not empty if (relaySet.read.length === 0) return + console.log('Publishing notifications') // Publish the notification event to the recipient's read relays const nostrController = NostrController.getInstance() - await nostrController - .publishEvent(wrappedEvent, relaySet.read) - .catch((errResults) => { - console.log( - `An error occurred while publishing notification event for ${hexToNpub(receiver)}`, - errResults - ) - throw errResults - }) + + await Promise.race([ + nostrController.publishEvent(wrappedEvent, relaySet.read), + timeout(1000 * 60 * 2) + ]).catch((err) => { + console.log( + `An error occurred while publishing notification event for ${hexToNpub(receiver)}`, + err + ) + throw err + }) } diff --git a/src/utils/utils.ts b/src/utils/utils.ts index fc5ade3..929af78 100644 --- a/src/utils/utils.ts +++ b/src/utils/utils.ts @@ -49,3 +49,18 @@ export const isOnline = async () => { return false // If an error occurs, return false } } + +/** + * Creates a promise that rejects with a timeout error after a specified duration. + * @param ms The duration in milliseconds after which the promise should reject. Defaults to 60000 milliseconds (1 minute). + * @returns A promise that rejects with an Error('Timeout') after the specified duration. + */ +export const timeout = (ms: number = 60000) => { + return new Promise((_, reject) => { + // Set a timeout using setTimeout + setTimeout(() => { + // Reject the promise with an Error indicating a timeout + reject(new Error('Timeout')) + }, ms) // Timeout duration in milliseconds + }) +}