budibase/packages/server/scripts/load/create-many-relationships.js

197 lines
4.3 KiB
JavaScript
Raw Normal View History

2023-12-19 16:59:23 +01:00
#!/bin/node
2023-12-22 11:46:49 +01:00
const {
createApp,
getTable,
createRow,
createTable,
getApp,
2023-12-22 12:18:24 +01:00
getRows,
2023-12-22 11:46:49 +01:00
} = require("./utils")
2023-12-19 16:59:23 +01:00
2023-12-20 11:51:35 +01:00
const Chance = require("chance")
2023-12-22 10:05:49 +01:00
2023-12-20 11:51:35 +01:00
const generator = new Chance()
2023-12-20 13:04:16 +01:00
const STUDENT_COUNT = 500
2023-12-20 12:18:29 +01:00
const SUBJECT_COUNT = 10
2023-12-19 16:59:23 +01:00
2023-12-22 11:46:49 +01:00
let { apiKey, appId } = require("yargs")
2023-12-22 11:36:29 +01:00
.demandOption(["apiKey"])
.option("appId").argv
2023-12-19 16:59:23 +01:00
2023-12-20 13:04:16 +01:00
const start = Date.now()
2023-12-22 11:46:49 +01:00
async function batchCreate(apiKey, appId, table, items, batchSize = 100) {
2023-12-21 17:39:14 +01:00
let i = 0
2023-12-21 18:29:57 +01:00
let errors = 0
2023-12-21 19:06:26 +01:00
2023-12-21 17:48:39 +01:00
async function createSingleRow(item) {
try {
const row = await createRow(apiKey, appId, table, item)
console.log(
`${table.name} - ${++i} of ${items.length} created (${
(Date.now() - start) / 1000
}s)`
)
return row
} catch {
2023-12-21 18:29:57 +01:00
errors++
}
2023-12-21 17:39:14 +01:00
}
const rows = []
2023-12-21 19:06:26 +01:00
const maxConcurrency = Math.min(batchSize, items.length)
const inFlight = {}
for (let itemIndex = 0; itemIndex < items.length; itemIndex++) {
const item = items[itemIndex]
2023-12-22 11:52:48 +01:00
const promise = createSingleRow(item)
.then(result => {
rows.push(result)
})
.finally(() => {
delete inFlight[itemIndex]
})
2023-12-21 19:06:26 +01:00
inFlight[itemIndex] = promise
if (Object.keys(inFlight).length >= maxConcurrency) {
await Promise.race(Object.values(inFlight))
}
2023-12-21 18:29:57 +01:00
}
2023-12-21 19:06:26 +01:00
await Promise.all(Object.values(inFlight))
2023-12-22 10:05:49 +01:00
if (errors) {
console.error(
`${table.name} - ${errors} creation errored (${
(Date.now() - start) / 1000
}s)`
)
}
2023-12-21 17:39:14 +01:00
return rows
}
2023-12-22 11:46:49 +01:00
const useExistingApp = !!appId
2023-12-20 12:30:35 +01:00
2023-12-22 11:46:49 +01:00
async function upsertTable(appId, tableName, tableData) {
if (useExistingApp) {
return await getTable(apiKey, appId, tableName)
2023-12-20 12:18:29 +01:00
}
2023-12-22 11:46:49 +01:00
const table = await createTable(apiKey, appId, {
...tableData,
name: tableName,
})
return table
}
async function run() {
if (!appId) {
const app = appId ? await getApp(apiKey, appId) : await createApp(apiKey)
appId = app._id
2024-01-02 12:31:08 +01:00
console.log(`App created. Url: http://localhost:10000/builder/app/${appId}`)
} else {
console.log(
`App retrieved. Url: http://localhost:10000/builder/app/${appId}`
)
}
2023-12-22 11:46:49 +01:00
const studentsTable = await getTable(apiKey, appId, "Students")
2023-12-19 16:59:23 +01:00
2023-12-20 12:52:25 +01:00
let studentNumber = studentsTable.schema["Auto ID"].lastID
2023-12-21 17:39:14 +01:00
const students = await batchCreate(
apiKey,
2023-12-22 11:46:49 +01:00
appId,
2023-12-21 17:39:14 +01:00
studentsTable,
2023-12-21 17:52:04 +01:00
Array.from({ length: STUDENT_COUNT }).map(() => ({
2023-12-21 17:39:14 +01:00
"Student Number": (++studentNumber).toString(),
"First Name": generator.first(),
"Last Name": generator.last(),
Gender: generator.pickone(["M", "F"]),
Grade: generator.pickone(["8", "9", "10", "11"]),
"Tardiness (Days)": generator.integer({ min: 1, max: 100 }),
"Home Number": generator.phone(),
"Attendance_(%)": generator.integer({ min: 0, max: 100 }),
2023-12-21 17:48:39 +01:00
}))
2023-12-21 17:24:48 +01:00
)
2023-12-20 15:02:21 +01:00
2023-12-22 11:46:49 +01:00
const subjectTable = await upsertTable(appId, "Subjects", {
2023-12-19 16:59:23 +01:00
schema: {
2023-12-20 11:51:35 +01:00
Name: {
2023-12-19 16:59:23 +01:00
name: "Name",
type: "string",
},
},
2023-12-20 12:52:25 +01:00
primaryDisplay: "Name",
2023-12-19 16:59:23 +01:00
})
2023-12-20 11:51:35 +01:00
2023-12-22 12:18:24 +01:00
const subjects = useExistingApp
? await getRows(apiKey, appId, subjectTable._id)
: await batchCreate(
apiKey,
appId,
subjectTable,
Array.from({ length: SUBJECT_COUNT }).map(() => ({
Name: generator.profession(),
}))
)
2023-12-20 15:02:21 +01:00
2023-12-22 11:46:49 +01:00
const gradesTable = await upsertTable(appId, "Grades", {
2023-12-20 12:52:25 +01:00
schema: {
Score: {
name: "Score",
type: "number",
},
Student: {
name: "Student",
tableId: studentsTable._id,
constraints: {
presence: true,
type: "array",
},
fieldName: "Grades",
relationshipType: "one-to-many",
type: "link",
},
Subject: {
name: "Subject",
tableId: subjectTable._id,
constraints: {
presence: true,
type: "array",
},
fieldName: "Grades",
relationshipType: "one-to-many",
type: "link",
},
},
})
2023-12-21 17:48:39 +01:00
await batchCreate(
apiKey,
2023-12-22 11:46:49 +01:00
appId,
2023-12-21 17:48:39 +01:00
gradesTable,
students.flatMap(student =>
subjects.map(subject => ({
2023-12-20 12:52:25 +01:00
Score: generator.integer({ min: 0, max: 100 }),
Student: [student],
Subject: [subject],
2023-12-21 17:48:39 +01:00
}))
)
)
2023-12-21 18:02:44 +01:00
console.log(
2023-12-22 11:46:49 +01:00
`Access the app here: http://localhost:10000/builder/app/${appId}`
2023-12-21 18:02:44 +01:00
)
2023-12-19 16:59:23 +01:00
}
2023-12-20 13:04:16 +01:00
run()
.then(() => {
2023-12-20 15:02:21 +01:00
console.log(`Done in ${(Date.now() - start) / 1000} seconds`)
2023-12-20 13:04:16 +01:00
})
.catch(err => {
console.error(err)
})