Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature]Be notified when the UNBONDING > UNBONDED period has ended #116

Merged
merged 4 commits into from
Jul 30, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions server/helpers/notification/notificateDelegatorUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,20 @@ const sendEmailRewardCallNotificationToDelegators = async currentRoundInfo => {
currentRoundId
)

if (
delegator.status === constants.DELEGATOR_STATUS.Unbonded &&
subscriber.lastEmailSentForUnbondedStatus
) {
console.log(
`[Notificate-Delegators] - Not sending email to ${subscriber.email} because is in Unbonded state and already sent an email in the last ${subscriber.lastEmailSentForUnbondedStatus} round`
)
continue
} else if (subscriber.lastEmailSentForUnbondedStatus) {
// Unset lastEmailSentForUnbondedStatus for any other status than Unbonded and property lastEmailSentForUnbondedStatus not null
subscriber.lastEmailSentForUnbondedStatus = null
await subscriber.save()
}

if (!shouldSubscriberReceiveNotifications) {
console.log(
`[Notificate-Delegators] - Not sending email to ${subscriber.email} because already sent an email in the last ${subscriber.lastEmailSent} round and the frequency is ${subscriber.emailFrequency}`
Expand Down
3 changes: 3 additions & 0 deletions server/helpers/sendDelegatorEmail.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,9 @@ const getBodyAndTemplateIdBasedOnDelegatorStatus = (
let body = {}
switch (delegator.status) {
case constants.DELEGATOR_STATUS.Unbonded:
subscriber.lastEmailSentForUnbondedStatus = currentRoundInfo.id
subscriber.save().then(doc => {})

templateId = sendgridTemplateIdClaimRewardUnbondedState
break
case constants.DELEGATOR_STATUS.Unbonding:
Expand Down
5 changes: 5 additions & 0 deletions server/subscriber/subscriber.model.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@ let SubscriberSchema = new mongoose.Schema({
return Math.floor(Math.random() * 900000000300000000000) + 1000000000000000
}
},
// References the roundID in which the last email was sent for the unbonded status
lastEmailSentForUnbondedStatus: {
type: String,
default: null
},
// References the roundID in which the last email was sent
lastEmailSent: {
type: String,
Expand Down
190 changes: 190 additions & 0 deletions test/notificate-delegators-utils.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -612,6 +612,196 @@ describe('## NotificateDelegatorsUtils', () => {
expect(getCurrentRoundInfoStub.called)
expect(getSubscriptorRoleStub.called)
})

it('Should continue if the subscriber is in unbonded state, and lastEmailSentForUnbondedStatus is set', async () => {
// given
let delegator = createDelegator('0x12312312312')

const currentRound = 10
const currentRoundInfo = {
id: currentRound
}
const subscriber = createSubscriber()
subscriber.lastEmailSentForUnbondedStatus = 2
const subscribers = [subscriber]

const constants = getLivepeerDefaultConstants()
delegator.status = constants.DELEGATOR_STATUS.Unbonded

const subscriptorRoleReturn = { role: constants.ROLE.DELEGATOR, constants, delegator }
const logExpectation1 = `[Notificate-Delegators] - Start sending email notification to delegators`
const logExpectation2 = `[Notificate-Delegators] - Not sending email to ${subscriber.email} because is in Unbonded state and already sent an email in the last ${subscriber.lastEmailSentForUnbondedStatus} round`
const logExpectation3 = `[Notificate-Delegators] - Emails subscribers to notify 0`
const logExpectation4 = `[Subscribers-utils] - Returning list of email subscribers delegators`
const logExpectation5 = `[Subscribers-utils] - Amount of email subscribers delegators: ${subscribers.length}`

// Stubs the return of Subscriber.find to return the list of subscribers
subscriberMock = sinon.mock(Subscriber)

const expectationSubscriber = subscriberMock
.expects('find')
.once()
.resolves(subscribers)

// Stubs the return of getSubscriptorRole to make the subscriber a delegate
getSubscriptorRoleStub = sinon
.stub(subscriberUtils, 'getSubscriptorRole')
.returns(subscriptorRoleReturn)

consoleLogMock = sinon.mock(console)

const expectationConsole1 = consoleLogMock
.expects('log')
.once()
.withArgs(logExpectation1)

const expectationConsole2 = consoleLogMock
.expects('log')
.once()
.withArgs(logExpectation2)

const expectationConsole3 = consoleLogMock
.expects('log')
.once()
.withArgs(logExpectation3)

const expectationConsole4 = consoleLogMock
.expects('log')
.once()
.withArgs(logExpectation4)

const expectationConsole5 = consoleLogMock
.expects('log')
.once()
.withArgs(logExpectation5)

// Stubs the return of getCurrentRoundInfo to return an mocked id
getCurrentRoundInfoStub = sinon
.stub(protocolService, 'getCurrentRoundInfo')
.returns(currentRoundInfo)

getDidDelegateCalledRewardStub = sinon.stub(utils, 'getDidDelegateCalledReward').returns(true)

getDelegatorNextRewardStub = sinon.stub(delegatorService, 'getDelegatorNextReward').returns(1)

getLivepeerDefaultConstantsStub = sinon
.stub(protocolService, 'getLivepeerDefaultConstants')
.returns(constants)

delegatorEmailUtilsMock = sinon.mock(delegatorEmailUtils)

const expectation = delegatorEmailUtilsMock
.expects('sendDelegatorNotificationEmail')
.never()
.resolves(null)

// when
await notificateDelegatorUtils.sendEmailRewardCallNotificationToDelegators(currentRoundInfo)

// then
consoleLogMock.verify()
subscriberMock.verify()
delegatorEmailUtilsMock.verify()
expect(getLivepeerDefaultConstantsStub.called)
expect(getDelegatorNextRewardStub.called)
expect(getDidDelegateCalledRewardStub.called)
expect(getCurrentRoundInfoStub.called)
expect(getSubscriptorRoleStub.called)
})

it('Should not continue if the subscriber is not in the unbonded state, and lastEmailSentForUnbondedStatus is set', async () => {
// given
let delegator = createDelegator('0x12312312312')

const currentRound = 10
const currentRoundInfo = {
id: currentRound
}
let subscriberData = createSubscriber()
subscriberData.lastEmailSentForUnbondedStatus = 2
const subscriber = new Subscriber(subscriberData)

const subscribers = [subscriber]

const constants = getLivepeerDefaultConstants()
delegator.status = constants.DELEGATOR_STATUS.Bonded

const subscriptorRoleReturn = { role: constants.ROLE.DELEGATOR, constants, delegator }
const logExpectation1 = `[Notificate-Delegators] - Start sending email notification to delegators`
const logExpectation2 = `[Notificate-Delegators] - Emails subscribers to notify 1`
const logExpectation3 = `[Subscribers-utils] - Returning list of email subscribers delegators`
const logExpectation4 = `[Subscribers-utils] - Amount of email subscribers delegators: ${subscribers.length}`

// Stubs the return of Subscriber.find to return the list of subscribers
subscriberMock = sinon.mock(Subscriber)

const expectationSubscriber = subscriberMock
.expects('find')
.once()
.resolves(subscribers)

subscriberMockSave = sinon.stub(Subscriber.prototype, 'save').returns(subscriber)

// Stubs the return of getSubscriptorRole to make the subscriber a delegate
getSubscriptorRoleStub = sinon
.stub(subscriberUtils, 'getSubscriptorRole')
.returns(subscriptorRoleReturn)

consoleLogMock = sinon.mock(console)

const expectationConsole1 = consoleLogMock
.expects('log')
.once()
.withArgs(logExpectation1)

const expectationConsole2 = consoleLogMock
.expects('log')
.once()
.withArgs(logExpectation2)

const expectationConsole3 = consoleLogMock
.expects('log')
.once()
.withArgs(logExpectation3)

const expectationConsole4 = consoleLogMock
.expects('log')
.once()
.withArgs(logExpectation4)

// Stubs the return of getCurrentRoundInfo to return an mocked id
getCurrentRoundInfoStub = sinon
.stub(protocolService, 'getCurrentRoundInfo')
.returns(currentRoundInfo)

getDidDelegateCalledRewardStub = sinon.stub(utils, 'getDidDelegateCalledReward').returns(true)

getDelegatorNextRewardStub = sinon.stub(delegatorService, 'getDelegatorNextReward').returns(1)

getLivepeerDefaultConstantsStub = sinon
.stub(protocolService, 'getLivepeerDefaultConstants')
.returns(constants)

delegatorEmailUtilsMock = sinon.mock(delegatorEmailUtils)

const expectation = delegatorEmailUtilsMock
.expects('sendDelegatorNotificationEmail')
.once()
.resolves(null)

// when
await notificateDelegatorUtils.sendEmailRewardCallNotificationToDelegators(currentRoundInfo)

// then
consoleLogMock.verify()
subscriberMock.verify()
delegatorEmailUtilsMock.verify()
expect(getLivepeerDefaultConstantsStub.called)
expect(getDelegatorNextRewardStub.called)
expect(getDidDelegateCalledRewardStub.called)
expect(getCurrentRoundInfoStub.called)
expect(getSubscriptorRoleStub.called)
})
})

describe('# sendEmailAfterBondingPeriodHasEndedNotificationToDelegators', () => {
Expand Down