mirror of
https://github.com/benjamin-wilson/public-pool.git
synced 2026-09-29 17:15:03 -07:00
db refactor
This commit is contained in:
@@ -0,0 +1,15 @@
|
||||
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||
|
||||
export class UniqueNonceIndex implements MigrationInterface {
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`CREATE UNIQUE INDEX "IDX_unique_nonce" ON "client_entity" ("sessionId") WHERE "deletedAt" IS NOT NULL`
|
||||
);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`DROP INDEX "IDX_unique_nonce"`);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -14,6 +14,9 @@ export class AddressSettingsEntity extends TrackedEntity {
|
||||
@Column({ type: 'decimal', default: 0 })
|
||||
bestDifficulty: number;
|
||||
|
||||
@Column({ nullable: true })
|
||||
bestDifficultyUserAgent: string;
|
||||
|
||||
@Column({ nullable: true })
|
||||
miscCoinbaseScriptData: string;
|
||||
|
||||
|
||||
@@ -17,13 +17,18 @@ export class AddressSettingsService {
|
||||
public async getSettings(address: string, createIfNotFound: boolean) {
|
||||
const settings = await this.addressSettingsRepository.findOne({ where: { address } });
|
||||
if (createIfNotFound == true && settings == null) {
|
||||
return await this.createNew(address);
|
||||
// It's possible to have a race condition here so if we get a PK violation, fetch it
|
||||
try {
|
||||
return await this.createNew(address);
|
||||
} catch (e) {
|
||||
return await this.addressSettingsRepository.findOne({ where: { address } });
|
||||
}
|
||||
}
|
||||
return settings;
|
||||
}
|
||||
|
||||
public async updateBestDifficulty(address: string, bestDifficulty: number) {
|
||||
return await this.addressSettingsRepository.update({ address }, { bestDifficulty });
|
||||
public async updateBestDifficulty(address: string, bestDifficulty: number, bestDifficultyUserAgent: string) {
|
||||
return await this.addressSettingsRepository.update({ address }, { bestDifficulty, bestDifficultyUserAgent });
|
||||
}
|
||||
|
||||
public async createNew(address: string) {
|
||||
@@ -46,4 +51,12 @@ export class AddressSettingsService {
|
||||
bestDifficulty: 0
|
||||
});
|
||||
}
|
||||
|
||||
public async getHighScores() {
|
||||
return await this.addressSettingsRepository.createQueryBuilder()
|
||||
.select('"updatedAt", "bestDifficulty", "bestDifficultyUserAgent"')
|
||||
.orderBy('"bestDifficulty"', 'DESC')
|
||||
.limit(10)
|
||||
.execute();
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,11 @@
|
||||
import { Column, Entity, Index, PrimaryGeneratedColumn } from 'typeorm';
|
||||
import { Column, Entity, Index, ManyToOne, PrimaryGeneratedColumn } from 'typeorm';
|
||||
|
||||
import { ClientEntity } from '../client/client.entity';
|
||||
import { TrackedEntity } from '../utils/TrackedEntity.entity';
|
||||
|
||||
@Entity()
|
||||
//Index for getHashRateForSession
|
||||
@Index(["address", "clientName", "sessionId"])
|
||||
//Index for statistics save
|
||||
@Index(["address", "clientName", "sessionId", "time"])
|
||||
@Index(["clientId", "time"])
|
||||
export class ClientStatisticsEntity extends TrackedEntity {
|
||||
|
||||
@PrimaryGeneratedColumn()
|
||||
@@ -32,4 +31,17 @@ export class ClientStatisticsEntity extends TrackedEntity {
|
||||
acceptedCount: number;
|
||||
|
||||
|
||||
|
||||
@ManyToOne(
|
||||
() => ClientEntity,
|
||||
clientEntity => clientEntity.statistics,
|
||||
{ nullable: false, }
|
||||
)
|
||||
client: ClientEntity;
|
||||
|
||||
@Index()
|
||||
@Column({ name: 'clientId' })
|
||||
public clientId: string;
|
||||
|
||||
|
||||
}
|
||||
@@ -19,25 +19,15 @@ export class ClientStatisticsService {
|
||||
}
|
||||
|
||||
public async save(clientStatistic: Partial<ClientStatisticsEntity>) {
|
||||
// Attempt to update the existing record
|
||||
const updateResult = await this.clientStatisticsRepository
|
||||
.createQueryBuilder()
|
||||
.update(ClientStatisticsEntity)
|
||||
.set({
|
||||
shares: () => `"shares" + :sharesIncrement`,
|
||||
acceptedCount: () => `"acceptedCount" + 1`
|
||||
// // Attempt to update the existing record
|
||||
const result = await this.clientStatisticsRepository.update({ clientId: clientStatistic.clientId, time: clientStatistic.time },
|
||||
{
|
||||
shares: clientStatistic.shares,
|
||||
acceptedCount: clientStatistic.acceptedCount
|
||||
})
|
||||
.where('address = :address AND clientName = :clientName AND sessionId = :sessionId AND time = :time', {
|
||||
address: clientStatistic.address,
|
||||
clientName: clientStatistic.clientName,
|
||||
sessionId: clientStatistic.sessionId,
|
||||
time: clientStatistic.time,
|
||||
sharesIncrement: clientStatistic.shares
|
||||
})
|
||||
.execute();
|
||||
|
||||
// Check if the update affected any rows
|
||||
if (updateResult.affected === 0) {
|
||||
if (result.affected === 0) {
|
||||
// If no rows were updated, insert a new record
|
||||
await this.clientStatisticsRepository.insert(clientStatistic);
|
||||
}
|
||||
@@ -139,7 +129,7 @@ export class ClientStatisticsService {
|
||||
}
|
||||
|
||||
|
||||
public async getHashRateForSession(address: string, clientName: string, sessionId: string) {
|
||||
public async getHashRateForSession(clientId: string) {
|
||||
|
||||
const query = `
|
||||
SELECT
|
||||
@@ -149,12 +139,12 @@ export class ClientStatisticsService {
|
||||
FROM
|
||||
client_statistics_entity AS entry
|
||||
WHERE
|
||||
entry.address = $1 AND entry."clientName" = $2 AND entry."sessionId" = $3
|
||||
entry."clientId" = $1
|
||||
ORDER BY time DESC
|
||||
LIMIT 2;
|
||||
`;
|
||||
|
||||
const result = await this.clientStatisticsRepository.query(query, [address, clientName, sessionId]);
|
||||
const result = await this.clientStatisticsRepository.query(query, [clientId]);
|
||||
|
||||
if (result.length < 1) {
|
||||
return 0;
|
||||
@@ -179,7 +169,7 @@ export class ClientStatisticsService {
|
||||
|
||||
}
|
||||
|
||||
public async getChartDataForSession(address: string, clientName: string, sessionId: string) {
|
||||
public async getChartDataForSession(clientId: string) {
|
||||
var yesterday = new Date(new Date().getTime() - (24 * 60 * 60 * 1000));
|
||||
|
||||
const query = `
|
||||
@@ -189,7 +179,7 @@ export class ClientStatisticsService {
|
||||
FROM
|
||||
client_statistics_entity AS entry
|
||||
WHERE
|
||||
entry.address = $1 AND entry."clientName" = $2 AND entry."sessionId" = $3 AND entry.time > ${yesterday.getTime()}
|
||||
entry."clientId" = $1 AND entry.time > ${yesterday.getTime()}
|
||||
GROUP BY
|
||||
time
|
||||
ORDER BY
|
||||
@@ -197,7 +187,7 @@ export class ClientStatisticsService {
|
||||
LIMIT 144;
|
||||
`;
|
||||
|
||||
const result = await this.clientStatisticsRepository.query(query, [address, clientName, sessionId]);
|
||||
const result = await this.clientStatisticsRepository.query(query, [clientId]);
|
||||
|
||||
return result.map(res => {
|
||||
res.label = new Date(parseInt(res.label)).toISOString();
|
||||
|
||||
@@ -1,21 +1,24 @@
|
||||
import { Column, Entity, Index, PrimaryColumn } from 'typeorm';
|
||||
import { Column, Entity, Index, OneToMany, PrimaryGeneratedColumn } from 'typeorm';
|
||||
|
||||
import { ClientStatisticsEntity } from '../client-statistics/client-statistics.entity';
|
||||
import { TrackedEntity } from '../utils/TrackedEntity.entity';
|
||||
|
||||
|
||||
@Entity()
|
||||
@Index(['address', 'clientName', 'sessionId'], { unique: true })
|
||||
@Index("IDX_unique_nonce", { synchronize: false })
|
||||
export class ClientEntity extends TrackedEntity {
|
||||
|
||||
|
||||
@PrimaryColumn({ length: 62, type: 'varchar' })
|
||||
address: string;
|
||||
|
||||
@PrimaryColumn({ length: 64, type: 'varchar' })
|
||||
clientName: string;
|
||||
@PrimaryGeneratedColumn('uuid')
|
||||
id: string;
|
||||
|
||||
@Index()
|
||||
@PrimaryColumn({ length: 8, type: 'varchar' })
|
||||
@Column({ length: 62, type: 'varchar' })
|
||||
address: string;
|
||||
|
||||
@Column({ length: 64, type: 'varchar' })
|
||||
clientName: string;
|
||||
|
||||
@Column({ length: 8, type: 'varchar', })
|
||||
sessionId: string;
|
||||
|
||||
|
||||
@@ -23,7 +26,6 @@ export class ClientEntity extends TrackedEntity {
|
||||
userAgent: string;
|
||||
|
||||
|
||||
|
||||
@Column({ type: 'timestamp' })
|
||||
startTime: Date;
|
||||
|
||||
@@ -33,5 +35,11 @@ export class ClientEntity extends TrackedEntity {
|
||||
@Column({ default: 0, type: 'decimal' })
|
||||
hashRate: number;
|
||||
|
||||
@OneToMany(
|
||||
() => ClientStatisticsEntity,
|
||||
clientStatisticsEntity => clientStatisticsEntity.client
|
||||
)
|
||||
statistics: ClientStatisticsEntity[]
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -28,8 +28,8 @@ export class ClientService {
|
||||
.execute();
|
||||
}
|
||||
|
||||
public async heartbeat(address: string, clientName: string, sessionId: string, hashRate: number, updatedAt: Date) {
|
||||
return await this.clientRepository.update({ address, clientName, sessionId }, { hashRate, deletedAt: null, updatedAt });
|
||||
public async heartbeat(id, hashRate: number, updatedAt: Date) {
|
||||
return await this.clientRepository.update({ id }, { hashRate, deletedAt: null, updatedAt });
|
||||
}
|
||||
|
||||
// public async save(client: Partial<ClientEntity>) {
|
||||
@@ -48,8 +48,8 @@ export class ClientService {
|
||||
return client as ClientEntity;
|
||||
}
|
||||
|
||||
public async delete(sessionId: string) {
|
||||
return await this.clientRepository.softDelete({ sessionId });
|
||||
public async delete(id: string) {
|
||||
return await this.clientRepository.softDelete({ id });
|
||||
}
|
||||
|
||||
public async deleteOldClients() {
|
||||
@@ -65,8 +65,8 @@ export class ClientService {
|
||||
|
||||
}
|
||||
|
||||
public async updateBestDifficulty(sessionId: string, bestDifficulty: number) {
|
||||
return await this.clientRepository.update({ sessionId }, { bestDifficulty });
|
||||
public async updateBestDifficulty(id: string, bestDifficulty: number) {
|
||||
return await this.clientRepository.update({ id }, { bestDifficulty });
|
||||
}
|
||||
public async connectedClientCount(): Promise<number> {
|
||||
return await this.clientRepository.count();
|
||||
@@ -111,7 +111,7 @@ export class ClientService {
|
||||
.addSelect('MAX(client.bestDifficulty)', 'bestDifficulty')
|
||||
.addSelect('SUM(client.hashRate)', 'totalHashRate')
|
||||
.groupBy('client.userAgent')
|
||||
.orderBy('count', 'DESC')
|
||||
.orderBy('"totalHashRate"', 'DESC')
|
||||
.getRawMany();
|
||||
return result;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user