From 2a86ec994acbdb1710b0f48e7e0ed6f3bc67fe36 Mon Sep 17 00:00:00 2001 From: Simeon Nakov Date: Tue, 4 Nov 2025 16:29:30 +0200 Subject: [PATCH] feat: adds factory for PendingTransactionStorage creation Signed-off-by: Simeon Nakov --- packages/relay/src/lib/relay.ts | 7 +-- .../PendingTransactionStorageFactory.ts | 26 +++++++++++ .../PendingTransactionStorageFactory.spec.ts | 44 +++++++++++++++++++ 3 files changed, 72 insertions(+), 5 deletions(-) create mode 100644 packages/relay/src/lib/services/transactionPoolService/PendingTransactionStorageFactory.ts create mode 100644 packages/relay/tests/lib/services/transactionPoolService/PendingTransactionStorageFactory.spec.ts diff --git a/packages/relay/src/lib/relay.ts b/packages/relay/src/lib/relay.ts index e0ab8797ac..06fd1d2ec4 100644 --- a/packages/relay/src/lib/relay.ts +++ b/packages/relay/src/lib/relay.ts @@ -25,8 +25,7 @@ import HAPIService from './services/hapiService/hapiService'; import { HbarLimitService } from './services/hbarLimitService'; import MetricService from './services/metricService/metricService'; import { registerRpcMethods } from './services/registryService/rpcMethodRegistryService'; -import { LocalPendingTransactionStorage } from './services/transactionPoolService/LocalPendingTransactionStorage'; -import { RedisPendingTransactionStorage } from './services/transactionPoolService/RedisPendingTransactionStorage'; +import { PendingTransactionStorageFactory } from './services/transactionPoolService/PendingTransactionStorageFactory'; import { IEthExecutionEventPayload, IExecuteQueryEventPayload, @@ -327,9 +326,7 @@ export class Relay { : this.mirrorNodeClient; this.metricService = new MetricService(this.logger, metricsCollector, this.register, hbarLimitService); - const storage = this.redisClient - ? new RedisPendingTransactionStorage(this.redisClient) - : new LocalPendingTransactionStorage(); + const storage = PendingTransactionStorageFactory.create(this.redisClient); // Create Eth implementation with connected Redis client this.ethImpl = new EthImpl( diff --git a/packages/relay/src/lib/services/transactionPoolService/PendingTransactionStorageFactory.ts b/packages/relay/src/lib/services/transactionPoolService/PendingTransactionStorageFactory.ts new file mode 100644 index 0000000000..f670ef582b --- /dev/null +++ b/packages/relay/src/lib/services/transactionPoolService/PendingTransactionStorageFactory.ts @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: Apache-2.0 + +import { RedisClientType } from 'redis'; + +import { PendingTransactionStorage } from '../../types/transactionPool'; +import { LocalPendingTransactionStorage } from './LocalPendingTransactionStorage'; +import { RedisPendingTransactionStorage } from './RedisPendingTransactionStorage'; + +/** + * Factory for creating PendingTransactionStorage instances. + * + * Encapsulates the logic for selecting the appropriate storage implementation + * based on available infrastructure (Redis vs in-memory). + */ +export class PendingTransactionStorageFactory { + /** + * Creates a PendingTransactionStorage instance. + * + * @param redisClient - Optional Redis client. If provided, creates Redis-backed storage; + * otherwise creates local in-memory storage. + * @returns A PendingTransactionStorage implementation. + */ + static create(redisClient?: RedisClientType): PendingTransactionStorage { + return redisClient ? new RedisPendingTransactionStorage(redisClient) : new LocalPendingTransactionStorage(); + } +} diff --git a/packages/relay/tests/lib/services/transactionPoolService/PendingTransactionStorageFactory.spec.ts b/packages/relay/tests/lib/services/transactionPoolService/PendingTransactionStorageFactory.spec.ts new file mode 100644 index 0000000000..f68297aff7 --- /dev/null +++ b/packages/relay/tests/lib/services/transactionPoolService/PendingTransactionStorageFactory.spec.ts @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: Apache-2.0 + +import chai, { expect } from 'chai'; +import chaiAsPromised from 'chai-as-promised'; + +import { LocalPendingTransactionStorage } from '../../../../src/lib/services/transactionPoolService/LocalPendingTransactionStorage'; +import { PendingTransactionStorageFactory } from '../../../../src/lib/services/transactionPoolService/PendingTransactionStorageFactory'; +import { RedisPendingTransactionStorage } from '../../../../src/lib/services/transactionPoolService/RedisPendingTransactionStorage'; + +chai.use(chaiAsPromised); + +describe('PendingTransactionStorageFactory', () => { + describe('create', () => { + it('should return LocalPendingTransactionStorage when redisClient is not provided', () => { + const storage = PendingTransactionStorageFactory.create(); + + expect(storage).to.be.instanceOf(LocalPendingTransactionStorage); + }); + + it('should return LocalPendingTransactionStorage when redisClient is undefined', () => { + const storage = PendingTransactionStorageFactory.create(undefined); + + expect(storage).to.be.instanceOf(LocalPendingTransactionStorage); + }); + + it('should return RedisPendingTransactionStorage when redisClient is provided', () => { + // Mock Redis client - just needs to be a truthy object for the factory logic + const mockRedisClient = {} as any; + + const storage = PendingTransactionStorageFactory.create(mockRedisClient); + + expect(storage).to.be.instanceOf(RedisPendingTransactionStorage); + }); + + it('should create different storage instances on multiple calls', () => { + const storage1 = PendingTransactionStorageFactory.create(); + const storage2 = PendingTransactionStorageFactory.create(); + + expect(storage1).to.not.equal(storage2); + expect(storage1).to.be.instanceOf(LocalPendingTransactionStorage); + expect(storage2).to.be.instanceOf(LocalPendingTransactionStorage); + }); + }); +});