From 47e0652b4a98916d4a1d012fbec61afd73a30565 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Thu, 16 Nov 2017 18:40:50 +0100 Subject: [PATCH 1/1] Optimize account creation --- scripts/parse-log.ts | 2 +- server/controllers/api/users.ts | 22 +++++++++++++++++----- server/initializers/installer.ts | 6 +++--- server/lib/user.ts | 22 ++++++++++++++-------- server/lib/video-channel.ts | 4 +--- server/models/account/account.ts | 2 +- server/tests/api/config.ts | 10 ++++++---- server/tests/utils/index.ts | 2 +- 8 files changed, 44 insertions(+), 26 deletions(-) diff --git a/scripts/parse-log.ts b/scripts/parse-log.ts index 81a22f7a0..8aac6fbda 100755 --- a/scripts/parse-log.ts +++ b/scripts/parse-log.ts @@ -38,5 +38,5 @@ const rl = createInterface({ rl.on('line', line => { const log = JSON.parse(line) - logLevels[log.level](log.message) + logLevels[log.level](log.message, log.stack) }) diff --git a/server/controllers/api/users.ts b/server/controllers/api/users.ts index 41ffb64cb..ac7c87517 100644 --- a/server/controllers/api/users.ts +++ b/server/controllers/api/users.ts @@ -70,7 +70,7 @@ usersRouter.post('/', usersRouter.post('/register', ensureUserRegistrationAllowed, usersRegisterValidator, - asyncMiddleware(registerUser) + asyncMiddleware(registerUserRetryWrapper) ) usersRouter.put('/me', @@ -113,7 +113,7 @@ async function getUserVideos (req: express.Request, res: express.Response, next: async function createUserRetryWrapper (req: express.Request, res: express.Response, next: express.NextFunction) { const options = { - arguments: [ req, res ], + arguments: [ req ], errorMessage: 'Cannot insert the user with many retries.' } @@ -123,7 +123,7 @@ async function createUserRetryWrapper (req: express.Request, res: express.Respon return res.type('json').status(204).end() } -async function createUser (req: express.Request, res: express.Response, next: express.NextFunction) { +async function createUser (req: express.Request) { const body: UserCreate = req.body const user = db.User.build({ username: body.username, @@ -139,7 +139,18 @@ async function createUser (req: express.Request, res: express.Response, next: ex logger.info('User %s with its channel and account created.', body.username) } -async function registerUser (req: express.Request, res: express.Response, next: express.NextFunction) { +async function registerUserRetryWrapper (req: express.Request, res: express.Response, next: express.NextFunction) { + const options = { + arguments: [ req ], + errorMessage: 'Cannot insert the user with many retries.' + } + + await retryTransactionWrapper(registerUser, options) + + return res.type('json').status(204).end() +} + +async function registerUser (req: express.Request) { const body: UserCreate = req.body const user = db.User.build({ @@ -152,7 +163,8 @@ async function registerUser (req: express.Request, res: express.Response, next: }) await createUserAccountAndChannel(user) - return res.type('json').status(204).end() + + logger.info('User %s with its channel and account registered.', body.username) } async function getUserInformation (req: express.Request, res: express.Response, next: express.NextFunction) { diff --git a/server/initializers/installer.ts b/server/initializers/installer.ts index 3f4c4dfbb..865495722 100644 --- a/server/initializers/installer.ts +++ b/server/initializers/installer.ts @@ -2,10 +2,9 @@ import * as passwordGenerator from 'password-generator' import { UserRole } from '../../shared' import { logger, mkdirpPromise, rimrafPromise } from '../helpers' import { createUserAccountAndChannel } from '../lib' -import { createLocalAccount } from '../lib/user' +import { createLocalAccountWithoutKeys } from '../lib/user' import { applicationExist, clientsExist, usersExist } from './checker' import { CACHE, CONFIG, LAST_MIGRATION_VERSION, SERVER_ACCOUNT_NAME } from './constants' - import { database as db } from './database' async function installApplication () { @@ -136,5 +135,6 @@ async function createApplicationIfNotExist () { const applicationInstance = await db.Application.create({ migrationVersion: LAST_MIGRATION_VERSION }) logger.info('Creating application account.') - return createLocalAccount(SERVER_ACCOUNT_NAME, null, applicationInstance.id, undefined) + + return createLocalAccountWithoutKeys(SERVER_ACCOUNT_NAME, null, applicationInstance.id, undefined) } diff --git a/server/lib/user.ts b/server/lib/user.ts index 9884e566f..2d7b36b4f 100644 --- a/server/lib/user.ts +++ b/server/lib/user.ts @@ -5,16 +5,17 @@ import { database as db } from '../initializers' import { CONFIG } from '../initializers/constants' import { UserInstance } from '../models' import { createVideoChannel } from './video-channel' +import { logger } from '../helpers/logger' async function createUserAccountAndChannel (user: UserInstance, validateUser = true) { - const res = await db.sequelize.transaction(async t => { + const { account, videoChannel } = await db.sequelize.transaction(async t => { const userOptions = { transaction: t, validate: validateUser } const userCreated = await user.save(userOptions) - const accountCreated = await createLocalAccount(user.username, user.id, null, t) + const accountCreated = await createLocalAccountWithoutKeys(user.username, user.id, null, t) const videoChannelName = `Default ${userCreated.username} channel` const videoChannelInfo = { @@ -25,18 +26,23 @@ async function createUserAccountAndChannel (user: UserInstance, validateUser = t return { account: accountCreated, videoChannel } }) - return res + // Set account keys, this could be long so process after the account creation and do not block the client + const { publicKey, privateKey } = await createPrivateAndPublicKeys() + account.set('publicKey', publicKey) + account.set('privateKey', privateKey) + account.save().catch(err => logger.error('Cannot set public/private keys of local account %d.', account.id, err)) + + return { account, videoChannel } } -async function createLocalAccount (name: string, userId: number, applicationId: number, t: Sequelize.Transaction) { - const { publicKey, privateKey } = await createPrivateAndPublicKeys() +async function createLocalAccountWithoutKeys (name: string, userId: number, applicationId: number, t: Sequelize.Transaction) { const url = getActivityPubUrl('account', name) const accountInstance = db.Account.build({ name, url, - publicKey, - privateKey, + publicKey: null, + privateKey: null, followersCount: 0, followingCount: 0, inboxUrl: url + '/inbox', @@ -56,5 +62,5 @@ async function createLocalAccount (name: string, userId: number, applicationId: export { createUserAccountAndChannel, - createLocalAccount + createLocalAccountWithoutKeys } diff --git a/server/lib/video-channel.ts b/server/lib/video-channel.ts index e69ec062f..6f9ae2d95 100644 --- a/server/lib/video-channel.ts +++ b/server/lib/video-channel.ts @@ -25,9 +25,7 @@ async function createVideoChannel (videoChannelInfo: VideoChannelCreate, account // Do not forget to add Account information to the created video channel videoChannelCreated.Account = account - await sendCreateVideoChannel(videoChannelCreated, t) - await shareVideoChannelByServer(videoChannelCreated, t) - + // No need to seed this empty video channel to followers return videoChannelCreated } diff --git a/server/models/account/account.ts b/server/models/account/account.ts index 84461a2eb..c370e1709 100644 --- a/server/models/account/account.ts +++ b/server/models/account/account.ts @@ -75,7 +75,7 @@ export default function defineAccount (sequelize: Sequelize.Sequelize, DataTypes }, publicKey: { type: DataTypes.STRING(CONSTRAINTS_FIELDS.ACCOUNTS.PUBLIC_KEY.max), - allowNull: false, + allowNull: true, validate: { publicKeyValid: value => { const res = isAccountPublicKeyValid(value) diff --git a/server/tests/api/config.ts b/server/tests/api/config.ts index 3dda3b4d7..72a9e5679 100644 --- a/server/tests/api/config.ts +++ b/server/tests/api/config.ts @@ -15,7 +15,7 @@ describe('Test config', function () { let server = null before(async function () { - this.timeout(120000) + this.timeout(10000) await flushTests() server = await runServer(1) @@ -29,9 +29,11 @@ describe('Test config', function () { }) it('Should have a correct config on a server with registration enabled and a users limit', async function () { - await registerUser(server.url, 'user1', 'super password') - await registerUser(server.url, 'user2', 'super password') - await registerUser(server.url, 'user3', 'super password') + await Promise.all([ + registerUser(server.url, 'user1', 'super password'), + registerUser(server.url, 'user2', 'super password'), + registerUser(server.url, 'user3', 'super password') + ]) const res = await getConfig(server.url) const data = res.body diff --git a/server/tests/utils/index.ts b/server/tests/utils/index.ts index 4325e4c94..fe6d3b041 100644 --- a/server/tests/utils/index.ts +++ b/server/tests/utils/index.ts @@ -3,7 +3,7 @@ export * from './clients' export * from './config' export * from './login' export * from './miscs' -export * from './pods' +export * from './follows' export * from './request-schedulers' export * from './requests' export * from './servers' -- 2.41.0