Use app.locals to store contracts and jobq

“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 <jamest@uk.ibm.com>
This commit is contained in:
James Taylor 2021-12-13 17:06:31 +00:00
parent 66199000ca
commit 711f1f560b
8 changed files with 49 additions and 46 deletions

View file

@ -48,7 +48,7 @@ describe('Asset Transfer Besic REST API', () => {
mockJob.id = '1';
mockJobQueue = mock<Queue>();
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<Contract>();
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 () => {

View file

@ -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,

View file

@ -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),

View file

@ -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<string, Contract>();
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);
});

View file

@ -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);

View file

@ -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<Transaction>;
let mockContract: MockProxy<Contract>;
let mockApplication: MockProxy<Application>;
let mockJob: MockProxy<Job>;
beforeEach(() => {
@ -179,6 +181,9 @@ describe('getJobCounts', () => {
.mockReturnValue(mockTransaction);
mockContracts.set('mockMspid', mockContract);
mockApplication = mock<Application>();
mockApplication.locals.mockMspid = { assetContract: mockContract };
mockJob = mock<Job>();
});
@ -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');
});
});

View file

@ -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<string, Contract>
): Worker => {
export const initJobQueueWorker = (app: Application): Worker => {
const worker = new Worker<JobData, JobResult>(
config.JOB_QUEUE_NAME,
async (job): Promise<JobResult> => {
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<string, Contract>,
app: Application,
job: Job<JobData, JobResult>
): Promise<JobResult> => {
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 },

View file

@ -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,