refactor: Simplify network error detection during auth test

This commit is contained in:
FoxxMD
2023-11-02 10:07:02 -04:00
parent 3a25057d05
commit 339bb7fcd2
4 changed files with 26 additions and 10 deletions
+5
View File
@@ -1,5 +1,6 @@
import {isArbitraryObject} from "../infrastructure/Atomic";
import ErrnoException = NodeJS.ErrnoException;
import {findCauseByFunc} from "../../utils";
export type NodeNetworkErrorCode = 'ENOTFOUND' | 'ETIMEDOUT' | 'EAI_AGAIN' | 'ECONNRESET' | 'ECONNREFUSED' | 'ERRADDRINUSE' | 'EADDRNOTAVAIL' | 'ECONNABORTED' | 'EHOSTUNREACH';
export const NETWORK_ERROR_CODES = ['ENOTFOUND', 'ETIMEDOUT', 'EAI_AGAIN', 'ECONNRESET', 'ECONNREFUSED', 'ERRADDRINUSE', 'EADDRNOTAVAIL', 'ECONNABORTED', 'EHOSTUNREACH'];
@@ -20,3 +21,7 @@ export interface NodeNetworkException extends ErrnoException {
export const isNodeNetworkException = (error: unknown): error is NodeNetworkException => {
return isErrnoException(error) && NETWORK_ERROR_CODES.includes(error.code);
}
export const hasNodeNetworkException = (error: unknown): boolean => {
return findCauseByFunc(error, isNodeNetworkException) !== undefined;
}
@@ -1,4 +1,5 @@
import {ErrorWithCause} from "pony-cause";
import {findCauseByFunc} from "../../utils";
export class UpstreamError<T = undefined> extends ErrorWithCause<T> {
@@ -10,3 +11,16 @@ export class UpstreamError<T = undefined> extends ErrorWithCause<T> {
this.showStopper = showStopper;
}
}
export const hasUpstreamError = (err: any, showStopping?: boolean): boolean => {
return findCauseByFunc(err, (e) => {
if (e instanceof UpstreamError) {
if (showStopping === undefined) {
return true;
} else {
return e.showStopper === showStopping;
}
}
return false;
}) !== undefined;
}
@@ -1,6 +1,6 @@
import dayjs, {Dayjs} from "dayjs";
import {
comparingMultipleArtists, findCauseByFunc,
comparingMultipleArtists,
isPlayTemporallyClose,
mergeArr,
playObjDataMatch, pollingBackoff,
@@ -16,21 +16,18 @@ import {
NOT_INITIALIZED, REFERENCE_WEIGHT,
ScrobbledPlayObject, TIME_WEIGHT, TITLE_WEIGHT,
} from "../common/infrastructure/Atomic";
import winston, {Logger} from '@foxxmd/winston';
import {Logger} from '@foxxmd/winston';
import { CommonClientConfig } from "../common/infrastructure/config/client/index";
import { ClientConfig } from "../common/infrastructure/config/client/clients";
import { Notifiers } from "../notifier/Notifiers";
import {FixedSizeList} from 'fixed-size-list';
import {DeadLetterScrobble, PlayObject, QueuedScrobble, SourceScrobble, TrackStringOptions} from "../../core/Atomic";
import {buildTrackString, capitalize, truncateStringToLength} from "../../core/StringUtils";
import EventEmitter from "events";
import {compareScrobbleArtists, compareScrobbleTracks, normalizeStr} from "../utils/StringUtils";
import {UpstreamError} from "../common/errors/UpstreamError";
import {hasUpstreamError, UpstreamError} from "../common/errors/UpstreamError";
import {nanoid} from "nanoid";
import {ErrorWithCause, messageWithCauses} from "pony-cause";
import {de} from "@faker-js/faker";
import {del} from "superagent";
import {isNodeNetworkException} from "../common/errors/NodeErrors";
import {hasNodeNetworkException} from "../common/errors/NodeErrors";
export default abstract class AbstractScrobbleClient implements Authenticatable {
@@ -171,8 +168,8 @@ export default abstract class AbstractScrobbleClient implements Authenticatable
this.authed = await this.doAuthentication();
this.authFailure = !this.authed;
} catch (e) {
// only signal as auth failure if error was NOT a node network error
this.authFailure = findCauseByFunc(e, isNodeNetworkException) === undefined;
// only signal as auth failure if error was NOT either a node network error or a non-showstopping upstream error
this.authFailure = !(hasNodeNetworkException(e) || hasUpstreamError(e, false));
this.authed = false;
this.logger.error(`Authentication test failed!${this.authFailure === false ? ' Due to a network issue. Will retry authentication on next heartbeat.' : ''}`);
this.logger.error(e);
+1 -1
View File
@@ -919,7 +919,7 @@ export const comparingMultipleArtists = (existing: PlayObject, candidate: PlayOb
/**
* Adapted from https://github.com/voxpelli/pony-cause/blob/main/lib/helpers.js to find cause by truthy function
* */
export const findCauseByFunc = (err: any, func: (e: any) => boolean) => {
export const findCauseByFunc = (err: any, func: (e: Error) => boolean) => {
if (!err || !func) return;
if (!(err instanceof Error)) return;
if (typeof func !== 'function') {