data rework

This commit is contained in:
Ben Wilson 2023-08-01 22:39:02 -04:00
parent d718df88cd
commit 5dd1fa3dfa
7 changed files with 140 additions and 124 deletions

2
.gitignore vendored
View File

@ -37,4 +37,4 @@ settings.json
!.vscode/extensions.json !.vscode/extensions.json
#DB #DB
**.sqlite **.sqlite**

View File

@ -1,6 +1,5 @@
import { Column, Entity, Index, PrimaryColumn } from 'typeorm'; import { Column, Entity, Index, PrimaryColumn } from 'typeorm';
import { DateTimeTransformer } from '../utils/DateTimeTransformer';
import { TrackedEntity } from '../utils/TrackedEntity.entity'; import { TrackedEntity } from '../utils/TrackedEntity.entity';
@Entity() @Entity()
@ -9,6 +8,7 @@ export class ClientStatisticsEntity extends TrackedEntity {
@PrimaryColumn({ length: 64, type: 'varchar' }) @PrimaryColumn({ length: 64, type: 'varchar' })
submissionHash: string; submissionHash: string;
@Index()
@Column({ length: 62, type: 'varchar' }) @Column({ length: 62, type: 'varchar' })
address: string; address: string;
@ -20,14 +20,11 @@ export class ClientStatisticsEntity extends TrackedEntity {
sessionId: string; sessionId: string;
@Index() @Index()
@Column({ @Column({ type: 'integer' })
type: 'datetime', time: number;
transformer: new DateTimeTransformer()
})
time: Date;
@Column({ type: 'real' }) @Column({ type: 'real' })
difficulty: number; shares: number;

View File

@ -18,7 +18,17 @@ export class ClientStatisticsService {
} }
public async save(clientStatistic: Partial<ClientStatisticsEntity>) { public async save(clientStatistic: Partial<ClientStatisticsEntity>) {
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() { public async deleteOldStatistics() {
@ -34,79 +44,74 @@ export class ClientStatisticsService {
public async getChartDataForSite() { public async getChartDataForSite() {
var yesterday = new Date(new Date().getTime() - (24 * 60 * 60 * 1000));
const query = ` const query = `
WITH result_set AS (
SELECT SELECT
MAX(time) || 'GMT' AS label, time AS label,
(SUM(difficulty) * 4294967296) / ROUND(((SUM(shares) * 4294967296) / 600)) AS data
((JULIANDAY(MAX(time)) - JULIANDAY(MIN(time))) * 24 * 60 * 60) AS data
FROM FROM
client_statistics_entity AS entry client_statistics_entity AS entry
WHERE WHERE
entry.time > datetime("now", "-1 day") entry.time > ${yesterday.getTime()}
GROUP BY GROUP BY
strftime('%Y-%m-%d %H', time, 'localtime') || (strftime('%M', time, 'localtime') / 10) time
ORDER BY ORDER BY
time time
) LIMIT 144;
SELECT *
FROM result_set
WHERE label <> (SELECT MAX(label) FROM result_set);
`; `;
const result = await this.clientStatisticsRepository.query(query); const result: any[] = await this.clientStatisticsRepository.query(query);
return result.map(res => { return result.map(res => {
res.label = new Date(res.label).toISOString(); res.label = new Date(res.label).toISOString();
return res; return res;
}); }).slice(0, result.length - 1)
} }
public async getHashRateForAddress(address: string) { // public async getHashRateForAddress(address: string) {
const query = ` // const oneHour = new Date(new Date().getTime() - (60 * 60 * 1000));
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 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 result = await this.clientStatisticsRepository.query(query, [address]);
const difficultySum = result[0].difficultySum;
return (difficultySum * 4294967296) / (timeDiff); // const difficultySum = result[0].difficultySum;
} // return (difficultySum * 4294967296) / (600);
// }
public async getChartDataForAddress(address: string) { public async getChartDataForAddress(address: string) {
var yesterday = new Date(new Date().getTime() - (24 * 60 * 60 * 1000));
const query = ` const query = `
WITH result_set AS (
SELECT SELECT
MAX(time) || 'GMT' AS label, time label,
(SUM(difficulty) * 4294967296) / (SUM(shares) * 4294967296) / 600 AS data
((JULIANDAY(MAX(time)) - JULIANDAY(MIN(time))) * 24 * 60 * 60) AS data
FROM FROM
client_statistics_entity AS entry client_statistics_entity AS entry
WHERE WHERE
entry.address = ? AND entry.time > datetime("now", "-1 day") entry.address = ? AND entry.time > ${yesterday.getTime()}
GROUP BY GROUP BY
strftime('%Y-%m-%d %H', time, 'localtime') || (strftime('%M', time, 'localtime') / 10) time
ORDER BY ORDER BY
time time
) LIMIT 144;
SELECT *
FROM result_set
WHERE label <> (SELECT MAX(label) FROM result_set);
`; `;
const result = await this.clientStatisticsRepository.query(query, [address]); const result = await this.clientStatisticsRepository.query(query, [address]);
@ -114,52 +119,50 @@ export class ClientStatisticsService {
return result.map(res => { return result.map(res => {
res.label = new Date(res.label).toISOString(); res.label = new Date(res.label).toISOString();
return res; return res;
}); }).slice(0, result.length - 1);
return result;
} }
public async getHashRateForGroup(address: string, clientName: string) { public async getHashRateForGroup(address: string, clientName: string) {
var oneHour = new Date(new Date().getTime() - (60 * 60 * 1000));
const query = ` const query = `
SELECT SELECT
(JULIANDAY(MAX(entry.time)) - JULIANDAY(MIN(entry.time))) * 24 * 60 * 60 AS timeDiff, SUM(entry.shares) AS difficultySum
SUM(entry.difficulty) AS difficultySum
FROM FROM
client_statistics_entity AS entry client_statistics_entity AS entry
WHERE 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 result = await this.clientStatisticsRepository.query(query, [address, clientName]);
const timeDiff = result[0].timeDiff;
const difficultySum = result[0].difficultySum; const difficultySum = result[0].difficultySum;
return (difficultySum * 4294967296) / (timeDiff); return (difficultySum * 4294967296) / (600);
} }
public async getChartDataForGroup(address: string, clientName: string) { public async getChartDataForGroup(address: string, clientName: string) {
var yesterday = new Date(new Date().getTime() - (24 * 60 * 60 * 1000));
const query = ` const query = `
WITH result_set AS ( SELECT
SELECT time label,
MAX(time) || 'GMT' AS label, (SUM(shares) * 4294967296) / 600 AS data
(SUM(difficulty) * 4294967296) / FROM
((JULIANDAY(MAX(time)) - JULIANDAY(MIN(time))) * 24 * 60 * 60) AS data client_statistics_entity AS entry
FROM WHERE
client_statistics_entity AS entry entry.address = ? AND entry.clientName = ? AND entry.time > ${yesterday.getTime()}
WHERE GROUP BY
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
time time
) ORDER BY
SELECT * time
FROM result_set LIMIT 144;
WHERE label <> (SELECT MAX(label) FROM result_set);
`; `;
const result = await this.clientStatisticsRepository.query(query, [address, clientName]); const result = await this.clientStatisticsRepository.query(query, [address, clientName]);
@ -167,9 +170,9 @@ export class ClientStatisticsService {
return result.map(res => { return result.map(res => {
res.label = new Date(res.label).toISOString(); res.label = new Date(res.label).toISOString();
return res; return res;
}); }).slice(0, result.length - 1);
return result;
} }
@ -177,43 +180,50 @@ export class ClientStatisticsService {
const query = ` const query = `
SELECT SELECT
(JULIANDAY(MAX(entry.time)) - JULIANDAY(MIN(entry.time))) * 24 * 60 * 60 AS timeDiff, createdAt,
SUM(entry.difficulty) AS difficultySum updatedAt,
shares
FROM FROM
client_statistics_entity AS entry client_statistics_entity AS entry
WHERE 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 result = await this.clientStatisticsRepository.query(query, [address, clientName, sessionId]);
const timeDiff = result[0].timeDiff; if (result.length < 1) {
const difficultySum = result[0].difficultySum; 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) { public async getChartDataForSession(address: string, clientName: string, sessionId: string) {
var yesterday = new Date(new Date().getTime() - (24 * 60 * 60 * 1000));
const query = ` const query = `
WITH result_set AS ( SELECT
SELECT time label,
MAX(time) || 'GMT' AS label, (SUM(shares) * 4294967296) / 600 AS data
(SUM(difficulty) * 4294967296) / FROM
((JULIANDAY(MAX(time)) - JULIANDAY(MIN(time))) * 24 * 60 * 60) AS data client_statistics_entity AS entry
FROM WHERE
client_statistics_entity AS entry entry.address = ? AND entry.clientName = ? AND entry.sessionId = ? AND entry.time > ${yesterday.getTime()}
WHERE GROUP BY
entry.address = ? AND entry.clientName = ? AND entry.sessionId = ? AND entry.time > datetime("now", "-1 day") time
GROUP BY ORDER BY
strftime('%Y-%m-%d %H', time, 'localtime') || (strftime('%M', time, 'localtime') / 10) time
ORDER BY LIMIT 144;
time
)
SELECT *
FROM result_set
WHERE label <> (SELECT MAX(label) FROM result_set);
`; `;
const result = await this.clientStatisticsRepository.query(query, [address, clientName, sessionId]); const result = await this.clientStatisticsRepository.query(query, [address, clientName, sessionId]);
@ -221,9 +231,8 @@ export class ClientStatisticsService {
return result.map(res => { return result.map(res => {
res.label = new Date(res.label).toISOString(); res.label = new Date(res.label).toISOString();
return res; return res;
}); }).slice(0, result.length - 1);
return result;
} }
public async deleteAll() { public async deleteAll() {

View File

@ -21,26 +21,30 @@ export class AppController {
const blockData = await this.blocksService.getFoundBlocks(); const blockData = await this.blocksService.getFoundBlocks();
const userAgents = await this.clientService.getUserAgents(); 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 { return {
chartData,
blockData, blockData,
userAgents 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;
}
} }

View File

@ -20,12 +20,8 @@ export class ClientController {
const workers = await this.clientService.getByAddress(address); const workers = await this.clientService.getByAddress(address);
const chartData = await this.clientStatisticsService.getChartDataForAddress(address);
const addressSettings = await this.addressSettingsService.getSettings(address); const addressSettings = await this.addressSettingsService.getSettings(address);
return { return {
bestDifficulty: addressSettings?.bestDifficulty, bestDifficulty: addressSettings?.bestDifficulty,
workersCount: workers.length, workersCount: workers.length,
@ -39,11 +35,16 @@ export class ClientController {
startTime: worker.startTime 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') @Get(':address/:workerName')
async getWorkerGroupInfo(@Param('address') address: string, @Param('workerName') workerName: string) { async getWorkerGroupInfo(@Param('address') address: string, @Param('workerName') workerName: string) {

View File

@ -24,9 +24,14 @@ export class StratumV1ClientStatistics {
difficulty: targetDifficulty, 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({ await this.clientStatisticsService.save({
time: new Date(), time: rounded.getTime(),
difficulty: targetDifficulty, shares: targetDifficulty,
address: client.address, address: client.address,
clientName: client.clientName, clientName: client.clientName,
sessionId: client.sessionId, sessionId: client.sessionId,

View File

@ -14,7 +14,7 @@ export class SubscriptionMessage extends StratumBaseMessage {
@IsString() @IsString()
@MaxLength(128) @MaxLength(128)
@Transform(({ value, key, obj, type }) => { @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; public userAgent: string;