mirror of
https://github.com/benjamin-wilson/public-pool.git
synced 2026-09-29 09:05:06 -07:00
msic
This commit is contained in:
@@ -1,13 +1,22 @@
|
|||||||
import { Column, Entity, ManyToOne, PrimaryGeneratedColumn } from 'typeorm';
|
import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';
|
||||||
|
|
||||||
import { ClientEntity } from '../client/client.entity';
|
import { TrackedEntity } from '../utils/TrackedEntity.entity';
|
||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
export class ClientStatisticsEntity {
|
export class ClientStatisticsEntity extends TrackedEntity {
|
||||||
|
|
||||||
@PrimaryGeneratedColumn()
|
@PrimaryGeneratedColumn()
|
||||||
id: number;
|
id: number;
|
||||||
|
|
||||||
|
@Column({ length: 62, type: 'varchar' })
|
||||||
|
address: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
clientName: string;
|
||||||
|
|
||||||
|
@Column({ length: 8, type: 'varchar' })
|
||||||
|
sessionId: string;
|
||||||
|
|
||||||
@Column({ type: 'datetime' })
|
@Column({ type: 'datetime' })
|
||||||
time: Date;
|
time: Date;
|
||||||
|
|
||||||
@@ -15,10 +24,6 @@ export class ClientStatisticsEntity {
|
|||||||
difficulty: number;
|
difficulty: number;
|
||||||
|
|
||||||
|
|
||||||
@ManyToOne(
|
|
||||||
() => ClientEntity,
|
|
||||||
client => client.clientStatistics
|
|
||||||
)
|
|
||||||
client: ClientEntity;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -19,7 +19,7 @@ export class ClientStatisticsService {
|
|||||||
return await this.clientStatisticsRepository.save(clientStatistic);
|
return await this.clientStatisticsRepository.save(clientStatistic);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getHashRate(clientId: string) {
|
public async getHashRate(sessionId: string) {
|
||||||
|
|
||||||
const query = `
|
const query = `
|
||||||
SELECT
|
SELECT
|
||||||
@@ -28,10 +28,10 @@ export class ClientStatisticsService {
|
|||||||
FROM
|
FROM
|
||||||
client_statistics_entity AS entry
|
client_statistics_entity AS entry
|
||||||
WHERE
|
WHERE
|
||||||
entry.clientId = ?
|
entry.sessionId = ? AND entry.time > datetime("now", "-1 hour")
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const result = await this.clientStatisticsRepository.query(query, [clientId]);
|
const result = await this.clientStatisticsRepository.query(query, [sessionId]);
|
||||||
|
|
||||||
const timeDiff = result[0].timeDiff;
|
const timeDiff = result[0].timeDiff;
|
||||||
const difficultySum = result[0].difficultySum;
|
const difficultySum = result[0].difficultySum;
|
||||||
@@ -39,4 +39,32 @@ export class ClientStatisticsService {
|
|||||||
return (difficultySum * 4294967296) / (timeDiff * 1000000000);
|
return (difficultySum * 4294967296) / (timeDiff * 1000000000);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async getChartData(sessionId: string) {
|
||||||
|
const query = `
|
||||||
|
WITH result_set AS (
|
||||||
|
SELECT
|
||||||
|
MAX(time) AS label,
|
||||||
|
(SUM(difficulty) * 4294967296) /
|
||||||
|
((JULIANDAY(MAX(time)) - JULIANDAY(MIN(time))) * 24 * 60 * 60 * 1000000000) AS data
|
||||||
|
FROM
|
||||||
|
client_statistics_entity AS entry
|
||||||
|
WHERE
|
||||||
|
entry.sessionId = ? AND entry.time > datetime("now", "-1 day")
|
||||||
|
GROUP BY
|
||||||
|
strftime('%Y-%m-%d %H', time, 'localtime') || (strftime('%M', time, 'localtime') / 5)
|
||||||
|
)
|
||||||
|
SELECT *
|
||||||
|
FROM result_set
|
||||||
|
WHERE label <> (SELECT MAX(Label) FROM result_set);
|
||||||
|
`;
|
||||||
|
|
||||||
|
const result = await this.clientStatisticsRepository.query(query, [sessionId]);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async deleteAll() {
|
||||||
|
return await this.clientStatisticsRepository.delete({})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,29 +1,32 @@
|
|||||||
import { Column, Entity, OneToMany, PrimaryColumn } from 'typeorm';
|
import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';
|
||||||
|
|
||||||
import { ClientStatisticsEntity } from '../client-statistics/client-statistics.entity';
|
|
||||||
import { TrackedEntity } from '../utils/TrackedEntity.entity';
|
import { TrackedEntity } from '../utils/TrackedEntity.entity';
|
||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
export class ClientEntity extends TrackedEntity {
|
export class ClientEntity extends TrackedEntity {
|
||||||
@PrimaryColumn({ length: 8, type: 'varchar' })
|
|
||||||
id: string;
|
|
||||||
|
|
||||||
@Column({ type: 'datetime' })
|
@PrimaryGeneratedColumn()
|
||||||
startTime: Date;
|
id: number;
|
||||||
|
|
||||||
@Column()
|
|
||||||
clientName: string;
|
|
||||||
|
|
||||||
@Column({ length: 62, type: 'varchar' })
|
@Column({ length: 62, type: 'varchar' })
|
||||||
address: string;
|
address: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
clientName: string;
|
||||||
|
|
||||||
|
@Column({ length: 8, type: 'varchar' })
|
||||||
|
sessionId: string;
|
||||||
|
|
||||||
|
@Column({ type: 'datetime' })
|
||||||
|
startTime: Date;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Column({ default: 0 })
|
@Column({ default: 0 })
|
||||||
bestDifficulty: number
|
bestDifficulty: number
|
||||||
|
|
||||||
@OneToMany(
|
|
||||||
() => ClientStatisticsEntity,
|
|
||||||
clientStatistic => clientStatistic.client
|
|
||||||
)
|
|
||||||
clientStatistics?: ClientStatisticsEntity[];
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,12 +21,12 @@ export class ClientService {
|
|||||||
return await this.clientRepository.save(client);
|
return await this.clientRepository.save(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async delete(id: string) {
|
public async delete(sessionId: string) {
|
||||||
return await this.clientRepository.softDelete({ id });
|
return await this.clientRepository.softDelete({ sessionId });
|
||||||
}
|
}
|
||||||
|
|
||||||
public async updateBestDifficulty(id: string, bestDifficulty: number) {
|
public async updateBestDifficulty(sessionId: string, bestDifficulty: number) {
|
||||||
return await this.clientRepository.update(id, { bestDifficulty });
|
return await this.clientRepository.update({ sessionId }, { bestDifficulty });
|
||||||
}
|
}
|
||||||
public async connectedClientCount(): Promise<number> {
|
public async connectedClientCount(): Promise<number> {
|
||||||
return await this.clientRepository.count();
|
return await this.clientRepository.count();
|
||||||
@@ -40,12 +40,17 @@ export class ClientService {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getByAddressAndName(address: string, id: string): Promise<ClientEntity> {
|
public async getById(address: string, clientName: string, sessionId: string): Promise<ClientEntity> {
|
||||||
return await this.clientRepository.findOne({
|
return await this.clientRepository.findOne({
|
||||||
where: {
|
where: {
|
||||||
address,
|
address,
|
||||||
id
|
clientName,
|
||||||
|
sessionId
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async deleteAll() {
|
||||||
|
return await this.clientRepository.softDelete({})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
import { Test, TestingModule } from '@nestjs/testing';
|
import { Test, TestingModule } from '@nestjs/testing';
|
||||||
|
|
||||||
import { AppController } from './app.controller';
|
import { AppController } from './app.controller';
|
||||||
import { AppService } from './app.service';
|
import { AppService } from './app.service';
|
||||||
|
|
||||||
@@ -16,7 +17,7 @@ describe('AppController', () => {
|
|||||||
|
|
||||||
describe('root', () => {
|
describe('root', () => {
|
||||||
it('should return "Hello World!"', () => {
|
it('should return "Hello World!"', () => {
|
||||||
expect(appController.getHello()).toBe('Hello World!');
|
// expect(appController.getHello()).toBe('Hello World!');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
+21
-13
@@ -1,4 +1,4 @@
|
|||||||
import { Controller, Get, Param } from '@nestjs/common';
|
import { Controller, Get, NotFoundException, Param } from '@nestjs/common';
|
||||||
|
|
||||||
import { AppService } from './app.service';
|
import { AppService } from './app.service';
|
||||||
import { ClientStatisticsService } from './ORM/client-statistics/client-statistics.service';
|
import { ClientStatisticsService } from './ORM/client-statistics/client-statistics.service';
|
||||||
@@ -21,21 +21,21 @@ export class AppController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get('client/:clientId')
|
@Get('client/:address')
|
||||||
async getClientInfo(@Param('clientId') clientId: string) {
|
async getClientInfo(@Param('address') address: string) {
|
||||||
|
|
||||||
|
const workers = await this.clientService.getByAddress(address);
|
||||||
|
|
||||||
const workers = await this.clientService.getByAddress(clientId);
|
|
||||||
|
|
||||||
//const workers = this.stratumV1Service.clients.filter(client => client.clientAuthorization.address === clientId);
|
|
||||||
return {
|
return {
|
||||||
workersCount: workers.length,
|
workersCount: workers.length,
|
||||||
workers: await Promise.all(
|
workers: await Promise.all(
|
||||||
workers.map(async (worker) => {
|
workers.map(async (worker) => {
|
||||||
return {
|
return {
|
||||||
id: worker.id,
|
sessionId: worker.sessionId,
|
||||||
name: worker.clientName,
|
name: worker.clientName,
|
||||||
bestDifficulty: Math.floor(worker.bestDifficulty),
|
bestDifficulty: Math.floor(worker.bestDifficulty),
|
||||||
hashRate: Math.floor(await this.clientStatisticsService.getHashRate(worker.id)),
|
hashRate: Math.floor(await this.clientStatisticsService.getHashRate(worker.sessionId)),
|
||||||
startTime: worker.startTime
|
startTime: worker.startTime
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
@@ -43,17 +43,25 @@ export class AppController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get('client/:clientId/:workerId')
|
@Get('client/:address/:workerName')
|
||||||
async getWorkerInfo(@Param('clientId') clientId: string, @Param('workerId') workerId: string) {
|
async getWorkerGroupInfo(@Param('address') address: string, @Param('address') workerName: string) {
|
||||||
|
|
||||||
const worker = await this.clientService.getByAddressAndName(clientId, workerId);
|
}
|
||||||
|
|
||||||
|
@Get('client/:address/:workerName/:sessionId')
|
||||||
|
async getWorkerInfo(@Param('address') address: string, @Param('workerName') workerName: string, @Param('sessionId') sessionId: string) {
|
||||||
|
|
||||||
|
const worker = await this.clientService.getById(address, workerName, sessionId);
|
||||||
|
if (worker == null) {
|
||||||
|
return new NotFoundException();
|
||||||
|
}
|
||||||
|
const chartData = await this.clientStatisticsService.getChartData(sessionId);
|
||||||
|
|
||||||
//const worker = this.stratumV1Service.clients.find(client => client.clientAuthorization.address === clientId && client.id === workerId);
|
|
||||||
return {
|
return {
|
||||||
id: worker.id,
|
sessionId: worker.sessionId,
|
||||||
name: worker.clientName,
|
name: worker.clientName,
|
||||||
bestDifficulty: Math.floor(worker.bestDifficulty),
|
bestDifficulty: Math.floor(worker.bestDifficulty),
|
||||||
//hashData: worker.statistics.historicSubmissions,
|
chartData: chartData,
|
||||||
startTime: worker.startTime
|
startTime: worker.startTime
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -19,7 +19,7 @@ async function bootstrap() {
|
|||||||
app.enableCors();
|
app.enableCors();
|
||||||
|
|
||||||
await app.listen(process.env.PORT, '0.0.0.0', () => {
|
await app.listen(process.env.PORT, '0.0.0.0', () => {
|
||||||
console.log(`https listening on port ${process.env.PORT}`);
|
console.log(`http listening on port ${process.env.PORT}`);
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -223,7 +223,7 @@ export class StratumV1Client extends EasyUnsubscribe {
|
|||||||
|
|
||||||
|
|
||||||
this.entity = await this.clientService.save({
|
this.entity = await this.clientService.save({
|
||||||
id: this.id,
|
sessionId: this.id,
|
||||||
address: this.clientAuthorization.address,
|
address: this.clientAuthorization.address,
|
||||||
clientName: this.clientAuthorization.worker,
|
clientName: this.clientAuthorization.worker,
|
||||||
startTime: new Date(),
|
startTime: new Date(),
|
||||||
@@ -268,6 +268,7 @@ export class StratumV1Client extends EasyUnsubscribe {
|
|||||||
await this.statistics.addSubmission(this.entity, this.clientDifficulty);
|
await this.statistics.addSubmission(this.entity, this.clientDifficulty);
|
||||||
if (diff > this.entity.bestDifficulty) {
|
if (diff > this.entity.bestDifficulty) {
|
||||||
await this.clientService.updateBestDifficulty(this.id, diff);
|
await this.clientService.updateBestDifficulty(this.id, diff);
|
||||||
|
this.entity.bestDifficulty = diff;
|
||||||
}
|
}
|
||||||
if (diff >= (networkDifficulty / 2)) {
|
if (diff >= (networkDifficulty / 2)) {
|
||||||
console.log('!!! BOCK FOUND !!!');
|
console.log('!!! BOCK FOUND !!!');
|
||||||
|
|||||||
@@ -13,7 +13,10 @@ export class StratumV1ClientStatistics {
|
|||||||
await this.clientStatisticsService.save({
|
await this.clientStatisticsService.save({
|
||||||
time: new Date(),
|
time: new Date(),
|
||||||
difficulty: targetDifficulty,
|
difficulty: targetDifficulty,
|
||||||
client
|
address: client.address,
|
||||||
|
clientName: client.clientName,
|
||||||
|
sessionId: client.sessionId,
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,9 @@ export class StratumV1Service implements OnModuleInit {
|
|||||||
|
|
||||||
async onModuleInit(): Promise<void> {
|
async onModuleInit(): Promise<void> {
|
||||||
|
|
||||||
|
//await this.clientStatisticsService.deleteAll();
|
||||||
|
await this.clientService.deleteAll();
|
||||||
|
|
||||||
this.startSocketServer();
|
this.startSocketServer();
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -50,9 +53,14 @@ export class StratumV1Service implements OnModuleInit {
|
|||||||
console.log(`Client disconnected: ${socket.remoteAddress}, ${clientCount} total clients`);
|
console.log(`Client disconnected: ${socket.remoteAddress}, ${clientCount} total clients`);
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on('error', (error: Error) => {
|
socket.on('error', async (error: Error) => {
|
||||||
// Handle socket error, usually a reset?
|
|
||||||
|
await this.clientService.delete(client.id);
|
||||||
|
|
||||||
|
const clientCount = await this.clientService.connectedClientCount();
|
||||||
console.error(`Socket error:`, error);
|
console.error(`Socket error:`, error);
|
||||||
|
console.log(`Client disconnected: ${socket.remoteAddress}, ${clientCount} total clients`);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
}).listen(3333, () => {
|
}).listen(3333, () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user