Browse Source

Feature/improve error handling in data providers (#5387)

* Improve error handling

* Update changelog
pull/5389/head^2
Thomas Kaul 16 hours ago
committed by GitHub
parent
commit
b0f770e50a
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 4
      CHANGELOG.md
  2. 10
      apps/api/src/services/data-provider/coingecko/coingecko.service.ts
  3. 8
      apps/api/src/services/data-provider/eod-historical-data/eod-historical-data.service.ts
  4. 10
      apps/api/src/services/data-provider/financial-modeling-prep/financial-modeling-prep.service.ts
  5. 34
      apps/api/src/services/data-provider/ghostfolio/ghostfolio.service.ts
  6. 2
      apps/api/src/services/data-provider/rapid-api/rapid-api.service.ts

4
CHANGELOG.md

@ -11,6 +11,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Extended the data providers management of the admin control panel by every data provider in use
### Changed
- Improved the error handling in data providers
## 2.192.0 - 2025-08-21
### Added

10
apps/api/src/services/data-provider/coingecko/coingecko.service.ts

@ -78,7 +78,7 @@ export class CoinGeckoService implements DataProviderInterface {
} catch (error) {
let message = error;
if (error?.name === 'AbortError') {
if (['AbortError', 'TimeoutError'].includes(error?.name)) {
message = `RequestError: The operation to get the asset profile for ${symbol} was aborted because the request to the data provider took more than ${(
this.configurationService.get('REQUEST_TIMEOUT') / 1000
).toFixed(3)} seconds`;
@ -196,8 +196,10 @@ export class CoinGeckoService implements DataProviderInterface {
} catch (error) {
let message = error;
if (error?.name === 'AbortError') {
message = `RequestError: The operation to get the quotes was aborted because the request to the data provider took more than ${(
if (['AbortError', 'TimeoutError'].includes(error?.name)) {
message = `RequestError: The operation to get the quotes for ${symbols.join(
', '
)} was aborted because the request to the data provider took more than ${(
this.configurationService.get('REQUEST_TIMEOUT') / 1000
).toFixed(3)} seconds`;
}
@ -237,7 +239,7 @@ export class CoinGeckoService implements DataProviderInterface {
} catch (error) {
let message = error;
if (error?.name === 'AbortError') {
if (['AbortError', 'TimeoutError'].includes(error?.name)) {
message = `RequestError: The operation to search for ${query} was aborted because the request to the data provider took more than ${(
this.configurationService.get('REQUEST_TIMEOUT') / 1000
).toFixed(3)} seconds`;

8
apps/api/src/services/data-provider/eod-historical-data/eod-historical-data.service.ts

@ -282,8 +282,10 @@ export class EodHistoricalDataService implements DataProviderInterface {
} catch (error) {
let message = error;
if (error?.name === 'AbortError') {
message = `RequestError: The operation to get the quotes was aborted because the request to the data provider took more than ${(
if (['AbortError', 'TimeoutError'].includes(error?.name)) {
message = `RequestError: The operation to get the quotes for ${symbols.join(
', '
)} was aborted because the request to the data provider took more than ${(
this.configurationService.get('REQUEST_TIMEOUT') / 1000
).toFixed(3)} seconds`;
}
@ -426,7 +428,7 @@ export class EodHistoricalDataService implements DataProviderInterface {
} catch (error) {
let message = error;
if (error?.name === 'AbortError') {
if (['AbortError', 'TimeoutError'].includes(error?.name)) {
message = `RequestError: The operation to search for ${aQuery} was aborted because the request to the data provider took more than ${(
this.configurationService.get('REQUEST_TIMEOUT') / 1000
).toFixed(3)} seconds`;

10
apps/api/src/services/data-provider/financial-modeling-prep/financial-modeling-prep.service.ts

@ -202,7 +202,7 @@ export class FinancialModelingPrepService implements DataProviderInterface {
} catch (error) {
let message = error;
if (error?.name === 'AbortError') {
if (['AbortError', 'TimeoutError'].includes(error?.name)) {
message = `RequestError: The operation to get the asset profile for ${symbol} was aborted because the request to the data provider took more than ${(
requestTimeout / 1000
).toFixed(3)} seconds`;
@ -392,8 +392,10 @@ export class FinancialModelingPrepService implements DataProviderInterface {
} catch (error) {
let message = error;
if (error?.name === 'AbortError') {
message = `RequestError: The operation to get the quotes was aborted because the request to the data provider took more than ${(
if (['AbortError', 'TimeoutError'].includes(error?.name)) {
message = `RequestError: The operation to get the quotes for ${symbols.join(
', '
)} was aborted because the request to the data provider took more than ${(
requestTimeout / 1000
).toFixed(3)} seconds`;
}
@ -469,7 +471,7 @@ export class FinancialModelingPrepService implements DataProviderInterface {
} catch (error) {
let message = error;
if (error?.name === 'AbortError') {
if (['AbortError', 'TimeoutError'].includes(error?.name)) {
message = `RequestError: The operation to search for ${query} was aborted because the request to the data provider took more than ${(
this.configurationService.get('REQUEST_TIMEOUT') / 1000
).toFixed(3)} seconds`;

34
apps/api/src/services/data-provider/ghostfolio/ghostfolio.service.ts

@ -68,14 +68,16 @@ export class GhostfolioService implements DataProviderInterface {
} catch (error) {
let message = error;
if (error.name === 'AbortError') {
message = `RequestError: The operation to get the quotes was aborted because the request to the data provider took more than ${(
if (['AbortError', 'TimeoutError'].includes(error?.name)) {
message = `RequestError: The operation to get the asset profile for ${symbol} was aborted because the request to the data provider took more than ${(
requestTimeout / 1000
).toFixed(3)} seconds`;
} else if (error.response?.statusCode === StatusCodes.TOO_MANY_REQUESTS) {
} else if (
error?.response?.statusCode === StatusCodes.TOO_MANY_REQUESTS
) {
message = 'RequestError: The daily request limit has been exceeded';
} else if (error.response?.statusCode === StatusCodes.UNAUTHORIZED) {
if (!error.request?.options?.headers?.authorization?.includes('-')) {
} else if (error?.response?.statusCode === StatusCodes.UNAUTHORIZED) {
if (!error?.request?.options?.headers?.authorization?.includes('-')) {
message =
'RequestError: The provided API key is invalid. Please update it in the Settings section of the Admin Control panel.';
} else {
@ -229,14 +231,18 @@ export class GhostfolioService implements DataProviderInterface {
} catch (error) {
let message = error;
if (error.name === 'AbortError') {
message = `RequestError: The operation to get the quotes was aborted because the request to the data provider took more than ${(
if (['AbortError', 'TimeoutError'].includes(error?.name)) {
message = `RequestError: The operation to get the quotes for ${symbols.join(
', '
)} was aborted because the request to the data provider took more than ${(
requestTimeout / 1000
).toFixed(3)} seconds`;
} else if (error.response?.statusCode === StatusCodes.TOO_MANY_REQUESTS) {
} else if (
error?.response?.statusCode === StatusCodes.TOO_MANY_REQUESTS
) {
message = 'RequestError: The daily request limit has been exceeded';
} else if (error.response?.statusCode === StatusCodes.UNAUTHORIZED) {
if (!error.request?.options?.headers?.authorization?.includes('-')) {
} else if (error?.response?.statusCode === StatusCodes.UNAUTHORIZED) {
if (!error?.request?.options?.headers?.authorization?.includes('-')) {
message =
'RequestError: The provided API key is invalid. Please update it in the Settings section of the Admin Control panel.';
} else {
@ -272,14 +278,16 @@ export class GhostfolioService implements DataProviderInterface {
} catch (error) {
let message = error;
if (error.name === 'AbortError') {
if (['AbortError', 'TimeoutError'].includes(error?.name)) {
message = `RequestError: The operation to search for ${query} was aborted because the request to the data provider took more than ${(
requestTimeout / 1000
).toFixed(3)} seconds`;
} else if (error.response?.statusCode === StatusCodes.TOO_MANY_REQUESTS) {
} else if (
error?.response?.statusCode === StatusCodes.TOO_MANY_REQUESTS
) {
message = 'RequestError: The daily request limit has been exceeded';
} else if (error.response?.statusCode === StatusCodes.UNAUTHORIZED) {
if (!error.request?.options?.headers?.authorization?.includes('-')) {
if (!error?.request?.options?.headers?.authorization?.includes('-')) {
message =
'RequestError: The provided API key is invalid. Please update it in the Settings section of the Admin Control panel.';
} else {

2
apps/api/src/services/data-provider/rapid-api/rapid-api.service.ts

@ -165,7 +165,7 @@ export class RapidApiService implements DataProviderInterface {
} catch (error) {
let message = error;
if (error?.name === 'AbortError') {
if (['AbortError', 'TimeoutError'].includes(error?.name)) {
message = `RequestError: The operation was aborted because the request to the data provider took more than ${(
this.configurationService.get('REQUEST_TIMEOUT') / 1000
).toFixed(3)} seconds`;

Loading…
Cancel
Save