From 711f1f560b28028a3e8f11a05d1c481691f559e4 Mon Sep 17 00:00:00 2001 From: James Taylor Date: Mon, 13 Dec 2021 17:06:31 +0000 Subject: [PATCH] Use app.locals to store contracts and jobq MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit “The app.locals object has properties that are local variables within the application.” …which looks like a better option than app.get and app.set for app settings. Also passes app to the initJobQueueWorker function for consistency. Signed-off-by: James Taylor --- .../src/__tests__/api.test.ts | 22 +++++++++--------- .../rest-api-typescript/src/assets.router.ts | 14 +++++------ .../rest-api-typescript/src/health.router.ts | 6 ++--- .../rest-api-typescript/src/index.ts | 23 +++++++++---------- .../rest-api-typescript/src/jobs.router.ts | 2 +- .../rest-api-typescript/src/jobs.spec.ts | 15 ++++++++---- .../rest-api-typescript/src/jobs.ts | 11 ++++----- .../src/transactions.router.ts | 2 +- 8 files changed, 49 insertions(+), 46 deletions(-) diff --git a/asset-transfer-basic/rest-api-typescript/src/__tests__/api.test.ts b/asset-transfer-basic/rest-api-typescript/src/__tests__/api.test.ts index 06d29dba..b1097bc0 100644 --- a/asset-transfer-basic/rest-api-typescript/src/__tests__/api.test.ts +++ b/asset-transfer-basic/rest-api-typescript/src/__tests__/api.test.ts @@ -48,7 +48,7 @@ describe('Asset Transfer Besic REST API', () => { mockJob.id = '1'; mockJobQueue = mock(); mockJobQueue.add.mockResolvedValue(mockJob); - app.set('jobq', mockJobQueue); + app.locals.jobq = mockJobQueue; }); describe('/ready', () => { @@ -81,17 +81,17 @@ describe('Asset Transfer Besic REST API', () => { mockOrg1QsccContract.evaluateTransaction .calledWith('GetChainInfo') .mockResolvedValue(mockBlockchainInfoBuffer); - app.set(config.mspIdOrg1, { + app.locals[config.mspIdOrg1] = { qsccContract: mockOrg1QsccContract, - }); + }; const mockOrg2QsccContract = mock(); mockOrg2QsccContract.evaluateTransaction .calledWith('GetChainInfo') .mockResolvedValue(mockBlockchainInfoBuffer); - app.set(config.mspIdOrg2, { + app.locals[config.mspIdOrg2] = { qsccContract: mockOrg2QsccContract, - }); + }; const response = await request(app).get('/live'); expect(response.statusCode).toEqual(200); @@ -115,9 +115,9 @@ describe('Asset Transfer Besic REST API', () => { mockBasicContract.createTransaction .calledWith('GetAllAssets') .mockReturnValue(mockGetAllAssetsTransaction); - app.set(config.mspIdOrg1, { + app.locals[config.mspIdOrg1] = { assetContract: mockBasicContract, - }); + }; }); it('GET should respond with 401 unauthorized json when an invalid API key is specified', async () => { @@ -276,9 +276,9 @@ describe('Asset Transfer Besic REST API', () => { .calledWith('ReadAsset') .mockReturnValue(mockReadAssetTransaction); - app.set(config.mspIdOrg1, { + app.locals[config.mspIdOrg1] = { assetContract: mockBasicContract, - }); + }; }); it('OPTIONS should respond with 401 unauthorized json when an invalid API key is specified', async () => { @@ -663,9 +663,9 @@ describe('Asset Transfer Besic REST API', () => { mockQsccContract.createTransaction .calledWith('GetTransactionByID') .mockReturnValue(mockGetTransactionByIDTransaction); - app.set(config.mspIdOrg1, { + app.locals[config.mspIdOrg1] = { qsccContract: mockQsccContract, - }); + }; }); it('GET should respond with 401 unauthorized json when an invalid API key is specified', async () => { diff --git a/asset-transfer-basic/rest-api-typescript/src/assets.router.ts b/asset-transfer-basic/rest-api-typescript/src/assets.router.ts index 5d6c96f5..0af215d1 100644 --- a/asset-transfer-basic/rest-api-typescript/src/assets.router.ts +++ b/asset-transfer-basic/rest-api-typescript/src/assets.router.ts @@ -38,7 +38,7 @@ assetsRouter.get('/', async (req: Request, res: Response) => { try { const mspId = req.user as string; - const contract = req.app.get(mspId).assetContract as Contract; + const contract = req.app.locals[mspId]?.assetContract as Contract; const data = await evatuateTransaction(contract, 'GetAllAssets'); let assets = []; @@ -82,7 +82,7 @@ assetsRouter.post( const assetId = req.body.id; try { - const submitQueue = req.app.get('jobq') as Queue; + const submitQueue = req.app.locals.jobq as Queue; const jobId = await addSubmitTransactionJob( submitQueue, mspId, @@ -120,7 +120,7 @@ assetsRouter.options('/:assetId', async (req: Request, res: Response) => { try { const mspId = req.user as string; - const contract = req.app.get(mspId).assetContract as Contract; + const contract = req.app.locals[mspId]?.assetContract as Contract; const data = await evatuateTransaction(contract, 'AssetExists', assetId); const exists = data.toString() === 'true'; @@ -160,7 +160,7 @@ assetsRouter.get('/:assetId', async (req: Request, res: Response) => { try { const mspId = req.user as string; - const contract = req.app.get(mspId).assetContract as Contract; + const contract = req.app.locals[mspId]?.assetContract as Contract; const data = await evatuateTransaction(contract, 'ReadAsset', assetId); const asset = JSON.parse(data.toString()); @@ -222,7 +222,7 @@ assetsRouter.put( const assetId = req.params.assetId; try { - const submitQueue = req.app.get('jobq') as Queue; + const submitQueue = req.app.locals.jobq as Queue; const jobId = await addSubmitTransactionJob( submitQueue, mspId, @@ -284,7 +284,7 @@ assetsRouter.patch( const newOwner = req.body[0].value; try { - const submitQueue = req.app.get('jobq') as Queue; + const submitQueue = req.app.locals.jobq as Queue; const jobId = await addSubmitTransactionJob( submitQueue, mspId, @@ -320,7 +320,7 @@ assetsRouter.delete('/:assetId', async (req: Request, res: Response) => { const assetId = req.params.assetId; try { - const submitQueue = req.app.get('jobq') as Queue; + const submitQueue = req.app.locals.jobq as Queue; const jobId = await addSubmitTransactionJob( submitQueue, mspId, diff --git a/asset-transfer-basic/rest-api-typescript/src/health.router.ts b/asset-transfer-basic/rest-api-typescript/src/health.router.ts index 463ee0e4..e0e32588 100644 --- a/asset-transfer-basic/rest-api-typescript/src/health.router.ts +++ b/asset-transfer-basic/rest-api-typescript/src/health.router.ts @@ -30,9 +30,9 @@ healthRouter.get('/live', async (req: Request, res: Response) => { logger.debug(req.body, 'Liveness request received'); try { - const submitQueue = req.app.get('jobq') as Queue; - const qsccOrg1 = req.app.get(config.mspIdOrg1).qsccContract as Contract; - const qsccOrg2 = req.app.get(config.mspIdOrg2).qsccContract as Contract; + const submitQueue = req.app.locals.jobq as Queue; + const qsccOrg1 = req.app.locals[config.mspIdOrg1]?.qsccContract as Contract; + const qsccOrg2 = req.app.locals[config.mspIdOrg2]?.qsccContract as Contract; await Promise.all([ getBlockHeight(qsccOrg1), diff --git a/asset-transfer-basic/rest-api-typescript/src/index.ts b/asset-transfer-basic/rest-api-typescript/src/index.ts index e033db4c..c9a08574 100644 --- a/asset-transfer-basic/rest-api-typescript/src/index.ts +++ b/asset-transfer-basic/rest-api-typescript/src/index.ts @@ -32,7 +32,6 @@ * express server implementation details */ -import { Contract } from 'fabric-network'; import * as config from './config'; import { createGateway, @@ -62,7 +61,10 @@ async function main() { ); } - logger.info('Connecting to Fabric network'); + logger.info('Creating REST server'); + const app = await createServer(); + + logger.info('Connecting to Fabric network with org1 mspid'); const wallet = await createWallet(); const gatewayOrg1 = await createGateway( @@ -73,6 +75,9 @@ async function main() { const networkOrg1 = await getNetwork(gatewayOrg1); const contractsOrg1 = await getContracts(networkOrg1); + app.locals[config.mspIdOrg1] = contractsOrg1; + + logger.info('Connecting to Fabric network with org2 mspid'); const gatewayOrg2 = await createGateway( config.connectionProfileOrg2, config.mspIdOrg2, @@ -81,24 +86,18 @@ async function main() { const networkOrg2 = await getNetwork(gatewayOrg2); const contractsOrg2 = await getContracts(networkOrg2); - const assetContracts = new Map(); - assetContracts.set(config.mspIdOrg1, contractsOrg1.assetContract); - assetContracts.set(config.mspIdOrg2, contractsOrg2.assetContract); + app.locals[config.mspIdOrg2] = contractsOrg2; logger.info('Initialising submit job queue'); jobQueue = initJobQueue(); - jobQueueWorker = initJobQueueWorker(assetContracts); + jobQueueWorker = initJobQueueWorker(app); if (config.submitJobQueueScheduler === true) { logger.info('Initialising submit job queue scheduler'); jobQueueScheduler = initJobQueueScheduler(); } + app.locals.jobq = jobQueue; - logger.info('Creating REST server'); - const app = await createServer(); - app.set(config.mspIdOrg1, contractsOrg1); - app.set(config.mspIdOrg2, contractsOrg2); - app.set('jobq', jobQueue); - + logger.info('Starting REST server'); app.listen(config.port, () => { logger.info('REST server started on port: %d', config.port); }); diff --git a/asset-transfer-basic/rest-api-typescript/src/jobs.router.ts b/asset-transfer-basic/rest-api-typescript/src/jobs.router.ts index 77dc5fe9..2c021a29 100644 --- a/asset-transfer-basic/rest-api-typescript/src/jobs.router.ts +++ b/asset-transfer-basic/rest-api-typescript/src/jobs.router.ts @@ -17,7 +17,7 @@ jobsRouter.get('/:jobId', async (req: Request, res: Response) => { logger.debug('Read request received for job ID %s', jobId); try { - const submitQueue = req.app.get('jobq') as Queue; + const submitQueue = req.app.locals.jobq as Queue; const jobSummary = await getJobSummary(submitQueue, jobId); diff --git a/asset-transfer-basic/rest-api-typescript/src/jobs.spec.ts b/asset-transfer-basic/rest-api-typescript/src/jobs.spec.ts index e0a60fa7..93e83f8b 100644 --- a/asset-transfer-basic/rest-api-typescript/src/jobs.spec.ts +++ b/asset-transfer-basic/rest-api-typescript/src/jobs.spec.ts @@ -11,6 +11,7 @@ import { } from './jobs'; import { Contract, Transaction } from 'fabric-network'; import { mock, MockProxy } from 'jest-mock-extended'; +import { Application } from 'express'; describe('initJobQueue', () => { it.todo('write tests'); @@ -164,6 +165,7 @@ describe('getJobCounts', () => { const mockSavedState = Buffer.from('MOCK SAVED STATE'); let mockTransaction: MockProxy; let mockContract: MockProxy; + let mockApplication: MockProxy; let mockJob: MockProxy; beforeEach(() => { @@ -179,6 +181,9 @@ describe('getJobCounts', () => { .mockReturnValue(mockTransaction); mockContracts.set('mockMspid', mockContract); + mockApplication = mock(); + mockApplication.locals.mockMspid = { assetContract: mockContract }; + mockJob = mock(); }); @@ -188,7 +193,7 @@ describe('getJobCounts', () => { }; const jobResult = await processSubmitTransactionJob( - mockContracts, + mockApplication, mockJob ); @@ -209,7 +214,7 @@ describe('getJobCounts', () => { .mockResolvedValue(mockPayload); const jobResult = await processSubmitTransactionJob( - mockContracts, + mockApplication, mockJob ); @@ -231,7 +236,7 @@ describe('getJobCounts', () => { .mockResolvedValue(mockPayload); const jobResult = await processSubmitTransactionJob( - mockContracts, + mockApplication, mockJob ); @@ -257,7 +262,7 @@ describe('getJobCounts', () => { ); const jobResult = await processSubmitTransactionJob( - mockContracts, + mockApplication, mockJob ); @@ -280,7 +285,7 @@ describe('getJobCounts', () => { .mockRejectedValue(new Error('MOCK ERROR')); await expect(async () => { - await processSubmitTransactionJob(mockContracts, mockJob); + await processSubmitTransactionJob(mockApplication, mockJob); }).rejects.toThrow('MOCK ERROR'); }); }); diff --git a/asset-transfer-basic/rest-api-typescript/src/jobs.ts b/asset-transfer-basic/rest-api-typescript/src/jobs.ts index 2b4f2399..de2ab458 100644 --- a/asset-transfer-basic/rest-api-typescript/src/jobs.ts +++ b/asset-transfer-basic/rest-api-typescript/src/jobs.ts @@ -6,6 +6,7 @@ */ import { ConnectionOptions, Job, Queue, QueueScheduler, Worker } from 'bullmq'; +import { Application } from 'express'; import { Contract, Transaction } from 'fabric-network'; import * as config from './config'; import { getRetryAction, RetryAction } from './errors'; @@ -69,13 +70,11 @@ export const initJobQueue = (): Queue => { return submitQueue; }; -export const initJobQueueWorker = ( - contracts: Map -): Worker => { +export const initJobQueueWorker = (app: Application): Worker => { const worker = new Worker( config.JOB_QUEUE_NAME, async (job): Promise => { - return await processSubmitTransactionJob(contracts, job); + return await processSubmitTransactionJob(app, job); }, { connection, concurrency: config.submitJobConcurrency } ); @@ -229,12 +228,12 @@ export const getJobCounts = async ( * The job will be retried if this function throws an error */ export const processSubmitTransactionJob = async ( - contracts: Map, + app: Application, job: Job ): Promise => { logger.debug({ jobId: job.id, jobName: job.name }, 'Processing job'); - const contract = contracts.get(job.data.mspid); + const contract = app.locals[job.data.mspid]?.assetContract as Contract; if (contract === undefined) { logger.error( { jobId: job.id, jobName: job.name }, diff --git a/asset-transfer-basic/rest-api-typescript/src/transactions.router.ts b/asset-transfer-basic/rest-api-typescript/src/transactions.router.ts index 4b729951..d092337d 100644 --- a/asset-transfer-basic/rest-api-typescript/src/transactions.router.ts +++ b/asset-transfer-basic/rest-api-typescript/src/transactions.router.ts @@ -21,7 +21,7 @@ transactionsRouter.get( logger.debug('Read request received for transaction ID %s', transactionId); try { - const qsccContract = req.app.get(mspId).qsccContract as Contract; + const qsccContract = req.app.locals[mspId]?.qsccContract as Contract; const validationCode = await getTransactionValidationCode( qsccContract,