Browse Source
Feature/execute scraper configuration instantly (#3723)
* Execute scraper configuration instantly
* Update changelog
---------
Co-authored-by: Thomas Kaul <4159106+dtslvr@users.noreply.github.com>
pull/3731/head
Shaunak Das
5 months ago
committed by
GitHub
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with
37 additions and
2 deletions
-
CHANGELOG.md
-
apps/api/src/services/data-provider/manual/manual.service.ts
-
apps/api/src/services/symbol-profile/symbol-profile.service.ts
-
libs/common/src/lib/interfaces/scraper-configuration.interface.ts
|
|
@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 |
|
|
|
### Added |
|
|
|
|
|
|
|
- Set up a performance logging service |
|
|
|
- Added the attribute `mode` to the scraper configuration to get quotes instantly |
|
|
|
|
|
|
|
### Changed |
|
|
|
|
|
|
|
|
|
@ -166,11 +166,42 @@ export class ManualService implements DataProviderInterface { |
|
|
|
} |
|
|
|
}); |
|
|
|
|
|
|
|
const symbolProfilesWithScraperConfigurationAndInstantMode = |
|
|
|
symbolProfiles.filter(({ scraperConfiguration }) => { |
|
|
|
return scraperConfiguration?.mode === 'instant'; |
|
|
|
}); |
|
|
|
|
|
|
|
const scraperResultPromises = |
|
|
|
symbolProfilesWithScraperConfigurationAndInstantMode.map( |
|
|
|
async ({ scraperConfiguration, symbol }) => { |
|
|
|
try { |
|
|
|
const marketPrice = await this.scrape(scraperConfiguration); |
|
|
|
return { marketPrice, symbol }; |
|
|
|
} catch (error) { |
|
|
|
Logger.error( |
|
|
|
`Could not get quote for ${symbol} (${this.getName()}): [${error.name}] ${error.message}`, |
|
|
|
'ManualService' |
|
|
|
); |
|
|
|
return { symbol, marketPrice: undefined }; |
|
|
|
} |
|
|
|
} |
|
|
|
); |
|
|
|
|
|
|
|
// Wait for all scraping requests to complete concurrently
|
|
|
|
const scraperResults = await Promise.all(scraperResultPromises); |
|
|
|
|
|
|
|
for (const { currency, symbol } of symbolProfiles) { |
|
|
|
let marketPrice = |
|
|
|
let { marketPrice } = |
|
|
|
scraperResults.find((result) => { |
|
|
|
return result.symbol === symbol; |
|
|
|
}) ?? {}; |
|
|
|
|
|
|
|
marketPrice = |
|
|
|
marketPrice ?? |
|
|
|
marketData.find((marketDataItem) => { |
|
|
|
return marketDataItem.symbol === symbol; |
|
|
|
})?.marketPrice ?? 0; |
|
|
|
})?.marketPrice ?? |
|
|
|
0; |
|
|
|
|
|
|
|
response[symbol] = { |
|
|
|
currency, |
|
|
|
|
|
@ -275,6 +275,8 @@ export class SymbolProfileService { |
|
|
|
headers: |
|
|
|
scraperConfiguration.headers as ScraperConfiguration['headers'], |
|
|
|
locale: scraperConfiguration.locale as string, |
|
|
|
mode: |
|
|
|
(scraperConfiguration.mode as ScraperConfiguration['mode']) ?? 'lazy', |
|
|
|
selector: scraperConfiguration.selector as string, |
|
|
|
url: scraperConfiguration.url as string |
|
|
|
}; |
|
|
|
|
|
@ -2,6 +2,7 @@ export interface ScraperConfiguration { |
|
|
|
defaultMarketPrice?: number; |
|
|
|
headers?: { [key: string]: string }; |
|
|
|
locale?: string; |
|
|
|
mode?: 'instant' | 'lazy'; |
|
|
|
selector: string; |
|
|
|
url: string; |
|
|
|
} |
|
|
|