Files
speckle-server/packages/server/modules/cli/commands/db/seed/users.js
T
Iain Sproat 96bed71022 fix(logging): Improves error logging and pretty-prints logs during dev & test (#1255)
* Improves error logging
- use pino error logger correctly by passing in error as first argument

* monitor deployment: Filter logging at INFO level and above
* Use structured logging to create parameters for monitoring results
* Add structured logging to obj fileimport service
* Fileimport service, fix and improve logging
    - use child logger with additional context where possible
    - select appropriate logging level
- fix duplicated context in log statement
* REST endpoints, add context to structured logging and remove same context from message
* Webhook service provides context to bound logger to properly use structured logging
    - Pass bound logger containing context to `makeNetworkRequest`
    - do not log url, as it may contain a secret (like Discord's webhook urls), instead log the webhook Id
     - log error message when network call fails
* upload: make better use of structured logging when recording data
* pino-pretty when in dev or test mode
    - pino-pretty configured to send to stderr
* LOG_PRETTY env var
* Silence structured logging during testing
     - can not rely on determining the port number by reading from stdout/stderr
     - instead we determine which port is free, then create our server on that port
     - we then poll that port until the server is ready before commencing tests
* Allow puppeteer to install chromium
* Do not need to install chromium separately
2022-12-13 09:18:28 +00:00

127 lines
3.5 KiB
JavaScript

const { logger } = require('@/logging/logging')
const { Users, ServerAcl } = require('@/modules/core/dbSchema')
const { Roles } = require('@/modules/core/helpers/mainConstants')
const { faker } = require('@faker-js/faker')
const { range } = require('lodash')
const RETRY_COUNT = 3
const UNIQUE_MAX_TIME = 500
function createFakeUser() {
return {
id: faker.unique(faker.random.alphaNumeric, [10], { maxTime: UNIQUE_MAX_TIME }),
name: faker.name.firstName() + ' ' + faker.name.lastName(),
bio: faker.lorem.lines(5),
company: faker.company.companyName(),
email: faker.unique(
faker.internet.email,
[
faker.unique(faker.random.alphaNumeric, [10]),
faker.unique(faker.random.alphaNumeric, [10])
],
{ maxTime: UNIQUE_MAX_TIME }
),
verified: faker.datatype.boolean(),
avatar: faker.random.alphaNumeric(255),
ip: faker.internet.ipv4(),
passwordDigest: faker.random.alphaNumeric(255)
}
}
function generateUsers(count) {
const users = []
for (let i = 0; i < count; i++) {
users.push(createFakeUser())
}
return users
}
function insertUsers(users) {
return Users.knex().returning(Users.col.id).insert(users)
}
async function* batchedOperationGenerator({
batchInsertGenerator,
itemCount,
batchSize,
retryCount = 3
}) {
logger.info('Starting batched operation...')
let currentItemCount = 0
const batchCount = Math.ceil(itemCount / batchSize)
for (let i = 0; i < batchCount; i++) {
logger.info(`Processing batch ${i + 1} out of ${batchCount}...`)
const newItemCount = Math.min(currentItemCount + batchSize, itemCount)
const insertCount = newItemCount - currentItemCount
if (insertCount <= 0) return
// Invoke batch generate & insert
const execute = () =>
Promise.resolve(batchInsertGenerator(insertCount, currentItemCount))
let batchPromise = execute().then((res) => {
logger.info(`...processed batch ${i + 1} out of ${batchCount}`)
return res
})
// Attach retries
range(retryCount).forEach(() => {
batchPromise = batchPromise.catch(() => {
return execute()
})
})
batchPromise = batchPromise.catch((e) => {
logger.error(e, 'Operation failed all retries')
})
currentItemCount = newItemCount
const results = await batchPromise
yield results
}
}
/** @type {import('yargs').CommandModule} */
const command = {
command: 'users <count> [batchsize]',
describe: 'Fill the `users` table with a ton of fake users',
builder(yargs) {
return yargs
.positional('count', {
describe: 'User count',
type: 'number'
})
.positional('batchsize', {
describe: 'Max amount of inserts to process at once',
type: 'number',
default: '500'
})
},
async handler(argv) {
const count = argv.count
const batchSize = argv.batchsize
const userBatchedInsertionGenerator = batchedOperationGenerator({
batchInsertGenerator: (insertCount) => {
const users = generateUsers(insertCount)
return insertUsers(users).then((users) => users.map((u) => u.id))
},
itemCount: count,
batchSize,
retryCount: RETRY_COUNT
})
for await (const insertedIds of userBatchedInsertionGenerator) {
logger.info('Inserting ACL entries for batch...')
const entries = insertedIds.map((id) => ({
role: Roles.Server.User,
userId: id
}))
await ServerAcl.knex().insert(entries)
logger.info('...inserted ACL')
}
}
}
module.exports = command