-
Notifications
You must be signed in to change notification settings - Fork 123
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[OTE-135] add roundtable task for CLOSE_ONLY -> BLOCKED compliance st…
…atus transition (#1034)
- Loading branch information
Showing
5 changed files
with
171 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
103 changes: 103 additions & 0 deletions
103
indexer/services/roundtable/__tests__/tasks/perform-compliance-status-transitions.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
import { | ||
dbHelpers, | ||
testConstants, | ||
ComplianceStatusTable, | ||
ComplianceStatus, | ||
testMocks, | ||
} from '@dydxprotocol-indexer/postgres'; | ||
import performComplianceStatusTransitionsTask from '../../src/tasks/perform-compliance-status-transitions'; | ||
import { logger, stats } from '@dydxprotocol-indexer/base'; | ||
import config from '../../src/config'; | ||
import { DateTime } from 'luxon'; | ||
|
||
describe('update-close-only-status', () => { | ||
beforeAll(async () => { | ||
await dbHelpers.migrate(); | ||
await dbHelpers.clearData(); | ||
}); | ||
|
||
beforeEach(async () => { | ||
await testMocks.seedData(); | ||
jest.spyOn(stats, 'increment'); | ||
jest.spyOn(stats, 'timing'); | ||
jest.spyOn(stats, 'gauge'); | ||
jest.spyOn(logger, 'error'); | ||
}); | ||
|
||
afterEach(async () => { | ||
await dbHelpers.clearData(); | ||
jest.clearAllMocks(); | ||
}); | ||
|
||
afterAll(async () => { | ||
await dbHelpers.teardown(); | ||
jest.resetAllMocks(); | ||
}); | ||
|
||
it('succeeds with no CLOSE_ONLY addresses', async () => { | ||
await performComplianceStatusTransitionsTask(); | ||
|
||
// Assert no addresses were updated | ||
expect(stats.gauge).toHaveBeenCalledWith( | ||
`${config.SERVICE_NAME}.num_stale_close_only_updated.count`, | ||
0, | ||
); | ||
expect(stats.gauge).toHaveBeenCalledWith( | ||
`${config.SERVICE_NAME}.num_stale_close_only.count`, | ||
0, | ||
); | ||
}); | ||
|
||
it('updates CLOSE_ONLY addresses older than 7 days to BLOCKED', async () => { | ||
config.CLOSE_ONLY_TO_BLOCKED_DAYS = 7; | ||
// Seed database with CLOSE_ONLY compliance status older than 7 days | ||
const oldUpdatedAt = DateTime.utc().minus({ days: 8 }).toISO(); | ||
const newTs = DateTime.utc().toISO(); | ||
await Promise.all([ | ||
ComplianceStatusTable.create({ | ||
address: testConstants.blockedAddress, | ||
status: ComplianceStatus.CLOSE_ONLY, | ||
createdAt: oldUpdatedAt, | ||
updatedAt: oldUpdatedAt, | ||
}), | ||
ComplianceStatusTable.create({ | ||
address: testConstants.defaultAddress, | ||
status: ComplianceStatus.CLOSE_ONLY, | ||
createdAt: newTs, | ||
updatedAt: newTs, | ||
}), | ||
]); | ||
|
||
await performComplianceStatusTransitionsTask(); | ||
|
||
// Assert the status was updated to BLOCKED | ||
const updatedStatus = await ComplianceStatusTable.findAll( | ||
{ address: [testConstants.blockedAddress] }, | ||
[], | ||
{}, | ||
); | ||
expect(updatedStatus[0].status).toEqual(ComplianceStatus.BLOCKED); | ||
expect(updatedStatus[0].updatedAt).not.toEqual(oldUpdatedAt); | ||
const nonUpdatedStatus = await ComplianceStatusTable.findAll( | ||
{ address: [testConstants.defaultAddress] }, | ||
[], | ||
{}, | ||
); | ||
expect(nonUpdatedStatus[0]).toEqual(expect.objectContaining({ | ||
address: testConstants.defaultAddress, | ||
status: ComplianceStatus.CLOSE_ONLY, | ||
createdAt: newTs, | ||
updatedAt: newTs, | ||
})); | ||
|
||
// Assert the stats were correctly recorded | ||
expect(stats.gauge).toHaveBeenCalledWith( | ||
`${config.SERVICE_NAME}.num_stale_close_only_updated.count`, | ||
1, | ||
); | ||
expect(stats.gauge).toHaveBeenCalledWith( | ||
`${config.SERVICE_NAME}.num_stale_close_only.count`, | ||
1, | ||
); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
56 changes: 56 additions & 0 deletions
56
indexer/services/roundtable/src/tasks/perform-compliance-status-transitions.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
import { | ||
ONE_DAY_IN_MILLISECONDS, | ||
stats, | ||
} from '@dydxprotocol-indexer/base'; | ||
import { | ||
ComplianceStatusFromDatabase, | ||
ComplianceStatusTable, | ||
ComplianceStatus, | ||
} from '@dydxprotocol-indexer/postgres'; | ||
|
||
import config from '../config'; | ||
|
||
// eslint-disable-next-line max-len | ||
const CLOSE_ONLY_TO_BLOCKED_DAYS_IN_MS: number = config.CLOSE_ONLY_TO_BLOCKED_DAYS * ONE_DAY_IN_MILLISECONDS; | ||
|
||
export default async function runTask(): Promise<void> { | ||
const queryStart: number = Date.now(); | ||
|
||
// Query for addresses with status CLOSE_ONLY and updatedAt less than NOW() - INTERVAL days | ||
const staleCloseOnlyAddresses: ComplianceStatusFromDatabase[] = await | ||
ComplianceStatusTable.findAll( | ||
{ | ||
status: ComplianceStatus.CLOSE_ONLY, | ||
updatedBeforeOrAt: new Date( | ||
queryStart - CLOSE_ONLY_TO_BLOCKED_DAYS_IN_MS, | ||
).toISOString(), | ||
}, | ||
[], | ||
{ | ||
readReplica: true, | ||
}, | ||
); | ||
stats.timing(`${config.SERVICE_NAME}.query_stale_close_only.timing`, Date.now() - queryStart); | ||
|
||
const updateStart: number = Date.now(); | ||
const addressesToUpdate: string[] = staleCloseOnlyAddresses.map( | ||
(record: ComplianceStatusFromDatabase) => record.address, | ||
); | ||
|
||
// Update addresses status to BLOCKED | ||
const updatedAddresses: ComplianceStatusFromDatabase[] = await Promise.all( | ||
addressesToUpdate.map((address) => ComplianceStatusTable.update({ | ||
address, | ||
status: ComplianceStatus.BLOCKED, | ||
updatedAt: new Date().toISOString(), | ||
}), | ||
), | ||
) as ComplianceStatusFromDatabase[]; | ||
|
||
stats.timing( | ||
`${config.SERVICE_NAME}.update_stale_close_only.timing`, | ||
Date.now() - updateStart, | ||
); | ||
stats.gauge(`${config.SERVICE_NAME}.num_stale_close_only.count`, addressesToUpdate.length); | ||
stats.gauge(`${config.SERVICE_NAME}.num_stale_close_only_updated.count`, updatedAddresses.length); | ||
} |