chore: Improve Transcript service call chain (#34920)
parent
f323946ec0
commit
1fb9f86a92
@ -0,0 +1,40 @@ |
||||
import { OmnichannelTranscript, QueueWorker } from '@rocket.chat/core-services'; |
||||
import type { AtLeast, IOmnichannelRoom } from '@rocket.chat/core-typings'; |
||||
import { LivechatRooms } from '@rocket.chat/models'; |
||||
|
||||
import { logger } from './logger'; |
||||
|
||||
const serviceName = 'omnichannel-transcript' as const; |
||||
export const requestPdfTranscript = async ( |
||||
room: AtLeast<IOmnichannelRoom, '_id' | 'open' | 'v' | 'pdfTranscriptRequested'>, |
||||
requestedBy: string, |
||||
): Promise<void> => { |
||||
if (room.open) { |
||||
throw new Error('room-still-open'); |
||||
} |
||||
|
||||
if (!room.v) { |
||||
throw new Error('improper-room-state'); |
||||
} |
||||
|
||||
// Don't request a transcript if there's already one requested :)
|
||||
if (room.pdfTranscriptRequested) { |
||||
// TODO: use logger
|
||||
logger.info(`Transcript already requested for room ${room._id}`); |
||||
return; |
||||
} |
||||
|
||||
// TODO: change this with a timestamp, allowing users to request a transcript again after a while if the first one fails
|
||||
await LivechatRooms.setTranscriptRequestedPdfById(room._id); |
||||
|
||||
const details = { details: { rid: room._id, userId: requestedBy, from: serviceName } }; |
||||
// Make the whole process sync when running on test mode
|
||||
// This will prevent the usage of timeouts on the tests of this functionality :)
|
||||
if (process.env.TEST_MODE) { |
||||
await OmnichannelTranscript.workOnPdf(details); |
||||
return; |
||||
} |
||||
|
||||
logger.info(`Queuing work for room ${room._id}`); |
||||
await QueueWorker.queueWork('work', `${serviceName}.workOnPdf`, details); |
||||
}; |
||||
@ -0,0 +1,74 @@ |
||||
import { expect } from 'chai'; |
||||
import { describe, it, beforeEach, after } from 'mocha'; |
||||
import proxyquire from 'proxyquire'; |
||||
import sinon from 'sinon'; |
||||
|
||||
const setStub = sinon.stub(); |
||||
const workOnPdfStub = sinon.stub(); |
||||
const queueWorkStub = sinon.stub(); |
||||
|
||||
const { requestPdfTranscript } = proxyquire |
||||
.noCallThru() |
||||
.load('../../../../../ee/app/livechat-enterprise/server/lib/requestPdfTranscript.ts', { |
||||
'@rocket.chat/models': { |
||||
LivechatRooms: { |
||||
setTranscriptRequestedPdfById: setStub, |
||||
}, |
||||
}, |
||||
'@rocket.chat/core-services': { |
||||
OmnichannelTranscript: { |
||||
workOnPdf: workOnPdfStub, |
||||
}, |
||||
QueueWorker: { |
||||
queueWork: queueWorkStub, |
||||
}, |
||||
}, |
||||
}); |
||||
|
||||
describe('requestPdfTranscript', () => { |
||||
const currentTestModeValue = process.env.TEST_MODE; |
||||
|
||||
beforeEach(() => { |
||||
setStub.reset(); |
||||
workOnPdfStub.reset(); |
||||
queueWorkStub.reset(); |
||||
}); |
||||
|
||||
after(() => { |
||||
process.env.TEST_MODE = currentTestModeValue; |
||||
}); |
||||
|
||||
it('should throw an error if room is still open', async () => { |
||||
await expect(requestPdfTranscript({ open: true }, 'userId')).to.be.rejectedWith('room-still-open'); |
||||
}); |
||||
it('should throw an error if room doesnt have a v property', async () => { |
||||
await expect(requestPdfTranscript({}, 'userId')).to.be.rejectedWith('improper-room-state'); |
||||
}); |
||||
it('should not request a transcript if it was already requested', async () => { |
||||
await requestPdfTranscript({ v: 1, pdfTranscriptRequested: true }, 'userId'); |
||||
expect(setStub.callCount).to.equal(0); |
||||
expect(workOnPdfStub.callCount).to.equal(0); |
||||
expect(queueWorkStub.callCount).to.equal(0); |
||||
}); |
||||
it('should set pdfTranscriptRequested to true on room', async () => { |
||||
await requestPdfTranscript({ _id: 'roomId', v: {}, pdfTranscriptRequested: false }, 'userId'); |
||||
expect(setStub.calledWith('roomId')).to.be.true; |
||||
}); |
||||
it('should call workOnPdf if TEST_MODE is true', async () => { |
||||
process.env.TEST_MODE = 'true'; |
||||
await requestPdfTranscript({ _id: 'roomId', v: {} }, 'userId'); |
||||
expect(workOnPdfStub.getCall(0).calledWithExactly({ details: { rid: 'roomId', userId: 'userId', from: 'omnichannel-transcript' } })).to |
||||
.be.true; |
||||
expect(queueWorkStub.calledOnce).to.be.false; |
||||
}); |
||||
it('should queue work if TEST_MODE is not set', async () => { |
||||
delete process.env.TEST_MODE; |
||||
await requestPdfTranscript({ _id: 'roomId', v: {} }, 'userId'); |
||||
expect(workOnPdfStub.calledOnce).to.be.false; |
||||
expect( |
||||
queueWorkStub.getCall(0).calledWithExactly('work', 'omnichannel-transcript.workOnPdf', { |
||||
details: { rid: 'roomId', userId: 'userId', from: 'omnichannel-transcript' }, |
||||
}), |
||||
).to.be.true; |
||||
}); |
||||
}); |
||||
@ -1,6 +1,14 @@ |
||||
import type { IUser, IRoom } from '@rocket.chat/core-typings'; |
||||
|
||||
type WorkDetails = { |
||||
rid: IRoom['_id']; |
||||
userId: IUser['_id']; |
||||
}; |
||||
|
||||
type WorkDetailsWithSource = WorkDetails & { |
||||
from: string; |
||||
}; |
||||
|
||||
export interface IOmnichannelTranscriptService { |
||||
requestTranscript({ details }: { details: { userId: IUser['_id']; rid: IRoom['_id'] } }): Promise<void>; |
||||
workOnPdf({ template, details }: { template: string; details: any }): Promise<void>; |
||||
workOnPdf({ details }: { details: WorkDetailsWithSource }): Promise<void>; |
||||
} |
||||
|
||||
Loading…
Reference in new issue