-
Notifications
You must be signed in to change notification settings - Fork 133
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
[IND-552] add roundtable task to take fast sync Postgres snapshots every 4 hours #912
Changes from 13 commits
6c04868
ffe0b2f
f8515a4
8851dbb
697bc6a
64054d6
424ca36
62a00b2
8460623
a0898af
4de0f17
f5ad041
fa75ea8
8ca7474
90b2f58
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
import config from '../../src/config'; | ||
import { asMock } from '@dydxprotocol-indexer/dev'; | ||
import { | ||
createDBSnapshot, | ||
deleteOldFastSyncSnapshots, | ||
getMostRecentDBSnapshotIdentifier, | ||
} from '../../src/helpers/aws'; | ||
import takeFastSyncSnapshotTask from '../../src/tasks/take-fast-sync-snapshot'; | ||
import { DateTime } from 'luxon'; | ||
|
||
jest.mock('../../src/helpers/aws'); | ||
|
||
describe('fast-sync-export-db-snapshot', () => { | ||
const snapshotIdentifier: string = `${config.FAST_SYNC_SNAPSHOT_IDENTIFIER_PREFIX}-postgres-main-staging-2022-05-03-04-16`; | ||
beforeAll(() => { | ||
config.RDS_INSTANCE_NAME = 'postgres-main-staging'; | ||
}); | ||
|
||
beforeEach(() => { | ||
jest.resetAllMocks(); | ||
asMock(getMostRecentDBSnapshotIdentifier).mockImplementation( | ||
async () => Promise.resolve(snapshotIdentifier), | ||
); | ||
}); | ||
|
||
afterAll(jest.resetAllMocks); | ||
|
||
it('Last snapshot was taken more than interval ago', async () => { | ||
await takeFastSyncSnapshotTask(); | ||
|
||
expect(createDBSnapshot).toHaveBeenCalled(); | ||
expect(deleteOldFastSyncSnapshots).toHaveBeenCalled(); | ||
}); | ||
|
||
it('Last snapshot was taken less than interval ago', async () => { | ||
const timestamp: string = DateTime.utc().minus({ minutes: 1 }).toFormat('yyyy-MM-dd-HH-mm'); | ||
asMock(getMostRecentDBSnapshotIdentifier).mockImplementation( | ||
async () => Promise.resolve(`${config.FAST_SYNC_SNAPSHOT_IDENTIFIER_PREFIX}-postgres-main-staging-${timestamp}`), | ||
); | ||
|
||
await takeFastSyncSnapshotTask(); | ||
|
||
expect(createDBSnapshot).not.toHaveBeenCalled(); | ||
expect(deleteOldFastSyncSnapshots).not.toHaveBeenCalled(); | ||
}); | ||
|
||
it('No existing snapshot', async () => { | ||
asMock(getMostRecentDBSnapshotIdentifier).mockImplementation( | ||
async () => Promise.resolve(undefined), | ||
); | ||
|
||
await takeFastSyncSnapshotTask(); | ||
|
||
expect(createDBSnapshot).toHaveBeenCalled(); | ||
expect(deleteOldFastSyncSnapshots).toHaveBeenCalled(); | ||
}); | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
import { logger, stats } from '@dydxprotocol-indexer/base'; | ||
import RDS from 'aws-sdk/clients/rds'; | ||
import { DateTime } from 'luxon'; | ||
|
||
import config from '../config'; | ||
import { | ||
createDBSnapshot, | ||
deleteOldFastSyncSnapshots, | ||
getMostRecentDBSnapshotIdentifier, | ||
} from '../helpers/aws'; | ||
|
||
const statStart: string = `${config.SERVICE_NAME}.fast_sync_export_db_snapshot`; | ||
|
||
/** | ||
* Checks if the difference between two dates is less than a given interval. | ||
* | ||
* @param startDate | ||
* @param endDate | ||
* @param intervalMs | ||
*/ | ||
function isDifferenceLessThanInterval( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: move this under runTask so that the top level function is at the top of the file There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
startDate: string, | ||
endDate: string, | ||
intervalMs: number, | ||
): boolean { | ||
const parseDateString = (dateStr: string): Date => { | ||
const [year, month, day, hour, minute] = dateStr.split('-').map(Number); | ||
return new Date(year, month, day, hour, minute); | ||
}; | ||
|
||
// Parse the date strings | ||
const parsedDate1 = parseDateString(startDate); | ||
const parsedDate2 = parseDateString(endDate); | ||
|
||
// Calculate the difference in milliseconds | ||
const differenceInMilliseconds = Math.abs(parsedDate1.getTime() - parsedDate2.getTime()); | ||
|
||
// Compare with the interval | ||
return differenceInMilliseconds < intervalMs; | ||
} | ||
|
||
export default async function runTask(): Promise<void> { | ||
const at: string = 'fast-sync-export-db-snapshot#runTask'; | ||
logger.info({ at, message: 'Starting task.' }); | ||
|
||
const rds: RDS = new RDS(); | ||
|
||
const dateString: string = DateTime.utc().toFormat('yyyy-MM-dd-HH-mm'); | ||
const snapshotIdentifier: string = `${config.FAST_SYNC_SNAPSHOT_IDENTIFIER_PREFIX}-${config.RDS_INSTANCE_NAME}-${dateString}`; | ||
// check the time of the last snapshot | ||
const lastSnapshotIdentifier: string | undefined = await getMostRecentDBSnapshotIdentifier( | ||
rds, | ||
config.FAST_SYNC_SNAPSHOT_IDENTIFIER_PREFIX, | ||
); | ||
if (lastSnapshotIdentifier !== undefined) { | ||
const s3Date: string = lastSnapshotIdentifier.split(config.RDS_INSTANCE_NAME)[1].slice(1); | ||
if ( | ||
isDifferenceLessThanInterval( | ||
s3Date, | ||
dateString, | ||
config.LOOPS_INTERVAL_MS_TAKE_FAST_SYNC_SNAPSHOTS, | ||
) | ||
) { | ||
stats.increment(`${statStart}.existingDbSnapshot`, 1); | ||
logger.info({ | ||
at, | ||
message: 'Last fast sync db snapshot was taken less than the interval ago', | ||
interval: config.LOOPS_INTERVAL_MS_TAKE_FAST_SYNC_SNAPSHOTS, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: log the s3Date and dateString There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
}); | ||
return; | ||
} | ||
} | ||
// Create the DB snapshot | ||
const startSnapshot: number = Date.now(); | ||
const createdSnapshotIdentifier: string = await | ||
createDBSnapshot(rds, snapshotIdentifier, config.RDS_INSTANCE_NAME); | ||
logger.info({ at, message: 'Created DB snapshot.', snapshotIdentifier: createdSnapshotIdentifier }); | ||
stats.timing(`${statStart}.createDbSnapshot`, Date.now() - startSnapshot); | ||
const startDeleteOldSnapshot: number = Date.now(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: separate into a separate function There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
// Delete old snapshots. | ||
await deleteOldFastSyncSnapshots(rds); | ||
stats.timing(`${statStart}.deleteOldSnapshots`, Date.now() - startDeleteOldSnapshot); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: can we log an error here? Technically there shouldn't be anything that doesn't match our fast sync identifier right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the rds automated daily snapshots will also be included here