mirror of
https://github.com/hyperledger/fabric-samples.git
synced 2026-06-22 17:45:10 +00:00
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:
parent
66199000ca
commit
711f1f560b
8 changed files with 49 additions and 46 deletions
|
|
@ -48,7 +48,7 @@ describe('Asset Transfer Besic REST API', () => {
|
||||||
mockJob.id = '1';
|
mockJob.id = '1';
|
||||||
mockJobQueue = mock<Queue>();
|
mockJobQueue = mock<Queue>();
|
||||||
mockJobQueue.add.mockResolvedValue(mockJob);
|
mockJobQueue.add.mockResolvedValue(mockJob);
|
||||||
app.set('jobq', mockJobQueue);
|
app.locals.jobq = mockJobQueue;
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('/ready', () => {
|
describe('/ready', () => {
|
||||||
|
|
@ -81,17 +81,17 @@ describe('Asset Transfer Besic REST API', () => {
|
||||||
mockOrg1QsccContract.evaluateTransaction
|
mockOrg1QsccContract.evaluateTransaction
|
||||||
.calledWith('GetChainInfo')
|
.calledWith('GetChainInfo')
|
||||||
.mockResolvedValue(mockBlockchainInfoBuffer);
|
.mockResolvedValue(mockBlockchainInfoBuffer);
|
||||||
app.set(config.mspIdOrg1, {
|
app.locals[config.mspIdOrg1] = {
|
||||||
qsccContract: mockOrg1QsccContract,
|
qsccContract: mockOrg1QsccContract,
|
||||||
});
|
};
|
||||||
|
|
||||||
const mockOrg2QsccContract = mock<Contract>();
|
const mockOrg2QsccContract = mock<Contract>();
|
||||||
mockOrg2QsccContract.evaluateTransaction
|
mockOrg2QsccContract.evaluateTransaction
|
||||||
.calledWith('GetChainInfo')
|
.calledWith('GetChainInfo')
|
||||||
.mockResolvedValue(mockBlockchainInfoBuffer);
|
.mockResolvedValue(mockBlockchainInfoBuffer);
|
||||||
app.set(config.mspIdOrg2, {
|
app.locals[config.mspIdOrg2] = {
|
||||||
qsccContract: mockOrg2QsccContract,
|
qsccContract: mockOrg2QsccContract,
|
||||||
});
|
};
|
||||||
|
|
||||||
const response = await request(app).get('/live');
|
const response = await request(app).get('/live');
|
||||||
expect(response.statusCode).toEqual(200);
|
expect(response.statusCode).toEqual(200);
|
||||||
|
|
@ -115,9 +115,9 @@ describe('Asset Transfer Besic REST API', () => {
|
||||||
mockBasicContract.createTransaction
|
mockBasicContract.createTransaction
|
||||||
.calledWith('GetAllAssets')
|
.calledWith('GetAllAssets')
|
||||||
.mockReturnValue(mockGetAllAssetsTransaction);
|
.mockReturnValue(mockGetAllAssetsTransaction);
|
||||||
app.set(config.mspIdOrg1, {
|
app.locals[config.mspIdOrg1] = {
|
||||||
assetContract: mockBasicContract,
|
assetContract: mockBasicContract,
|
||||||
});
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
it('GET should respond with 401 unauthorized json when an invalid API key is specified', async () => {
|
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')
|
.calledWith('ReadAsset')
|
||||||
.mockReturnValue(mockReadAssetTransaction);
|
.mockReturnValue(mockReadAssetTransaction);
|
||||||
|
|
||||||
app.set(config.mspIdOrg1, {
|
app.locals[config.mspIdOrg1] = {
|
||||||
assetContract: mockBasicContract,
|
assetContract: mockBasicContract,
|
||||||
});
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
it('OPTIONS should respond with 401 unauthorized json when an invalid API key is specified', async () => {
|
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
|
mockQsccContract.createTransaction
|
||||||
.calledWith('GetTransactionByID')
|
.calledWith('GetTransactionByID')
|
||||||
.mockReturnValue(mockGetTransactionByIDTransaction);
|
.mockReturnValue(mockGetTransactionByIDTransaction);
|
||||||
app.set(config.mspIdOrg1, {
|
app.locals[config.mspIdOrg1] = {
|
||||||
qsccContract: mockQsccContract,
|
qsccContract: mockQsccContract,
|
||||||
});
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
it('GET should respond with 401 unauthorized json when an invalid API key is specified', async () => {
|
it('GET should respond with 401 unauthorized json when an invalid API key is specified', async () => {
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ assetsRouter.get('/', async (req: Request, res: Response) => {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const mspId = req.user as string;
|
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');
|
const data = await evatuateTransaction(contract, 'GetAllAssets');
|
||||||
let assets = [];
|
let assets = [];
|
||||||
|
|
@ -82,7 +82,7 @@ assetsRouter.post(
|
||||||
const assetId = req.body.id;
|
const assetId = req.body.id;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const submitQueue = req.app.get('jobq') as Queue;
|
const submitQueue = req.app.locals.jobq as Queue;
|
||||||
const jobId = await addSubmitTransactionJob(
|
const jobId = await addSubmitTransactionJob(
|
||||||
submitQueue,
|
submitQueue,
|
||||||
mspId,
|
mspId,
|
||||||
|
|
@ -120,7 +120,7 @@ assetsRouter.options('/:assetId', async (req: Request, res: Response) => {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const mspId = req.user as string;
|
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 data = await evatuateTransaction(contract, 'AssetExists', assetId);
|
||||||
const exists = data.toString() === 'true';
|
const exists = data.toString() === 'true';
|
||||||
|
|
@ -160,7 +160,7 @@ assetsRouter.get('/:assetId', async (req: Request, res: Response) => {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const mspId = req.user as string;
|
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 data = await evatuateTransaction(contract, 'ReadAsset', assetId);
|
||||||
const asset = JSON.parse(data.toString());
|
const asset = JSON.parse(data.toString());
|
||||||
|
|
@ -222,7 +222,7 @@ assetsRouter.put(
|
||||||
const assetId = req.params.assetId;
|
const assetId = req.params.assetId;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const submitQueue = req.app.get('jobq') as Queue;
|
const submitQueue = req.app.locals.jobq as Queue;
|
||||||
const jobId = await addSubmitTransactionJob(
|
const jobId = await addSubmitTransactionJob(
|
||||||
submitQueue,
|
submitQueue,
|
||||||
mspId,
|
mspId,
|
||||||
|
|
@ -284,7 +284,7 @@ assetsRouter.patch(
|
||||||
const newOwner = req.body[0].value;
|
const newOwner = req.body[0].value;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const submitQueue = req.app.get('jobq') as Queue;
|
const submitQueue = req.app.locals.jobq as Queue;
|
||||||
const jobId = await addSubmitTransactionJob(
|
const jobId = await addSubmitTransactionJob(
|
||||||
submitQueue,
|
submitQueue,
|
||||||
mspId,
|
mspId,
|
||||||
|
|
@ -320,7 +320,7 @@ assetsRouter.delete('/:assetId', async (req: Request, res: Response) => {
|
||||||
const assetId = req.params.assetId;
|
const assetId = req.params.assetId;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const submitQueue = req.app.get('jobq') as Queue;
|
const submitQueue = req.app.locals.jobq as Queue;
|
||||||
const jobId = await addSubmitTransactionJob(
|
const jobId = await addSubmitTransactionJob(
|
||||||
submitQueue,
|
submitQueue,
|
||||||
mspId,
|
mspId,
|
||||||
|
|
|
||||||
|
|
@ -30,9 +30,9 @@ healthRouter.get('/live', async (req: Request, res: Response) => {
|
||||||
logger.debug(req.body, 'Liveness request received');
|
logger.debug(req.body, 'Liveness request received');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const submitQueue = req.app.get('jobq') as Queue;
|
const submitQueue = req.app.locals.jobq as Queue;
|
||||||
const qsccOrg1 = req.app.get(config.mspIdOrg1).qsccContract as Contract;
|
const qsccOrg1 = req.app.locals[config.mspIdOrg1]?.qsccContract as Contract;
|
||||||
const qsccOrg2 = req.app.get(config.mspIdOrg2).qsccContract as Contract;
|
const qsccOrg2 = req.app.locals[config.mspIdOrg2]?.qsccContract as Contract;
|
||||||
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
getBlockHeight(qsccOrg1),
|
getBlockHeight(qsccOrg1),
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,6 @@
|
||||||
* express server implementation details
|
* express server implementation details
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Contract } from 'fabric-network';
|
|
||||||
import * as config from './config';
|
import * as config from './config';
|
||||||
import {
|
import {
|
||||||
createGateway,
|
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 wallet = await createWallet();
|
||||||
|
|
||||||
const gatewayOrg1 = await createGateway(
|
const gatewayOrg1 = await createGateway(
|
||||||
|
|
@ -73,6 +75,9 @@ async function main() {
|
||||||
const networkOrg1 = await getNetwork(gatewayOrg1);
|
const networkOrg1 = await getNetwork(gatewayOrg1);
|
||||||
const contractsOrg1 = await getContracts(networkOrg1);
|
const contractsOrg1 = await getContracts(networkOrg1);
|
||||||
|
|
||||||
|
app.locals[config.mspIdOrg1] = contractsOrg1;
|
||||||
|
|
||||||
|
logger.info('Connecting to Fabric network with org2 mspid');
|
||||||
const gatewayOrg2 = await createGateway(
|
const gatewayOrg2 = await createGateway(
|
||||||
config.connectionProfileOrg2,
|
config.connectionProfileOrg2,
|
||||||
config.mspIdOrg2,
|
config.mspIdOrg2,
|
||||||
|
|
@ -81,24 +86,18 @@ async function main() {
|
||||||
const networkOrg2 = await getNetwork(gatewayOrg2);
|
const networkOrg2 = await getNetwork(gatewayOrg2);
|
||||||
const contractsOrg2 = await getContracts(networkOrg2);
|
const contractsOrg2 = await getContracts(networkOrg2);
|
||||||
|
|
||||||
const assetContracts = new Map<string, Contract>();
|
app.locals[config.mspIdOrg2] = contractsOrg2;
|
||||||
assetContracts.set(config.mspIdOrg1, contractsOrg1.assetContract);
|
|
||||||
assetContracts.set(config.mspIdOrg2, contractsOrg2.assetContract);
|
|
||||||
|
|
||||||
logger.info('Initialising submit job queue');
|
logger.info('Initialising submit job queue');
|
||||||
jobQueue = initJobQueue();
|
jobQueue = initJobQueue();
|
||||||
jobQueueWorker = initJobQueueWorker(assetContracts);
|
jobQueueWorker = initJobQueueWorker(app);
|
||||||
if (config.submitJobQueueScheduler === true) {
|
if (config.submitJobQueueScheduler === true) {
|
||||||
logger.info('Initialising submit job queue scheduler');
|
logger.info('Initialising submit job queue scheduler');
|
||||||
jobQueueScheduler = initJobQueueScheduler();
|
jobQueueScheduler = initJobQueueScheduler();
|
||||||
}
|
}
|
||||||
|
app.locals.jobq = jobQueue;
|
||||||
|
|
||||||
logger.info('Creating REST server');
|
logger.info('Starting REST server');
|
||||||
const app = await createServer();
|
|
||||||
app.set(config.mspIdOrg1, contractsOrg1);
|
|
||||||
app.set(config.mspIdOrg2, contractsOrg2);
|
|
||||||
app.set('jobq', jobQueue);
|
|
||||||
|
|
||||||
app.listen(config.port, () => {
|
app.listen(config.port, () => {
|
||||||
logger.info('REST server started on port: %d', config.port);
|
logger.info('REST server started on port: %d', config.port);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ jobsRouter.get('/:jobId', async (req: Request, res: Response) => {
|
||||||
logger.debug('Read request received for job ID %s', jobId);
|
logger.debug('Read request received for job ID %s', jobId);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const submitQueue = req.app.get('jobq') as Queue;
|
const submitQueue = req.app.locals.jobq as Queue;
|
||||||
|
|
||||||
const jobSummary = await getJobSummary(submitQueue, jobId);
|
const jobSummary = await getJobSummary(submitQueue, jobId);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ import {
|
||||||
} from './jobs';
|
} from './jobs';
|
||||||
import { Contract, Transaction } from 'fabric-network';
|
import { Contract, Transaction } from 'fabric-network';
|
||||||
import { mock, MockProxy } from 'jest-mock-extended';
|
import { mock, MockProxy } from 'jest-mock-extended';
|
||||||
|
import { Application } from 'express';
|
||||||
|
|
||||||
describe('initJobQueue', () => {
|
describe('initJobQueue', () => {
|
||||||
it.todo('write tests');
|
it.todo('write tests');
|
||||||
|
|
@ -164,6 +165,7 @@ describe('getJobCounts', () => {
|
||||||
const mockSavedState = Buffer.from('MOCK SAVED STATE');
|
const mockSavedState = Buffer.from('MOCK SAVED STATE');
|
||||||
let mockTransaction: MockProxy<Transaction>;
|
let mockTransaction: MockProxy<Transaction>;
|
||||||
let mockContract: MockProxy<Contract>;
|
let mockContract: MockProxy<Contract>;
|
||||||
|
let mockApplication: MockProxy<Application>;
|
||||||
let mockJob: MockProxy<Job>;
|
let mockJob: MockProxy<Job>;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
|
@ -179,6 +181,9 @@ describe('getJobCounts', () => {
|
||||||
.mockReturnValue(mockTransaction);
|
.mockReturnValue(mockTransaction);
|
||||||
mockContracts.set('mockMspid', mockContract);
|
mockContracts.set('mockMspid', mockContract);
|
||||||
|
|
||||||
|
mockApplication = mock<Application>();
|
||||||
|
mockApplication.locals.mockMspid = { assetContract: mockContract };
|
||||||
|
|
||||||
mockJob = mock<Job>();
|
mockJob = mock<Job>();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -188,7 +193,7 @@ describe('getJobCounts', () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const jobResult = await processSubmitTransactionJob(
|
const jobResult = await processSubmitTransactionJob(
|
||||||
mockContracts,
|
mockApplication,
|
||||||
mockJob
|
mockJob
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -209,7 +214,7 @@ describe('getJobCounts', () => {
|
||||||
.mockResolvedValue(mockPayload);
|
.mockResolvedValue(mockPayload);
|
||||||
|
|
||||||
const jobResult = await processSubmitTransactionJob(
|
const jobResult = await processSubmitTransactionJob(
|
||||||
mockContracts,
|
mockApplication,
|
||||||
mockJob
|
mockJob
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -231,7 +236,7 @@ describe('getJobCounts', () => {
|
||||||
.mockResolvedValue(mockPayload);
|
.mockResolvedValue(mockPayload);
|
||||||
|
|
||||||
const jobResult = await processSubmitTransactionJob(
|
const jobResult = await processSubmitTransactionJob(
|
||||||
mockContracts,
|
mockApplication,
|
||||||
mockJob
|
mockJob
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -257,7 +262,7 @@ describe('getJobCounts', () => {
|
||||||
);
|
);
|
||||||
|
|
||||||
const jobResult = await processSubmitTransactionJob(
|
const jobResult = await processSubmitTransactionJob(
|
||||||
mockContracts,
|
mockApplication,
|
||||||
mockJob
|
mockJob
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -280,7 +285,7 @@ describe('getJobCounts', () => {
|
||||||
.mockRejectedValue(new Error('MOCK ERROR'));
|
.mockRejectedValue(new Error('MOCK ERROR'));
|
||||||
|
|
||||||
await expect(async () => {
|
await expect(async () => {
|
||||||
await processSubmitTransactionJob(mockContracts, mockJob);
|
await processSubmitTransactionJob(mockApplication, mockJob);
|
||||||
}).rejects.toThrow('MOCK ERROR');
|
}).rejects.toThrow('MOCK ERROR');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { ConnectionOptions, Job, Queue, QueueScheduler, Worker } from 'bullmq';
|
import { ConnectionOptions, Job, Queue, QueueScheduler, Worker } from 'bullmq';
|
||||||
|
import { Application } from 'express';
|
||||||
import { Contract, Transaction } from 'fabric-network';
|
import { Contract, Transaction } from 'fabric-network';
|
||||||
import * as config from './config';
|
import * as config from './config';
|
||||||
import { getRetryAction, RetryAction } from './errors';
|
import { getRetryAction, RetryAction } from './errors';
|
||||||
|
|
@ -69,13 +70,11 @@ export const initJobQueue = (): Queue => {
|
||||||
return submitQueue;
|
return submitQueue;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const initJobQueueWorker = (
|
export const initJobQueueWorker = (app: Application): Worker => {
|
||||||
contracts: Map<string, Contract>
|
|
||||||
): Worker => {
|
|
||||||
const worker = new Worker<JobData, JobResult>(
|
const worker = new Worker<JobData, JobResult>(
|
||||||
config.JOB_QUEUE_NAME,
|
config.JOB_QUEUE_NAME,
|
||||||
async (job): Promise<JobResult> => {
|
async (job): Promise<JobResult> => {
|
||||||
return await processSubmitTransactionJob(contracts, job);
|
return await processSubmitTransactionJob(app, job);
|
||||||
},
|
},
|
||||||
{ connection, concurrency: config.submitJobConcurrency }
|
{ connection, concurrency: config.submitJobConcurrency }
|
||||||
);
|
);
|
||||||
|
|
@ -229,12 +228,12 @@ export const getJobCounts = async (
|
||||||
* The job will be retried if this function throws an error
|
* The job will be retried if this function throws an error
|
||||||
*/
|
*/
|
||||||
export const processSubmitTransactionJob = async (
|
export const processSubmitTransactionJob = async (
|
||||||
contracts: Map<string, Contract>,
|
app: Application,
|
||||||
job: Job<JobData, JobResult>
|
job: Job<JobData, JobResult>
|
||||||
): Promise<JobResult> => {
|
): Promise<JobResult> => {
|
||||||
logger.debug({ jobId: job.id, jobName: job.name }, 'Processing job');
|
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) {
|
if (contract === undefined) {
|
||||||
logger.error(
|
logger.error(
|
||||||
{ jobId: job.id, jobName: job.name },
|
{ jobId: job.id, jobName: job.name },
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ transactionsRouter.get(
|
||||||
logger.debug('Read request received for transaction ID %s', transactionId);
|
logger.debug('Read request received for transaction ID %s', transactionId);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const qsccContract = req.app.get(mspId).qsccContract as Contract;
|
const qsccContract = req.app.locals[mspId]?.qsccContract as Contract;
|
||||||
|
|
||||||
const validationCode = await getTransactionValidationCode(
|
const validationCode = await getTransactionValidationCode(
|
||||||
qsccContract,
|
qsccContract,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue