mirror of https://github.com/nocodb/nocodb
Pranav C
2 years ago
5 changed files with 696 additions and 1 deletions
@ -0,0 +1,195 @@ |
|||||||
|
import axios from 'axios'; |
||||||
|
import Project from '../../../models/Project'; |
||||||
|
import NcConnectionMgrv2 from '../../../utils/common/NcConnectionMgrv2'; |
||||||
|
import Noco from '../../../Noco'; |
||||||
|
import User from '../../../models/User'; |
||||||
|
import NocoCache from '../../../cache/NocoCache'; |
||||||
|
import { CacheScope } from '../../../utils/globals'; |
||||||
|
import ProjectUser from '../../../models/ProjectUser'; |
||||||
|
import resetPgSakilaProject from './resetPgSakilaProject'; |
||||||
|
import resetMysqlSakilaProject from './resetMysqlSakilaProject'; |
||||||
|
import resetMetaSakilaSqliteProject from './resetMetaSakilaSqliteProject'; |
||||||
|
|
||||||
|
const workerStatus = {}; |
||||||
|
|
||||||
|
const loginRootUser = async () => { |
||||||
|
const response = await axios.post( |
||||||
|
'http://localhost:8080/api/v1/auth/user/signin', |
||||||
|
{ email: 'user@nocodb.com', password: 'Password123.' } |
||||||
|
); |
||||||
|
|
||||||
|
return response.data.token; |
||||||
|
}; |
||||||
|
|
||||||
|
const projectTitleByType = { |
||||||
|
sqlite: 'sampleREST', |
||||||
|
mysql: 'externalREST', |
||||||
|
pg: 'pgExtREST', |
||||||
|
}; |
||||||
|
|
||||||
|
export class TestResetService { |
||||||
|
private readonly parallelId; |
||||||
|
// todo: Hack to resolve issue with pg resetting
|
||||||
|
private readonly workerId; |
||||||
|
private readonly dbType; |
||||||
|
private readonly isEmptyProject: boolean; |
||||||
|
|
||||||
|
constructor({ |
||||||
|
parallelId, |
||||||
|
dbType, |
||||||
|
isEmptyProject, |
||||||
|
workerId, |
||||||
|
}: { |
||||||
|
parallelId: string; |
||||||
|
dbType: string; |
||||||
|
isEmptyProject: boolean; |
||||||
|
workerId: string; |
||||||
|
}) { |
||||||
|
this.parallelId = parallelId; |
||||||
|
this.dbType = dbType; |
||||||
|
this.isEmptyProject = isEmptyProject; |
||||||
|
this.workerId = workerId; |
||||||
|
} |
||||||
|
|
||||||
|
async process() { |
||||||
|
try { |
||||||
|
// console.log(
|
||||||
|
// `earlier workerStatus: parrelledId: ${this.parallelId}:`,
|
||||||
|
// workerStatus[this.parallelId]
|
||||||
|
// );
|
||||||
|
|
||||||
|
// wait till previous worker is done
|
||||||
|
while (workerStatus[this.parallelId] === 'processing') { |
||||||
|
console.log( |
||||||
|
`waiting for previous worker to finish parrelelId:${this.parallelId}` |
||||||
|
); |
||||||
|
await new Promise((resolve) => setTimeout(resolve, 1000)); |
||||||
|
} |
||||||
|
|
||||||
|
workerStatus[this.parallelId] = 'processing'; |
||||||
|
|
||||||
|
const token = await loginRootUser(); |
||||||
|
|
||||||
|
const { project } = await this.resetProject({ |
||||||
|
token, |
||||||
|
dbType: this.dbType, |
||||||
|
parallelId: this.parallelId, |
||||||
|
workerId: this.workerId, |
||||||
|
}); |
||||||
|
|
||||||
|
try { |
||||||
|
await removeAllProjectCreatedByTheTest(this.parallelId); |
||||||
|
await removeAllPrefixedUsersExceptSuper(this.parallelId); |
||||||
|
} catch (e) { |
||||||
|
console.log(`Error in cleaning up project: ${this.parallelId}`, e); |
||||||
|
} |
||||||
|
|
||||||
|
workerStatus[this.parallelId] = 'completed'; |
||||||
|
return { token, project }; |
||||||
|
} catch (e) { |
||||||
|
console.error('TestResetService:process', e); |
||||||
|
workerStatus[this.parallelId] = 'errored'; |
||||||
|
return { error: e }; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
async resetProject({ |
||||||
|
token, |
||||||
|
dbType, |
||||||
|
parallelId, |
||||||
|
workerId, |
||||||
|
}: { |
||||||
|
token: string; |
||||||
|
dbType: string; |
||||||
|
parallelId: string; |
||||||
|
workerId: string; |
||||||
|
}) { |
||||||
|
const title = `${projectTitleByType[dbType]}${parallelId}`; |
||||||
|
const project: Project | undefined = await Project.getByTitle(title); |
||||||
|
|
||||||
|
if (project) { |
||||||
|
await removeProjectUsersFromCache(project); |
||||||
|
|
||||||
|
const bases = await project.getBases(); |
||||||
|
|
||||||
|
for (const base of bases) { |
||||||
|
await NcConnectionMgrv2.deleteAwait(base); |
||||||
|
await base.delete(Noco.ncMeta, { force: true }); |
||||||
|
} |
||||||
|
|
||||||
|
await Project.delete(project.id); |
||||||
|
} |
||||||
|
|
||||||
|
if (dbType == 'sqlite') { |
||||||
|
await resetMetaSakilaSqliteProject({ |
||||||
|
token, |
||||||
|
title, |
||||||
|
parallelId, |
||||||
|
isEmptyProject: this.isEmptyProject, |
||||||
|
}); |
||||||
|
} else if (dbType == 'mysql') { |
||||||
|
await resetMysqlSakilaProject({ |
||||||
|
token, |
||||||
|
title, |
||||||
|
parallelId, |
||||||
|
oldProject: project, |
||||||
|
isEmptyProject: this.isEmptyProject, |
||||||
|
}); |
||||||
|
} else if (dbType == 'pg') { |
||||||
|
await resetPgSakilaProject({ |
||||||
|
token, |
||||||
|
title, |
||||||
|
parallelId: workerId, |
||||||
|
oldProject: project, |
||||||
|
isEmptyProject: this.isEmptyProject, |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
return { |
||||||
|
project: await Project.getByTitle(title), |
||||||
|
}; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
const removeAllProjectCreatedByTheTest = async (parallelId: string) => { |
||||||
|
const projects = await Project.list({}); |
||||||
|
|
||||||
|
for (const project of projects) { |
||||||
|
if (project.title.startsWith(`nc_test_${parallelId}_`)) { |
||||||
|
await Project.delete(project.id); |
||||||
|
} |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
const removeAllPrefixedUsersExceptSuper = async (parallelId: string) => { |
||||||
|
const users = (await User.list()).filter( |
||||||
|
(user) => !user.roles.includes('super') |
||||||
|
); |
||||||
|
|
||||||
|
for (const user of users) { |
||||||
|
if (user.email.startsWith(`nc_test_${parallelId}_`)) { |
||||||
|
await NocoCache.del(`${CacheScope.USER}:${user.email}`); |
||||||
|
await User.delete(user.id); |
||||||
|
} |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
// todo: Remove this once user deletion improvement PR is merged
|
||||||
|
const removeProjectUsersFromCache = async (project: Project) => { |
||||||
|
const projectUsers: ProjectUser[] = await ProjectUser.getUsersList({ |
||||||
|
project_id: project.id, |
||||||
|
limit: 1000, |
||||||
|
offset: 0, |
||||||
|
}); |
||||||
|
|
||||||
|
for (const projectUser of projectUsers) { |
||||||
|
try { |
||||||
|
const user: User = await User.get(projectUser.fk_user_id); |
||||||
|
await NocoCache.del( |
||||||
|
`${CacheScope.PROJECT_USER}:${project.id}:${user.id}` |
||||||
|
); |
||||||
|
} catch (e) { |
||||||
|
console.error('removeProjectUsersFromCache', e); |
||||||
|
} |
||||||
|
} |
||||||
|
}; |
@ -0,0 +1,92 @@ |
|||||||
|
import { promises as fs } from 'fs'; |
||||||
|
import axios from 'axios'; |
||||||
|
|
||||||
|
const sqliteFilePath = (parallelId: string) => { |
||||||
|
const rootDir = __dirname.replace( |
||||||
|
'/src/lib/services/test/TestResetService', |
||||||
|
'', |
||||||
|
); |
||||||
|
|
||||||
|
return `${rootDir}/test_sakila_${parallelId}.db`; |
||||||
|
}; |
||||||
|
|
||||||
|
const sakilaProjectConfig = (title: string, parallelId: string) => ({ |
||||||
|
title, |
||||||
|
bases: [ |
||||||
|
{ |
||||||
|
type: 'sqlite3', |
||||||
|
config: { |
||||||
|
client: 'sqlite3', |
||||||
|
connection: { |
||||||
|
client: 'sqlite3', |
||||||
|
connection: { |
||||||
|
filename: sqliteFilePath(parallelId), |
||||||
|
database: 'test_sakila', |
||||||
|
multipleStatements: true, |
||||||
|
}, |
||||||
|
}, |
||||||
|
}, |
||||||
|
inflection_column: 'camelize', |
||||||
|
inflection_table: 'camelize', |
||||||
|
}, |
||||||
|
], |
||||||
|
external: true, |
||||||
|
}); |
||||||
|
|
||||||
|
const resetMetaSakilaSqliteProject = async ({ |
||||||
|
parallelId, |
||||||
|
token, |
||||||
|
title, |
||||||
|
isEmptyProject, |
||||||
|
}: { |
||||||
|
parallelId: string; |
||||||
|
token: string; |
||||||
|
title: string; |
||||||
|
isEmptyProject: boolean; |
||||||
|
}) => { |
||||||
|
await deleteSqliteFileIfExists(parallelId); |
||||||
|
|
||||||
|
if (!isEmptyProject) await seedSakilaSqliteFile(parallelId); |
||||||
|
|
||||||
|
await createProject(token, title, parallelId); |
||||||
|
}; |
||||||
|
|
||||||
|
const createProject = async ( |
||||||
|
token: string, |
||||||
|
title: string, |
||||||
|
parallelId: string, |
||||||
|
) => { |
||||||
|
const response = await axios.post( |
||||||
|
'http://localhost:8080/api/v1/db/meta/projects/', |
||||||
|
sakilaProjectConfig(title, parallelId), |
||||||
|
{ |
||||||
|
headers: { |
||||||
|
'xc-auth': token, |
||||||
|
}, |
||||||
|
}, |
||||||
|
); |
||||||
|
if (response.status !== 200) { |
||||||
|
console.error('Error creating project', response.data); |
||||||
|
} |
||||||
|
return response.data; |
||||||
|
}; |
||||||
|
|
||||||
|
const deleteSqliteFileIfExists = async (parallelId: string) => { |
||||||
|
if (await fs.stat(sqliteFilePath(parallelId)).catch(() => null)) { |
||||||
|
await fs.unlink(sqliteFilePath(parallelId)); |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
const seedSakilaSqliteFile = async (parallelId: string) => { |
||||||
|
const testsDir = __dirname.replace( |
||||||
|
'/src/lib/services/test/TestResetService', |
||||||
|
'/tests', |
||||||
|
); |
||||||
|
|
||||||
|
await fs.copyFile( |
||||||
|
`${testsDir}/sqlite-sakila-db/sakila.db`, |
||||||
|
sqliteFilePath(parallelId), |
||||||
|
); |
||||||
|
}; |
||||||
|
|
||||||
|
export default resetMetaSakilaSqliteProject; |
@ -0,0 +1,202 @@ |
|||||||
|
import { promises as fs } from 'fs'; |
||||||
|
import axios from 'axios'; |
||||||
|
import { knex } from 'knex'; |
||||||
|
import Audit from '../../../models/Audit'; |
||||||
|
import type { Knex } from 'knex'; |
||||||
|
import type Project from '../../../models/Project'; |
||||||
|
|
||||||
|
const config = { |
||||||
|
client: 'mysql2', |
||||||
|
connection: { |
||||||
|
host: 'localhost', |
||||||
|
port: 3306, |
||||||
|
user: 'root', |
||||||
|
password: 'password', |
||||||
|
database: 'sakila', |
||||||
|
multipleStatements: true, |
||||||
|
dateStrings: true, |
||||||
|
}, |
||||||
|
}; |
||||||
|
|
||||||
|
const extMysqlProject = (title, parallelId) => ({ |
||||||
|
title, |
||||||
|
bases: [ |
||||||
|
{ |
||||||
|
type: 'mysql2', |
||||||
|
config: { |
||||||
|
client: 'mysql2', |
||||||
|
connection: { |
||||||
|
host: 'localhost', |
||||||
|
port: '3306', |
||||||
|
user: 'root', |
||||||
|
password: 'password', |
||||||
|
database: `test_sakila_${parallelId}`, |
||||||
|
}, |
||||||
|
}, |
||||||
|
inflection_column: 'camelize', |
||||||
|
inflection_table: 'camelize', |
||||||
|
}, |
||||||
|
], |
||||||
|
external: true, |
||||||
|
}); |
||||||
|
|
||||||
|
const isSakilaMysqlToBeReset = async ( |
||||||
|
knex: Knex, |
||||||
|
parallelId: string, |
||||||
|
project?: Project, |
||||||
|
) => { |
||||||
|
const tablesInDbInfo: Array<any> = await knex.raw( |
||||||
|
`SELECT table_name FROM information_schema.tables WHERE table_schema = 'test_sakila_${parallelId}'`, |
||||||
|
); |
||||||
|
|
||||||
|
const nonMetaTablesInDb = tablesInDbInfo[0] |
||||||
|
.map((t) => t['TABLE_NAME']) |
||||||
|
.filter((table) => table !== 'nc_evolutions'); |
||||||
|
|
||||||
|
const mysqlSakilaTablesAndViews = [ |
||||||
|
...mysqlSakilaTables, |
||||||
|
...mysqlSakilaSqlViews, |
||||||
|
]; |
||||||
|
|
||||||
|
if ( |
||||||
|
nonMetaTablesInDb.length === 0 || |
||||||
|
// If there are sakila tables
|
||||||
|
!nonMetaTablesInDb.includes(`actor`) || |
||||||
|
// If there are no pg sakila tables in tables in db
|
||||||
|
!( |
||||||
|
nonMetaTablesInDb.length === mysqlSakilaTablesAndViews.length && |
||||||
|
nonMetaTablesInDb.every((t) => mysqlSakilaTablesAndViews.includes(t)) |
||||||
|
) |
||||||
|
) { |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
if (!project) return true; |
||||||
|
|
||||||
|
const audits = await Audit.projectAuditList(project.id, {}); |
||||||
|
|
||||||
|
// todo: Will be fixed in the data resetting revamp
|
||||||
|
console.log(`audits:resetMysqlSakilaProject:${parallelId}`, audits?.length); |
||||||
|
return true; |
||||||
|
}; |
||||||
|
|
||||||
|
const resetSakilaMysql = async ( |
||||||
|
knex: Knex, |
||||||
|
parallelId: string, |
||||||
|
isEmptyProject: boolean, |
||||||
|
) => { |
||||||
|
const testsDir = __dirname.replace( |
||||||
|
'/src/lib/services/test/TestResetService', |
||||||
|
'/tests', |
||||||
|
); |
||||||
|
|
||||||
|
try { |
||||||
|
await knex.raw(`DROP DATABASE test_sakila_${parallelId}`); |
||||||
|
} catch (e) { |
||||||
|
console.log('Error dropping db', e); |
||||||
|
} |
||||||
|
await knex.raw(`CREATE DATABASE test_sakila_${parallelId}`); |
||||||
|
|
||||||
|
if (isEmptyProject) return; |
||||||
|
|
||||||
|
const trx = await knex.transaction(); |
||||||
|
|
||||||
|
try { |
||||||
|
const schemaFile = await fs.readFile( |
||||||
|
`${testsDir}/mysql-sakila-db/03-test-sakila-schema.sql`, |
||||||
|
); |
||||||
|
const dataFile = await fs.readFile( |
||||||
|
`${testsDir}/mysql-sakila-db/04-test-sakila-data.sql`, |
||||||
|
); |
||||||
|
|
||||||
|
await trx.raw( |
||||||
|
schemaFile |
||||||
|
.toString() |
||||||
|
.replace(/test_sakila/g, `test_sakila_${parallelId}`), |
||||||
|
); |
||||||
|
await trx.raw( |
||||||
|
dataFile.toString().replace(/test_sakila/g, `test_sakila_${parallelId}`), |
||||||
|
); |
||||||
|
|
||||||
|
await trx.commit(); |
||||||
|
} catch (e) { |
||||||
|
console.log('Error resetting mysql db', e); |
||||||
|
await trx.rollback(e); |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
const resetMysqlSakilaProject = async ({ |
||||||
|
token, |
||||||
|
title, |
||||||
|
parallelId, |
||||||
|
oldProject, |
||||||
|
isEmptyProject, |
||||||
|
}: { |
||||||
|
token: string; |
||||||
|
title: string; |
||||||
|
parallelId: string; |
||||||
|
oldProject?: Project | undefined; |
||||||
|
isEmptyProject: boolean; |
||||||
|
}) => { |
||||||
|
const nc_knex = knex(config); |
||||||
|
|
||||||
|
try { |
||||||
|
await nc_knex.raw(`USE test_sakila_${parallelId}`); |
||||||
|
} catch (e) { |
||||||
|
await nc_knex.raw(`CREATE DATABASE test_sakila_${parallelId}`); |
||||||
|
await nc_knex.raw(`USE test_sakila_${parallelId}`); |
||||||
|
} |
||||||
|
|
||||||
|
if ( |
||||||
|
isEmptyProject || |
||||||
|
(await isSakilaMysqlToBeReset(nc_knex, parallelId, oldProject)) |
||||||
|
) { |
||||||
|
await resetSakilaMysql(nc_knex, parallelId, isEmptyProject); |
||||||
|
} |
||||||
|
|
||||||
|
const response = await axios.post( |
||||||
|
'http://localhost:8080/api/v1/db/meta/projects/', |
||||||
|
extMysqlProject(title, parallelId), |
||||||
|
{ |
||||||
|
headers: { |
||||||
|
'xc-auth': token, |
||||||
|
}, |
||||||
|
}, |
||||||
|
); |
||||||
|
if (response.status !== 200) { |
||||||
|
console.error('Error creating project', response.data); |
||||||
|
} |
||||||
|
|
||||||
|
await nc_knex.destroy(); |
||||||
|
}; |
||||||
|
|
||||||
|
const mysqlSakilaTables = [ |
||||||
|
'actor', |
||||||
|
'address', |
||||||
|
'category', |
||||||
|
'city', |
||||||
|
'country', |
||||||
|
'customer', |
||||||
|
'film', |
||||||
|
'film_text', |
||||||
|
'film_actor', |
||||||
|
'film_category', |
||||||
|
'inventory', |
||||||
|
'language', |
||||||
|
'payment', |
||||||
|
'rental', |
||||||
|
'staff', |
||||||
|
'store', |
||||||
|
]; |
||||||
|
|
||||||
|
const mysqlSakilaSqlViews = [ |
||||||
|
'actor_info', |
||||||
|
'customer_list', |
||||||
|
'film_list', |
||||||
|
'nicer_but_slower_film_list', |
||||||
|
'sales_by_film_category', |
||||||
|
'sales_by_store', |
||||||
|
'staff_list', |
||||||
|
]; |
||||||
|
|
||||||
|
export default resetMysqlSakilaProject; |
@ -0,0 +1,193 @@ |
|||||||
|
import { promises as fs } from 'fs'; |
||||||
|
import axios from 'axios'; |
||||||
|
import { knex } from 'knex'; |
||||||
|
import Audit from '../../../models/Audit'; |
||||||
|
import type Project from '../../../models/Project'; |
||||||
|
|
||||||
|
const config = { |
||||||
|
client: 'pg', |
||||||
|
connection: { |
||||||
|
host: 'localhost', |
||||||
|
port: 5432, |
||||||
|
user: 'postgres', |
||||||
|
password: 'password', |
||||||
|
database: 'postgres', |
||||||
|
multipleStatements: true, |
||||||
|
}, |
||||||
|
searchPath: ['public', 'information_schema'], |
||||||
|
pool: { min: 0, max: 5 }, |
||||||
|
}; |
||||||
|
|
||||||
|
const extMysqlProject = (title, parallelId) => ({ |
||||||
|
title, |
||||||
|
bases: [ |
||||||
|
{ |
||||||
|
type: 'pg', |
||||||
|
config: { |
||||||
|
client: 'pg', |
||||||
|
connection: { |
||||||
|
host: 'localhost', |
||||||
|
port: '5432', |
||||||
|
user: 'postgres', |
||||||
|
password: 'password', |
||||||
|
database: `sakila_${parallelId}`, |
||||||
|
}, |
||||||
|
searchPath: ['public'], |
||||||
|
}, |
||||||
|
inflection_column: 'camelize', |
||||||
|
inflection_table: 'camelize', |
||||||
|
}, |
||||||
|
], |
||||||
|
external: true, |
||||||
|
}); |
||||||
|
|
||||||
|
const isSakilaPgToBeReset = async (parallelId: string, project?: Project) => { |
||||||
|
const sakilaKnex = knex(sakilaKnexConfig(parallelId)); |
||||||
|
|
||||||
|
const tablesInDb: Array<string> = ( |
||||||
|
await sakilaKnex.raw( |
||||||
|
`SELECT * FROM information_schema.tables WHERE table_schema = 'public'`, |
||||||
|
) |
||||||
|
).rows.map((row) => row.table_name); |
||||||
|
|
||||||
|
await sakilaKnex.destroy(); |
||||||
|
|
||||||
|
const nonMetaTablesInDb = tablesInDb.filter( |
||||||
|
(table) => table !== 'nc_evolutions', |
||||||
|
); |
||||||
|
const pgSakilaTablesAndViews = [...pgSakilaTables, ...pgSakilaSqlViews]; |
||||||
|
|
||||||
|
if ( |
||||||
|
tablesInDb.length === 0 || |
||||||
|
// If there are sakila tables
|
||||||
|
!tablesInDb.includes(`actor`) || |
||||||
|
// If there are no pg sakila tables in tables in db
|
||||||
|
!( |
||||||
|
nonMetaTablesInDb.length === pgSakilaTablesAndViews.length && |
||||||
|
nonMetaTablesInDb.every((t) => pgSakilaTablesAndViews.includes(t)) |
||||||
|
) |
||||||
|
) { |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
if (!project) return false; |
||||||
|
|
||||||
|
const audits = await Audit.projectAuditList(project.id, {}); |
||||||
|
|
||||||
|
return audits?.length > 0; |
||||||
|
}; |
||||||
|
|
||||||
|
const resetSakilaPg = async (parallelId: string, isEmptyProject: boolean) => { |
||||||
|
const testsDir = __dirname.replace( |
||||||
|
'/src/lib/services/test/TestResetService', |
||||||
|
'/tests', |
||||||
|
); |
||||||
|
|
||||||
|
if (isEmptyProject) return; |
||||||
|
|
||||||
|
try { |
||||||
|
const sakilaKnex = knex(sakilaKnexConfig(parallelId)); |
||||||
|
const schemaFile = await fs.readFile( |
||||||
|
`${testsDir}/pg-sakila-db/01-postgres-sakila-schema.sql`, |
||||||
|
); |
||||||
|
await sakilaKnex.raw(schemaFile.toString()); |
||||||
|
|
||||||
|
const trx = await sakilaKnex.transaction(); |
||||||
|
const dataFile = await fs.readFile( |
||||||
|
`${testsDir}/pg-sakila-db/02-postgres-sakila-insert-data.sql`, |
||||||
|
); |
||||||
|
await trx.raw(dataFile.toString()); |
||||||
|
await trx.commit(); |
||||||
|
|
||||||
|
await sakilaKnex.destroy(); |
||||||
|
} catch (e) { |
||||||
|
console.error(`Error resetting pg sakila db: Worker ${parallelId}`); |
||||||
|
throw Error(`Error resetting pg sakila db: Worker ${parallelId}`); |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
const sakilaKnexConfig = (parallelId: string) => ({ |
||||||
|
...config, |
||||||
|
connection: { |
||||||
|
...config.connection, |
||||||
|
database: `sakila_${parallelId}`, |
||||||
|
}, |
||||||
|
}); |
||||||
|
|
||||||
|
const resetPgSakilaProject = async ({ |
||||||
|
token, |
||||||
|
title, |
||||||
|
parallelId, |
||||||
|
oldProject, |
||||||
|
isEmptyProject, |
||||||
|
}: { |
||||||
|
token: string; |
||||||
|
title: string; |
||||||
|
parallelId: string; |
||||||
|
oldProject?: Project | undefined; |
||||||
|
isEmptyProject: boolean; |
||||||
|
}) => { |
||||||
|
const pgknex = knex(config); |
||||||
|
|
||||||
|
try { |
||||||
|
await pgknex.raw(`CREATE DATABASE sakila_${parallelId}`); |
||||||
|
} catch (e) {} |
||||||
|
|
||||||
|
if (isEmptyProject || (await isSakilaPgToBeReset(parallelId, oldProject))) { |
||||||
|
await pgknex.raw(`DROP DATABASE IF EXISTS sakila_${parallelId}`); |
||||||
|
await pgknex.raw(`CREATE DATABASE sakila_${parallelId}`); |
||||||
|
await pgknex.destroy(); |
||||||
|
|
||||||
|
await resetSakilaPg(parallelId, isEmptyProject); |
||||||
|
} |
||||||
|
|
||||||
|
const response = await axios.post( |
||||||
|
'http://localhost:8080/api/v1/db/meta/projects/', |
||||||
|
extMysqlProject(title, parallelId), |
||||||
|
{ |
||||||
|
headers: { |
||||||
|
'xc-auth': token, |
||||||
|
}, |
||||||
|
}, |
||||||
|
); |
||||||
|
if (response.status !== 200) { |
||||||
|
console.error('Error creating project', response.data); |
||||||
|
throw new Error('Error creating project', response.data); |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
const pgSakilaTables = [ |
||||||
|
'country', |
||||||
|
'city', |
||||||
|
'actor', |
||||||
|
'film_actor', |
||||||
|
'category', |
||||||
|
'film_category', |
||||||
|
'language', |
||||||
|
'film', |
||||||
|
'payment_p2007_01', |
||||||
|
'payment_p2007_02', |
||||||
|
'payment_p2007_03', |
||||||
|
'payment_p2007_04', |
||||||
|
'payment_p2007_05', |
||||||
|
'payment_p2007_06', |
||||||
|
'payment', |
||||||
|
'customer', |
||||||
|
'inventory', |
||||||
|
'rental', |
||||||
|
'address', |
||||||
|
'staff', |
||||||
|
'store', |
||||||
|
]; |
||||||
|
|
||||||
|
const pgSakilaSqlViews = [ |
||||||
|
'actor_info', |
||||||
|
'customer_list', |
||||||
|
'film_list', |
||||||
|
'nicer_but_slower_film_list', |
||||||
|
'sales_by_film_category', |
||||||
|
'sales_by_store', |
||||||
|
'staff_list', |
||||||
|
]; |
||||||
|
|
||||||
|
export default resetPgSakilaProject; |
@ -1,7 +1,20 @@ |
|||||||
import { Controller } from '@nestjs/common'; |
import { Controller, Post, Req } from '@nestjs/common'; |
||||||
import { TestService } from './test.service'; |
import { TestService } from './test.service'; |
||||||
|
import { TestResetService } from './TestResetService'; |
||||||
|
|
||||||
@Controller('test') |
@Controller('test') |
||||||
export class TestController { |
export class TestController { |
||||||
constructor(private readonly testService: TestService) {} |
constructor(private readonly testService: TestService) {} |
||||||
|
|
||||||
|
@Post('/api/v1/meta/test/reset') |
||||||
|
async reset(@Req() req) { |
||||||
|
const service = new TestResetService({ |
||||||
|
parallelId: req.body.parallelId, |
||||||
|
dbType: req.body.dbType, |
||||||
|
isEmptyProject: req.body.isEmptyProject, |
||||||
|
workerId: req.body.workerId, |
||||||
|
}); |
||||||
|
|
||||||
|
return await service.process(); |
||||||
|
} |
||||||
} |
} |
||||||
|
Loading…
Reference in new issue