Skip to content

Commit

Permalink
Speed up database schema sync for watch mode
Browse files Browse the repository at this point in the history
  • Loading branch information
shanejearley committed Mar 15, 2023
1 parent 3e290ee commit ba2ef94
Show file tree
Hide file tree
Showing 7 changed files with 60 additions and 33 deletions.
4 changes: 2 additions & 2 deletions common/data/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
"build": "echo '@casimir/data build not specified. Disregard this warning and any listed errors above if @casimir/types is not needed for the current project build.' && exit 0",
"clean": "ts-node --transpile-only scripts/clean.ts",
"configure:python": "poetry install && poetry run ipython kernel install --user --name=casimir-data",
"dev": "ts-node --transpile-only scripts/postgres.ts --clean \"$npm_config_clean\" --tables \"$npm_config_tables\"",
"watch": "ts-node-dev --watch src --respawn --transpile-only scripts/postgres.ts --clean \"$npm_config_clean\" --tables \"$npm_config_tables\"",
"dev": "ts-node --transpile-only scripts/postgres.ts --tables \"$npm_config_tables\"",
"watch": "ts-node-dev --watch src --respawn --transpile-only scripts/postgres.ts --tables \"$npm_config_tables\"",
"test": "echo \"Error: no test specified\" && exit 1"
},
"dependencies": {
Expand Down
22 changes: 17 additions & 5 deletions common/data/scripts/clean.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,25 @@
import { run } from '@casimir/helpers'

/** Resource path from package caller */
const resources = './scripts'
const resourcePath = './scripts'

/**
* Clean local Docker Postgres environment, sql, and pgdata.
* Clean Docker containers, Postgres data, and SQL schema files.
*/
void async function () {
console.log(`Cleaning Docker services, Postgres data, and SQL schema files from ${resources}`)
await run('docker compose -p casimir-data down -v')
await run(`npx rimraf ${resources}/.out`)
console.log(`Cleaning up Docker containers, Postgres data, and SQL schema files from ${resourcePath}/.out`)

/** Stop postgres database */
const stackName = 'casimir-data'
const containerName = `${stackName}-postgres-1`
const container = await run(`docker ps -q --filter name=${containerName}`)
if (container) {
await run(`docker compose -p ${stackName} -f ${resourcePath}/docker-compose.yaml down`)
}

/** Clear output directory for pgdata and sql */
const outDir = `${resourcePath}/.out`
await run(`npx rimraf ${outDir}`)

console.log('🐘 Database resources cleaned')
}()
3 changes: 1 addition & 2 deletions common/data/scripts/docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
version: '3'

services:
pg:
postgres:
image: postgres:latest
restart: always
ports:
- 5432:5432
environment:
Expand Down
41 changes: 22 additions & 19 deletions common/data/scripts/postgres.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { run } from '@casimir/helpers'
import { JsonSchema, Schema, accountSchema, nonceSchema, userSchema } from '@casimir/data'

/** Resource path from package caller */
const resources = './scripts'
const resourcePath = './scripts'

/** All table schemas */
const tableSchemas = {
Expand All @@ -17,37 +17,40 @@ const tableSchemas = {
* Run a local postgres database with the given tables.
*
* Arguments:
* --clean: clean the database before starting (optional, i.e., --clean)
* --tables: tables to deploy (optional, i.e., --tables=accounts,users)
*/
void async function () {

/** Parse command line arguments */
const argv = minimist(process.argv.slice(2))

/** Default to clean services and data */
const clean = argv.clean !== 'false' || argv.clean !== false

/** Default to all tables */
const tables = argv.tables ? argv.tables.split(',') : ['accounts', 'nonces', 'users']

/** Write to sql file in ${resources}/sql */
if (clean) {
await run('npm run clean --workspace @casimir/data')
}
const sqlDir = `${resources}/.out/sql`
if (!fs.existsSync(sqlDir)) fs.mkdirSync(sqlDir, { recursive: true })
let sqlSchema = '-- Generated by @casimir/data/scripts/postgres.ts\n\n'
for (const table of tables) {
const tableSchema = tableSchemas[table] as JsonSchema
const schema = new Schema(tableSchema)
const postgresTable = schema.getPostgresTable()

console.log(`${schema.getTitle()} JSON schema parsed to SQL:`)
console.log(postgresTable)
console.log(`${schema.getTitle()} JSON schema parsed to SQL`)
sqlSchema += `DROP TABLE IF EXISTS ${table};\n`
sqlSchema += `${postgresTable}\n\n`
}

fs.writeFileSync(`${sqlDir}/${table}.sql`, postgresTable)
/** Write to sql file in ${resourcePath}/sql */
const sqlDir = `${resourcePath}/.out/sql`
if (!fs.existsSync(sqlDir)) fs.mkdirSync(sqlDir, { recursive: true })
fs.writeFileSync(`${sqlDir}/schema.sql`, sqlSchema)

/** Start or sync database with latest schema */
const stackName = 'casimir-data'
const containerName = `${stackName}-postgres-1`
const container = await run(`docker ps -q --filter name=${containerName}`)
if (!container) {
/** Start local database */
await run(`docker compose -p ${stackName} -f ${resourcePath}/docker-compose.yaml up -d`)
console.log('🐘 Database started')
} else {
await run(`docker exec ${containerName} psql -U postgres -d postgres -f /docker-entrypoint-initdb.d/schema.sql`)
console.log('🐘 Database synced')
}

/** Start local database */
await run(`docker compose -p casimir-data -f ${resources}/docker-compose.yaml up -d`)
}()
4 changes: 4 additions & 0 deletions common/data/src/schemas/account.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@
"type": "array",
"description": "The account transactions"
},
"updated_at": {
"type": "string",
"description": "The account last update date in ISO 8601 format"
},
"wallet": {
"type": "string",
"description": "The account wallet provider"
Expand Down
9 changes: 7 additions & 2 deletions common/helpers/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,10 +99,15 @@ export function kebabCase(string: string): string {
*/
export async function run(fullCommand: string) {
const [command, ...args] = fullCommand.split(' ')
const child = spawn(command, args, { stdio: 'inherit' })
const child = spawn(command, args)
let data = ''
return new Promise((resolve, reject) => {
child.on('error', reject)
child.on('exit', resolve)
child.stdout.on('data', chunk => {
process.stdout.write(chunk.toString())
data += chunk.toString()
})
child.on('exit', () => resolve(data))
})
}

Expand Down
10 changes: 7 additions & 3 deletions scripts/local/dev.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,14 @@ void async function () {
const { chains, services, tables } = apps[app as keyof typeof apps]

if (mock) {

if (clean) {
/** Clean postgres database */
await $`npm run clean --workspace @casimir/data`
}

/** Mock postgres database */
$`npm run watch --clean=${clean} --tables=${tables.join(',')} --workspace @casimir/data`
/** Comment out line above and uncomment line below when schemas are stable */
// $`npm run dev --clean=${clean} --tables=${tables.join(',')} --workspace @casimir/data`
$`npm run watch --tables=${tables.join(',')} --workspace @casimir/data`

/** Mock services */
let port = 4000
Expand Down

0 comments on commit ba2ef94

Please sign in to comment.