-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #238 from adhocteam/data-validation-script
Add data validation script
- Loading branch information
Showing
7 changed files
with
129 additions
and
8 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
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
import { QueryTypes } from 'sequelize'; | ||
import { sequelize } from '../models'; | ||
import { auditLogger } from '../logger'; | ||
|
||
const runSelectQuery = (query) => ( | ||
sequelize.query(query, { type: QueryTypes.SELECT }) | ||
); | ||
|
||
const countAndLastUpdated = async (tableName) => { | ||
const updatedAtQuery = `SELECT "updatedAt" FROM "${tableName}" ORDER BY "updatedAt" DESC LIMIT 1`; | ||
const [results] = await runSelectQuery(updatedAtQuery); | ||
let updatedAt = ''; | ||
if (results) { updatedAt = results.updatedAt; } | ||
const countQuery = `SELECT count(*) FROM "${tableName}"`; | ||
const [{ count }] = await runSelectQuery(countQuery); | ||
return { | ||
updatedAt, | ||
count, | ||
}; | ||
}; | ||
|
||
const dataValidation = async () => { | ||
let query; | ||
let results; | ||
const tableNames = [ | ||
'ActivityReports', | ||
'Files', | ||
'Goals', | ||
'Objectives', | ||
'NextSteps', | ||
'Grantees', | ||
'Grants', | ||
'Users', | ||
]; | ||
const tableChecks = tableNames.map(async (table) => { | ||
const { updatedAt, count } = await countAndLastUpdated(table); | ||
auditLogger.info(`${table} has ${count} records, last updated at: ${updatedAt}`); | ||
}); | ||
await Promise.allSettled(tableChecks); | ||
|
||
query = 'SELECT "regionId", "status", count(*) FROM "Grants" GROUP BY "regionId", "status" ORDER BY "regionId", "status"'; | ||
results = await runSelectQuery(query); | ||
auditLogger.info(`Grants data counts: ${JSON.stringify(results, null, 2)}`); | ||
|
||
query = 'SELECT "regionId", "status", count(*) FROM "ActivityReports" GROUP BY "regionId", "status" ORDER BY "regionId", "status"'; | ||
results = await runSelectQuery(query); | ||
auditLogger.info(`ActivityReports data counts: ${JSON.stringify(results, null, 2)}`); | ||
}; | ||
|
||
export { | ||
runSelectQuery, | ||
countAndLastUpdated, | ||
}; | ||
export default dataValidation; |
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,45 @@ | ||
import dataValidation, { countAndLastUpdated, runSelectQuery } from './dataValidation'; | ||
import { sequelize } from '../models'; | ||
import { auditLogger } from '../logger'; | ||
import { DECIMAL_BASE } from '../constants'; | ||
|
||
jest.mock('../logger'); | ||
|
||
describe('dataValidation', () => { | ||
afterAll(async () => { | ||
await sequelize.close(); | ||
}); | ||
|
||
describe('run basic query', () => { | ||
it('should return the data in an object', async () => { | ||
const query = 'SELECT "regionId", "status", count(*) FROM "Grants" GROUP BY "regionId", "status" ORDER BY "regionId", "status"'; | ||
const [ | ||
{ regionId: firstRowRegion, status: firstRowStatus, count: firstRowCount }, | ||
{ regionId: secondRowRegion, status: secondRowStatus, count: secondRowCount }, | ||
] = await runSelectQuery(query); | ||
|
||
expect(firstRowRegion).toBe(1); | ||
expect(firstRowStatus).toBe('Active'); | ||
expect(firstRowCount).toBe('2'); | ||
expect(secondRowRegion).toBe(1); | ||
expect(secondRowStatus).toBe('Inactive'); | ||
expect(secondRowCount).toBe('1'); | ||
}); | ||
}); | ||
|
||
describe('run count and last updated', () => { | ||
it('should return the count and last updated value for the given table', async () => { | ||
const { | ||
updatedAt, | ||
count, | ||
} = await countAndLastUpdated('Grants'); | ||
expect(parseInt(count, DECIMAL_BASE)).toBeGreaterThan(0); | ||
expect(updatedAt).not.toBe(''); | ||
}); | ||
}); | ||
|
||
it('should log results to the auditLogger', async () => { | ||
await dataValidation(); | ||
expect(auditLogger.info).toHaveBeenCalledTimes(10); | ||
}); | ||
}); |
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,14 @@ | ||
import dataValidation from './dataValidation'; | ||
import { auditLogger } from '../logger'; | ||
|
||
/** | ||
* dataValidationCLI runs basic queries against the DB to verify that the db state | ||
* is as we expect following import or restore operations. | ||
* | ||
* To run: `cf run-task tta-smarthub-prod --command "yarn db:validation"` | ||
*/ | ||
|
||
dataValidation().catch((e) => { | ||
auditLogger.error(e); | ||
return process.exit(1); | ||
}); |