From 5dd1fa3dfa581fc51c030ec082fd14cd4dda1127 Mon Sep 17 00:00:00 2001 From: Ben Wilson Date: Tue, 1 Aug 2023 22:39:02 -0400 Subject: [PATCH] data rework --- .gitignore | 2 +- .../client-statistics.entity.ts | 11 +- .../client-statistics.service.ts | 191 +++++++++--------- src/app.controller.ts | 36 ++-- src/controllers/client/client.controller.ts | 13 +- src/models/StratumV1ClientStatistics.ts | 9 +- .../stratum-messages/SubscriptionMessage.ts | 2 +- 7 files changed, 140 insertions(+), 124 deletions(-) diff --git a/.gitignore b/.gitignore index 17cf0c0..ae1be05 100644 --- a/.gitignore +++ b/.gitignore @@ -37,4 +37,4 @@ settings.json !.vscode/extensions.json #DB -**.sqlite \ No newline at end of file +**.sqlite** \ No newline at end of file diff --git a/src/ORM/client-statistics/client-statistics.entity.ts b/src/ORM/client-statistics/client-statistics.entity.ts index ed80fe4..0ea8985 100644 --- a/src/ORM/client-statistics/client-statistics.entity.ts +++ b/src/ORM/client-statistics/client-statistics.entity.ts @@ -1,6 +1,5 @@ import { Column, Entity, Index, PrimaryColumn } from 'typeorm'; -import { DateTimeTransformer } from '../utils/DateTimeTransformer'; import { TrackedEntity } from '../utils/TrackedEntity.entity'; @Entity() @@ -9,6 +8,7 @@ export class ClientStatisticsEntity extends TrackedEntity { @PrimaryColumn({ length: 64, type: 'varchar' }) submissionHash: string; + @Index() @Column({ length: 62, type: 'varchar' }) address: string; @@ -20,14 +20,11 @@ export class ClientStatisticsEntity extends TrackedEntity { sessionId: string; @Index() - @Column({ - type: 'datetime', - transformer: new DateTimeTransformer() - }) - time: Date; + @Column({ type: 'integer' }) + time: number; @Column({ type: 'real' }) - difficulty: number; + shares: number; diff --git a/src/ORM/client-statistics/client-statistics.service.ts b/src/ORM/client-statistics/client-statistics.service.ts index c70ec39..8801585 100644 --- a/src/ORM/client-statistics/client-statistics.service.ts +++ b/src/ORM/client-statistics/client-statistics.service.ts @@ -18,7 +18,17 @@ export class ClientStatisticsService { } public async save(clientStatistic: Partial) { - return await this.clientStatisticsRepository.save(clientStatistic); + const res1 = await this.clientStatisticsRepository.createQueryBuilder() + .update(ClientStatisticsEntity) + .set({ + shares: () => `"shares" + ${clientStatistic.shares}` // Use the actual value of shares here + }) + .where('address = :address AND clientName = :clientName AND sessionId = :sessionId AND time = :time', { address: clientStatistic.address, clientName: clientStatistic.clientName, sessionId: clientStatistic.sessionId, time: clientStatistic.time }) + .execute(); + + if (res1.affected == 0) { + await this.clientStatisticsRepository.insert(clientStatistic); + } } public async deleteOldStatistics() { @@ -34,79 +44,74 @@ export class ClientStatisticsService { public async getChartDataForSite() { + var yesterday = new Date(new Date().getTime() - (24 * 60 * 60 * 1000)); const query = ` - WITH result_set AS ( SELECT - MAX(time) || 'GMT' AS label, - (SUM(difficulty) * 4294967296) / - ((JULIANDAY(MAX(time)) - JULIANDAY(MIN(time))) * 24 * 60 * 60) AS data + time AS label, + ROUND(((SUM(shares) * 4294967296) / 600)) AS data FROM client_statistics_entity AS entry WHERE - entry.time > datetime("now", "-1 day") + entry.time > ${yesterday.getTime()} GROUP BY - strftime('%Y-%m-%d %H', time, 'localtime') || (strftime('%M', time, 'localtime') / 10) + time ORDER BY - time - ) - SELECT * - FROM result_set - WHERE label <> (SELECT MAX(label) FROM result_set); + time + LIMIT 144; + `; - const result = await this.clientStatisticsRepository.query(query); - + const result: any[] = await this.clientStatisticsRepository.query(query); return result.map(res => { res.label = new Date(res.label).toISOString(); return res; - }); + }).slice(0, result.length - 1) } - public async getHashRateForAddress(address: string) { + // public async getHashRateForAddress(address: string) { - const query = ` - SELECT - (JULIANDAY(MAX(entry.time)) - JULIANDAY(MIN(entry.time))) * 24 * 60 * 60 AS timeDiff, - SUM(entry.difficulty) AS difficultySum - FROM - client_statistics_entity AS entry - WHERE - entry.address = ? AND entry.time > datetime("now", "-1 hour") - `; + // const oneHour = new Date(new Date().getTime() - (60 * 60 * 1000)); - const result = await this.clientStatisticsRepository.query(query, [address]); + // const query = ` + // SELECT + // SUM(entry.shares) AS difficultySum + // FROM + // client_statistics_entity AS entry + // WHERE + // entry.address = ? AND entry.time > ${oneHour} + // `; - const timeDiff = result[0].timeDiff; - const difficultySum = result[0].difficultySum; + // const result = await this.clientStatisticsRepository.query(query, [address]); - return (difficultySum * 4294967296) / (timeDiff); + // const difficultySum = result[0].difficultySum; - } + // return (difficultySum * 4294967296) / (600); + + // } public async getChartDataForAddress(address: string) { + + var yesterday = new Date(new Date().getTime() - (24 * 60 * 60 * 1000)); + const query = ` - WITH result_set AS ( SELECT - MAX(time) || 'GMT' AS label, - (SUM(difficulty) * 4294967296) / - ((JULIANDAY(MAX(time)) - JULIANDAY(MIN(time))) * 24 * 60 * 60) AS data + time label, + (SUM(shares) * 4294967296) / 600 AS data FROM client_statistics_entity AS entry WHERE - entry.address = ? AND entry.time > datetime("now", "-1 day") + entry.address = ? AND entry.time > ${yesterday.getTime()} GROUP BY - strftime('%Y-%m-%d %H', time, 'localtime') || (strftime('%M', time, 'localtime') / 10) + time ORDER BY - time - ) - SELECT * - FROM result_set - WHERE label <> (SELECT MAX(label) FROM result_set); + time + LIMIT 144; + `; const result = await this.clientStatisticsRepository.query(query, [address]); @@ -114,52 +119,50 @@ export class ClientStatisticsService { return result.map(res => { res.label = new Date(res.label).toISOString(); return res; - }); + }).slice(0, result.length - 1); + - return result; } public async getHashRateForGroup(address: string, clientName: string) { + var oneHour = new Date(new Date().getTime() - (60 * 60 * 1000)); + const query = ` SELECT - (JULIANDAY(MAX(entry.time)) - JULIANDAY(MIN(entry.time))) * 24 * 60 * 60 AS timeDiff, - SUM(entry.difficulty) AS difficultySum + SUM(entry.shares) AS difficultySum FROM client_statistics_entity AS entry WHERE - entry.address = ? AND entry.clientName = ? AND entry.time > datetime("now", "-1 hour") + entry.address = ? AND entry.clientName = ? AND entry.time > ${oneHour.getTime()} `; const result = await this.clientStatisticsRepository.query(query, [address, clientName]); - const timeDiff = result[0].timeDiff; + const difficultySum = result[0].difficultySum; - return (difficultySum * 4294967296) / (timeDiff); + return (difficultySum * 4294967296) / (600); } public async getChartDataForGroup(address: string, clientName: string) { + var yesterday = new Date(new Date().getTime() - (24 * 60 * 60 * 1000)); + const query = ` - WITH result_set AS ( - SELECT - MAX(time) || 'GMT' AS label, - (SUM(difficulty) * 4294967296) / - ((JULIANDAY(MAX(time)) - JULIANDAY(MIN(time))) * 24 * 60 * 60) AS data - FROM - client_statistics_entity AS entry - WHERE - entry.address = ? AND entry.clientName = ? AND entry.time > datetime("now", "-1 day") - GROUP BY - strftime('%Y-%m-%d %H', time, 'localtime') || (strftime('%M', time, 'localtime') / 10) - ORDER BY + SELECT + time label, + (SUM(shares) * 4294967296) / 600 AS data + FROM + client_statistics_entity AS entry + WHERE + entry.address = ? AND entry.clientName = ? AND entry.time > ${yesterday.getTime()} + GROUP BY time - ) - SELECT * - FROM result_set - WHERE label <> (SELECT MAX(label) FROM result_set); + ORDER BY + time + LIMIT 144; `; const result = await this.clientStatisticsRepository.query(query, [address, clientName]); @@ -167,9 +170,9 @@ export class ClientStatisticsService { return result.map(res => { res.label = new Date(res.label).toISOString(); return res; - }); + }).slice(0, result.length - 1); + - return result; } @@ -177,43 +180,50 @@ export class ClientStatisticsService { const query = ` SELECT - (JULIANDAY(MAX(entry.time)) - JULIANDAY(MIN(entry.time))) * 24 * 60 * 60 AS timeDiff, - SUM(entry.difficulty) AS difficultySum + createdAt, + updatedAt, + shares FROM client_statistics_entity AS entry WHERE - entry.address = ? AND entry.clientName = ? AND entry.sessionId = ? AND entry.time > datetime("now", "-1 hour") + entry.address = ? AND entry.clientName = ? AND entry.sessionId = ? + ORDER BY time DESC + LIMIT 1; `; const result = await this.clientStatisticsRepository.query(query, [address, clientName, sessionId]); - const timeDiff = result[0].timeDiff; - const difficultySum = result[0].difficultySum; + if (result.length < 1) { + return 0; + } - return (difficultySum * 4294967296) / (timeDiff); + const time = new Date(result[0].updatedAt).getTime() - new Date(result[0].createdAt).getTime(); + + if (time < 1) { + return 0; + } + + return (result[0].shares * 4294967296) / (time / 1000); } public async getChartDataForSession(address: string, clientName: string, sessionId: string) { + var yesterday = new Date(new Date().getTime() - (24 * 60 * 60 * 1000)); + const query = ` - WITH result_set AS ( - SELECT - MAX(time) || 'GMT' AS label, - (SUM(difficulty) * 4294967296) / - ((JULIANDAY(MAX(time)) - JULIANDAY(MIN(time))) * 24 * 60 * 60) AS data - FROM - client_statistics_entity AS entry - WHERE - entry.address = ? AND entry.clientName = ? AND entry.sessionId = ? AND entry.time > datetime("now", "-1 day") - GROUP BY - strftime('%Y-%m-%d %H', time, 'localtime') || (strftime('%M', time, 'localtime') / 10) - ORDER BY - time - ) - SELECT * - FROM result_set - WHERE label <> (SELECT MAX(label) FROM result_set); + SELECT + time label, + (SUM(shares) * 4294967296) / 600 AS data + FROM + client_statistics_entity AS entry + WHERE + entry.address = ? AND entry.clientName = ? AND entry.sessionId = ? AND entry.time > ${yesterday.getTime()} + GROUP BY + time + ORDER BY + time + LIMIT 144; `; const result = await this.clientStatisticsRepository.query(query, [address, clientName, sessionId]); @@ -221,9 +231,8 @@ export class ClientStatisticsService { return result.map(res => { res.label = new Date(res.label).toISOString(); return res; - }); + }).slice(0, result.length - 1); - return result; } public async deleteAll() { diff --git a/src/app.controller.ts b/src/app.controller.ts index fb69c2d..5843d79 100644 --- a/src/app.controller.ts +++ b/src/app.controller.ts @@ -21,26 +21,30 @@ export class AppController { const blockData = await this.blocksService.getFoundBlocks(); const userAgents = await this.clientService.getUserAgents(); - const CACHE_KEY = 'SITE_HASHRATE_GRAPH'; - const cachedResult = await this.cacheManager.get(CACHE_KEY); - if (cachedResult != null) { - return { - chartData: cachedResult, - blockData, - userAgents - }; - } - - const chartData = [];// await this.clientStatisticsService.getChartDataForSite(); - - //5 min - await this.cacheManager.set(CACHE_KEY, chartData, 5 * 60 * 1000); - return { - chartData, blockData, userAgents }; } + @Get('info/chart') + public async infoChart() { + + + // const CACHE_KEY = 'SITE_HASHRATE_GRAPH'; + // const cachedResult = await this.cacheManager.get(CACHE_KEY); + + // if (cachedResult != null) { + // return cachedResult; + // } + + const chartData = await this.clientStatisticsService.getChartDataForSite(); + + //5 min + //await this.cacheManager.set(CACHE_KEY, chartData, 5 * 60 * 1000); + + return chartData; + + + } } diff --git a/src/controllers/client/client.controller.ts b/src/controllers/client/client.controller.ts index 1645828..4d10f74 100644 --- a/src/controllers/client/client.controller.ts +++ b/src/controllers/client/client.controller.ts @@ -20,12 +20,8 @@ export class ClientController { const workers = await this.clientService.getByAddress(address); - const chartData = await this.clientStatisticsService.getChartDataForAddress(address); - const addressSettings = await this.addressSettingsService.getSettings(address); - - return { bestDifficulty: addressSettings?.bestDifficulty, workersCount: workers.length, @@ -39,11 +35,16 @@ export class ClientController { startTime: worker.startTime }; }) - ), - chartData + ) } } + @Get(':address/chart') + async getClientInfoChart(@Param('address') address: string) { + const chartData = await this.clientStatisticsService.getChartDataForAddress(address); + return chartData; + } + @Get(':address/:workerName') async getWorkerGroupInfo(@Param('address') address: string, @Param('workerName') workerName: string) { diff --git a/src/models/StratumV1ClientStatistics.ts b/src/models/StratumV1ClientStatistics.ts index fa999a8..8fa3588 100644 --- a/src/models/StratumV1ClientStatistics.ts +++ b/src/models/StratumV1ClientStatistics.ts @@ -24,9 +24,14 @@ export class StratumV1ClientStatistics { difficulty: targetDifficulty, }); + // 10 min + var coeff = 1000 * 60 * 10; + var date = new Date(); + var rounded = new Date(Math.round(date.getTime() / coeff) * coeff); + await this.clientStatisticsService.save({ - time: new Date(), - difficulty: targetDifficulty, + time: rounded.getTime(), + shares: targetDifficulty, address: client.address, clientName: client.clientName, sessionId: client.sessionId, diff --git a/src/models/stratum-messages/SubscriptionMessage.ts b/src/models/stratum-messages/SubscriptionMessage.ts index 5402372..ed84421 100644 --- a/src/models/stratum-messages/SubscriptionMessage.ts +++ b/src/models/stratum-messages/SubscriptionMessage.ts @@ -14,7 +14,7 @@ export class SubscriptionMessage extends StratumBaseMessage { @IsString() @MaxLength(128) @Transform(({ value, key, obj, type }) => { - return obj.params[0] == null ? 'unknown' : SubscriptionMessage.refineUserAgent(obj.params); + return obj.params[0] == null ? 'unknown' : SubscriptionMessage.refineUserAgent(obj.params[0]); }) public userAgent: string;