Verified Commit 84f67585 authored by aguestuser's avatar aguestuser

[h] notify members of deleted channels in background

* BUG SYMPTOM: when deleting a very large channel, the call to
  `phoneNumberRegistrar.destroy` fails due to a mysterious `Operation
  timeout`
* LIKELY CAUSE: awaiting the resolution of the call to
  `notifyMembers` (which takes over an hour for a large channel)
  likely causes the transaction initiated at the top of `destroy` to
  timeout
* FIX: launch notifications as "fire and forget" process in the
  background and add some more verbose logging to help debug if error persists
parent 97dd8323
......@@ -27,18 +27,31 @@ const destroy = async ({ phoneNumber, sender }) => {
return { status: 'ERROR', message: `No records found for ${phoneNumber}` }
if (phoneNumberRecord) {
logger.log(`deleting phone number ${phoneNumber}...`)
await phoneNumberRepository.destroy(phoneNumber, tx)
await releasePhoneNumber(phoneNumberRecord)
logger.log(`...deleted phone number ${phoneNumber}.`)
}
if (channel) {
logger.log(`deleting channel ${phoneNumber}...`)
await channelRepository.destroy(channel.phoneNumber, tx)
await eventRepository.log(eventTypes.CHANNEL_DESTROYED, phoneNumber, tx)
await notifier.notifyMembersExcept(channel, sender, notificationKeys.CHANNEL_DESTROYED)
logger.log(`...deleted channel ${phoneNumber}`)
;(async () => {
logger.log(`sending deletion notice to members of: ${phoneNumber}...`)
await notifier
.notifyMembersExcept(channel, sender, notificationKeys.CHANNEL_DESTROYED)
.catch(logger.error)
logger.log(`...sent deltion notice to members of: ${phoneNumber}`)
})()
}
logger.log(`destroying signald data for ${phoneNumber}...`)
await signal.unsubscribe(phoneNumber)
await deleteSignalKeystore(phoneNumber)
logger.log(`destroyed signald data for ${phoneNumber}...`)
await tx.commit()
return { status: 'SUCCESS', msg: 'All records of phone number have been destroyed.' }
......
......@@ -52,7 +52,7 @@ describe('phone number registrar -- destroy module', () => {
destroyChannelStub = sinon.stub(channelRepository, 'destroy')
destroyPhoneNumberStub = sinon.stub(phoneNumberRepository, 'destroy')
notifyMaintainersStub = sinon.stub(notifier, 'notifyMaintainers')
notifyMembersExceptStub = sinon.stub(notifier, 'notifyMembersExcept')
notifyMembersExceptStub = sinon.stub(notifier, 'notifyMembersExcept').returns(Promise.resolve())
twilioRemoveStub = sinon.stub()
sinon.stub(commonService, 'getTwilioClient').callsFake(() => ({
incomingPhoneNumbers: () => ({ remove: twilioRemoveStub }),
......@@ -225,19 +225,18 @@ describe('phone number registrar -- destroy module', () => {
notifyMaintainersStub.returns(Promise.resolve())
})
it('returns an error status', async () => {
it('commits the db transaction', async () => {
await destroy({ phoneNumber })
expect(commitStub.callCount).to.eql(1)
})
it('returns a success status', async () => {
const response = await destroy({ phoneNumber })
expect(response).to.eql({
message: `Failed to destroy channel for ${phoneNumber}. Error: Failed to broadcast message`,
status: 'ERROR',
status: 'SUCCESS',
msg: 'All records of phone number have been destroyed.',
})
})
it('rolls back the db transaction', async () => {
await destroy({ phoneNumber })
expect(rollbackStub.callCount).to.eql(1)
expect(commitStub.callCount).to.eql(0)
})
})
describe('when deleting the phone number from the db fails', () => {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment