Feature/introduce data gathering progress (#467)

* Add data gathering progress

* Update changelog
pull/468/head
Thomas Kaul 3 years ago committed by GitHub
parent 9df8541145
commit a42700b9fe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added ### Added
- Added a logo to the log on the server start - Added a logo to the log on the server start
- Added the data gathering progress to the log and the admin control panel
## 1.74.0 - 11.11.2021 ## 1.74.0 - 11.11.2021

@ -20,6 +20,8 @@ export class AdminService {
public async get(): Promise<AdminData> { public async get(): Promise<AdminData> {
return { return {
dataGatheringProgress:
await this.dataGatheringService.getDataGatheringProgress(),
exchangeRates: this.exchangeRateDataService exchangeRates: this.exchangeRateDataService
.getCurrencies() .getCurrencies()
.filter((currency) => { .filter((currency) => {
@ -58,7 +60,7 @@ export class AdminService {
return 'IN_PROGRESS'; return 'IN_PROGRESS';
} }
return null; return undefined;
} }
private async getUsersWithAnalytics(): Promise<AdminData['users']> { private async getUsersWithAnalytics(): Promise<AdminData['users']> {

@ -18,7 +18,6 @@ import {
import { ConfigurationService } from './configuration.service'; import { ConfigurationService } from './configuration.service';
import { DataProviderService } from './data-provider/data-provider.service'; import { DataProviderService } from './data-provider/data-provider.service';
import { GhostfolioScraperApiService } from './data-provider/ghostfolio-scraper-api/ghostfolio-scraper-api.service';
import { DataEnhancerInterface } from './data-provider/interfaces/data-enhancer.interface'; import { DataEnhancerInterface } from './data-provider/interfaces/data-enhancer.interface';
import { ExchangeRateDataService } from './exchange-rate-data.service'; import { ExchangeRateDataService } from './exchange-rate-data.service';
import { IDataGatheringItem } from './interfaces/interfaces'; import { IDataGatheringItem } from './interfaces/interfaces';
@ -26,13 +25,14 @@ import { PrismaService } from './prisma.service';
@Injectable() @Injectable()
export class DataGatheringService { export class DataGatheringService {
private dataGatheringProgress: number;
public constructor( public constructor(
private readonly configurationService: ConfigurationService, private readonly configurationService: ConfigurationService,
@Inject('DataEnhancers') @Inject('DataEnhancers')
private readonly dataEnhancers: DataEnhancerInterface[], private readonly dataEnhancers: DataEnhancerInterface[],
private readonly dataProviderService: DataProviderService, private readonly dataProviderService: DataProviderService,
private readonly exchangeRateDataService: ExchangeRateDataService, private readonly exchangeRateDataService: ExchangeRateDataService,
private readonly ghostfolioScraperApi: GhostfolioScraperApiService,
private readonly prismaService: PrismaService, private readonly prismaService: PrismaService,
private readonly symbolProfileService: SymbolProfileService private readonly symbolProfileService: SymbolProfileService
) {} ) {}
@ -204,8 +204,11 @@ export class DataGatheringService {
public async gatherSymbols(aSymbolsWithStartDate: IDataGatheringItem[]) { public async gatherSymbols(aSymbolsWithStartDate: IDataGatheringItem[]) {
let hasError = false; let hasError = false;
let symbolCounter = 0;
for (const { dataSource, date, symbol } of aSymbolsWithStartDate) { for (const { dataSource, date, symbol } of aSymbolsWithStartDate) {
this.dataGatheringProgress = symbolCounter / aSymbolsWithStartDate.length;
try { try {
const historicalData = await this.dataProviderService.getHistoricalRaw( const historicalData = await this.dataProviderService.getHistoricalRaw(
[{ dataSource, symbol }], [{ dataSource, symbol }],
@ -263,6 +266,16 @@ export class DataGatheringService {
hasError = true; hasError = true;
Logger.error(error); Logger.error(error);
} }
if (symbolCounter > 0 && symbolCounter % 100 === 0) {
Logger.log(
`Data gathering progress: ${(
this.dataGatheringProgress * 100
).toFixed(2)}%`
);
}
symbolCounter += 1;
} }
await this.exchangeRateDataService.initialize(); await this.exchangeRateDataService.initialize();
@ -272,6 +285,16 @@ export class DataGatheringService {
} }
} }
public async getDataGatheringProgress() {
const isInProgress = await this.getIsInProgress();
if (isInProgress) {
return this.dataGatheringProgress;
}
return undefined;
}
public async getIsInProgress() { public async getIsInProgress() {
return await this.prismaService.property.findUnique({ return await this.prismaService.property.findUnique({
where: { key: 'LOCKED_DATA_GATHERING' } where: { key: 'LOCKED_DATA_GATHERING' }

@ -22,6 +22,7 @@ import { takeUntil } from 'rxjs/operators';
}) })
export class AdminPageComponent implements OnDestroy, OnInit { export class AdminPageComponent implements OnDestroy, OnInit {
public dataGatheringInProgress: boolean; public dataGatheringInProgress: boolean;
public dataGatheringProgress: number;
public defaultDateFormat = DEFAULT_DATE_FORMAT; public defaultDateFormat = DEFAULT_DATE_FORMAT;
public exchangeRates: { label1: string; label2: string; value: number }[]; public exchangeRates: { label1: string; label2: string; value: number }[];
public lastDataGathering: string; public lastDataGathering: string;
@ -134,12 +135,14 @@ export class AdminPageComponent implements OnDestroy, OnInit {
.pipe(takeUntil(this.unsubscribeSubject)) .pipe(takeUntil(this.unsubscribeSubject))
.subscribe( .subscribe(
({ ({
dataGatheringProgress,
exchangeRates, exchangeRates,
lastDataGathering, lastDataGathering,
transactionCount, transactionCount,
userCount, userCount,
users users
}) => { }) => {
this.dataGatheringProgress = dataGatheringProgress;
this.exchangeRates = exchangeRates; this.exchangeRates = exchangeRates;
this.users = users; this.users = users;

@ -35,14 +35,15 @@
</div> </div>
</div> </div>
<div class="d-flex my-3"> <div class="d-flex my-3">
<div class="w-50" i18n>Last Data Gathering</div> <div class="w-50" i18n>Data Gathering</div>
<div class="w-50"> <div class="w-50">
<div> <div>
<ng-container *ngIf="lastDataGathering" <ng-container *ngIf="lastDataGathering"
>{{ lastDataGathering }}</ng-container >{{ lastDataGathering }}</ng-container
> >
<ng-container *ngIf="dataGatheringInProgress" i18n <ng-container *ngIf="dataGatheringInProgress" i18n
>In Progress</ng-container >In Progress ({{ dataGatheringProgress | percent : '1.2-2'
}})</ng-container
> >
</div> </div>
<div class="mt-2 overflow-hidden"> <div class="mt-2 overflow-hidden">

@ -1,6 +1,7 @@
export interface AdminData { export interface AdminData {
dataGatheringProgress?: number;
exchangeRates: { label1: string; label2: string; value: number }[]; exchangeRates: { label1: string; label2: string; value: number }[];
lastDataGathering: Date | 'IN_PROGRESS'; lastDataGathering?: Date | 'IN_PROGRESS';
transactionCount: number; transactionCount: number;
userCount: number; userCount: number;
users: { users: {

Loading…
Cancel
Save