Optimize SV1 block notify fanout

This commit is contained in:
Ben
2026-07-13 11:55:26 -04:00
parent 3d58802feb
commit c60264bbe5
17 changed files with 1799 additions and 169 deletions
+41 -1
View File
@@ -12,6 +12,7 @@ describe('StratumV1Service', () => {
const originalTlsHandshakeTimeoutMs = process.env.STRATUM_TLS_HANDSHAKE_TIMEOUT_MS;
const originalSocketTimeoutMs = process.env.STRATUM_SOCKET_TIMEOUT_MS;
const originalTcpKeepAliveInitialDelayMs = process.env.STRATUM_TCP_KEEPALIVE_INITIAL_DELAY_MS;
const originalFanoutTargetClientsPerWorker = process.env.STRATUM_FANOUT_TARGET_CLIENTS_PER_WORKER;
let service: StratumV1Service;
let clientService;
@@ -19,6 +20,7 @@ describe('StratumV1Service', () => {
let stratumV2Service;
let redisMessagingService;
let miningJobs: Subject<any>;
let prestageJobs: Subject<any>;
let consoleLogSpy: jest.SpyInstance;
let consoleWarnSpy: jest.SpyInstance;
@@ -36,13 +38,17 @@ describe('StratumV1Service', () => {
};
redisMessagingService = {};
miningJobs = new Subject();
prestageJobs = new Subject();
service = new StratumV1Service(
{} as any,
clientService,
{} as any,
{} as any,
{} as any,
{ newMiningJob$: miningJobs.asObservable() } as any,
{
newMiningJob$: miningJobs.asObservable(),
sv1PrestageJob$: prestageJobs.asObservable(),
} as any,
{} as any,
stratumV2Service as any,
userAgentReportService as any,
@@ -63,6 +69,7 @@ describe('StratumV1Service', () => {
restoreEnv('STRATUM_TLS_HANDSHAKE_TIMEOUT_MS', originalTlsHandshakeTimeoutMs);
restoreEnv('STRATUM_SOCKET_TIMEOUT_MS', originalSocketTimeoutMs);
restoreEnv('STRATUM_TCP_KEEPALIVE_INITIAL_DELAY_MS', originalTcpKeepAliveInitialDelayMs);
restoreEnv('STRATUM_FANOUT_TARGET_CLIENTS_PER_WORKER', originalFanoutTargetClientsPerWorker);
consoleLogSpy.mockRestore();
consoleWarnSpy.mockRestore();
jest.useRealTimers();
@@ -137,6 +144,7 @@ describe('StratumV1Service', () => {
});
it('enqueues a 100,000-client fanout without per-client async serialization', () => {
process.env.STRATUM_FANOUT_TARGET_CLIENTS_PER_WORKER = '10000';
const clientCount = 100_000;
let writes = 0;
const broadcastMiningJob = () => {
@@ -166,6 +174,8 @@ describe('StratumV1Service', () => {
event: 'stratum_job_fanout',
eventId: 'load-test',
clients: clientCount,
targetClientsPerWorker: 10_000,
overTargetClients: 90_000,
written: clientCount,
}));
expect(trace.milestoneMs).toEqual(expect.objectContaining({
@@ -176,6 +186,36 @@ describe('StratumV1Service', () => {
expect(trace.totalMs).toBeLessThan(1_000);
});
it('pre-stages next-height jobs for connected miners without broadcasting them', async () => {
process.env.MASTER = 'false';
process.env.STRATUM_PORTS = '';
process.env.STRATUM_SECURE = 'false';
const clients = Array.from({ length: 3 }, () => ({
preStageMiningJob: jest.fn().mockReturnValue(true),
broadcastMiningJob: jest.fn(),
}));
clients.forEach(client => (service as any).clients.add(client));
await service.onModuleInit();
const prestage = {
blockData: {
id: 'prestage-2',
height: 900002,
payoutMode: 'solo',
notificationEventId: 'prestage-event',
},
};
prestageJobs.next(prestage);
await Promise.resolve();
clients.forEach(client => {
expect(client.preStageMiningJob).toHaveBeenCalledWith(prestage);
expect(client.broadcastMiningJob).not.toHaveBeenCalled();
});
expect(consoleLogSpy).toHaveBeenCalledWith(expect.stringContaining('sv1_job_prestage'));
service.onModuleDestroy();
});
it('does not log routine non-new-block fanout unless explicitly enabled', () => {
(service as any).clients.add({
broadcastMiningJob: jest.fn().mockReturnValue({