|
| 1 | +import { AfterErrorContext, AfterErrorHook, AfterSuccessContext, AfterSuccessHook } from "../types"; |
| 2 | + |
| 3 | +/** |
| 4 | + * Represents a hook that logs status and information that the request will be retried |
| 5 | + * after encountering a 5xx error. |
| 6 | + */ |
| 7 | +export class LoggerHook implements AfterSuccessHook, AfterErrorHook { |
| 8 | + private retriesCounter: Map<string, number> = new Map(); |
| 9 | + |
| 10 | + /** |
| 11 | + * Log retries to give users visibility into requests. |
| 12 | + * @param response - The response object received from the server. |
| 13 | + * @param error - The error object representing the encountered error. |
| 14 | + * @param operationID - The unique identifier for the operation being logged. |
| 15 | + */ |
| 16 | + private logRetries( |
| 17 | + response: Response | null, |
| 18 | + error: unknown, |
| 19 | + operationID: string |
| 20 | + ): void { |
| 21 | + if (response && response.status >= 500) { |
| 22 | + console.warn( |
| 23 | + "Failed to process a request due to API server error with status code %d. " + |
| 24 | + "Attempting retry number %d after sleep.", |
| 25 | + response.status, |
| 26 | + this.retriesCounter.get(operationID) |
| 27 | + ); |
| 28 | + if (response.statusText) { |
| 29 | + console.warn("Server message - %s", response.statusText); |
| 30 | + } |
| 31 | + } else if (error) { |
| 32 | + console.info( |
| 33 | + `Failed to process a request due to connection error - ${(error as Error).message}. ` + |
| 34 | + `Attempting retry number ${this.retriesCounter.get(operationID)} after sleep.` |
| 35 | + ); |
| 36 | + } |
| 37 | + } |
| 38 | + |
| 39 | + /** |
| 40 | + * Handles successful responses, resetting the retry counter for the operation. |
| 41 | + * Logs a success message indicating that the document was successfully partitioned. |
| 42 | + * @param hookCtx - The context object containing information about the request. |
| 43 | + * @param response - The response object received from the server. |
| 44 | + * @returns The response object. |
| 45 | + */ |
| 46 | + afterSuccess(hookCtx: AfterSuccessContext, response: Response): Response { |
| 47 | + this.retriesCounter.delete(hookCtx.operationID); |
| 48 | + // NOTE: In case of split page partition this means - at least one of the splits was partitioned successfully |
| 49 | + console.info("Successfully partitioned the document."); |
| 50 | + return response; |
| 51 | + } |
| 52 | + |
| 53 | + /** |
| 54 | + * Executes after an error occurs during a request. |
| 55 | + * @param hookCtx - The context object containing information about the request. |
| 56 | + * @param response - The response object received from the server. |
| 57 | + * @param error - The error object representing the encountered error. |
| 58 | + * @returns An object containing the updated response and error. |
| 59 | + */ |
| 60 | + afterError( |
| 61 | + hookCtx: AfterErrorContext, |
| 62 | + response: Response | null, |
| 63 | + error: unknown |
| 64 | + ): { response: Response | null; error: unknown } { |
| 65 | + const currentCount = this.retriesCounter.get(hookCtx.operationID) || 0; |
| 66 | + this.retriesCounter.set(hookCtx.operationID, currentCount + 1); |
| 67 | + this.logRetries(response, error, hookCtx.operationID); |
| 68 | + |
| 69 | + if (response && response.status === 200) { |
| 70 | + console.info("Successfully partitioned the document."); |
| 71 | + } else { |
| 72 | + console.error("Failed to partition the document."); |
| 73 | + if (response) { |
| 74 | + console.error(`Server responded with ${response.status} - ${response.statusText}`); |
| 75 | + } |
| 76 | + if (error) { |
| 77 | + console.error(`Following error occurred - ${(error as Error).message}`); |
| 78 | + } |
| 79 | + } |
| 80 | + return { response, error }; |
| 81 | + } |
| 82 | +} |
0 commit comments