Merge pull request #3770 from strapi/chore/boostrap-async

make boostrap functions async only
This commit is contained in:
Alexandre BODIN 2019-08-12 17:33:27 +02:00 committed by GitHub
commit 5bd4b0d747
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 128 additions and 127 deletions

View File

@ -83,9 +83,36 @@ The `bootstrap` function is called at every server start. You can use it to add
Here are some use cases: Here are some use cases:
- Create an admin user if there isn't. - Create an admin user if there isn't one.
- Fill the database with some necessary data. - Fill the database with some necessary data.
- Check that the database is up-and-running. - Check that the database is up-and-running.
- Load some envrionments variables.
The bootstrap function can be synchronous or asynchronous
**Synchronous**
```js
module.exports = () => {
// some sync code
};
```
**Return a promise**
```js
module.exports = () => {
return new Promise(/* some code */);
};
```
**Be async**
```js
module.exports = async () => {
await someSetup();
};
```
### CRON tasks ### CRON tasks

View File

@ -8,6 +8,4 @@
* run jobs, or perform some special logic. * run jobs, or perform some special logic.
*/ */
module.exports = cb => { module.exports = () => {};
cb();
};

View File

@ -6,8 +6,8 @@
* *
* This gives you an opportunity to set up your data model, * This gives you an opportunity to set up your data model,
* run jobs, or perform some special logic. * run jobs, or perform some special logic.
*
* See more details here: https://strapi.io/documentation/3.0.0-beta.x/configurations/configurations.html#bootstrap
*/ */
module.exports = cb => { module.exports = () => {};
cb();
};

View File

@ -10,8 +10,8 @@ const {
/** /**
* Synchronize content manager schemas * Synchronize content manager schemas
*/ */
module.exports = cb => { module.exports = () => {
syncSchemas().then(() => cb(), err => cb(err)); return syncSchemas();
}; };
async function syncSchemas() { async function syncSchemas() {

View File

@ -2,11 +2,11 @@ const fs = require('fs');
const path = require('path'); const path = require('path');
const _ = require('lodash'); const _ = require('lodash');
module.exports = async cb => { module.exports = async () => {
// Check if the plugin users-permissions is installed because the documentation needs it // Check if the plugin users-permissions is installed because the documentation needs it
if (Object.keys(strapi.plugins).indexOf('users-permissions') === -1) { if (Object.keys(strapi.plugins).indexOf('users-permissions') === -1) {
throw new Error( throw new Error(
'In order to make the documentation plugin works the users-permissions one is required', 'In order to make the documentation plugin works the users-permissions one is required'
); );
} }
@ -26,16 +26,24 @@ module.exports = async cb => {
// Generate plugins' documentation // Generate plugins' documentation
const pluginsWithDocumentationNeeded = services.getPluginsWithDocumentationNeeded(); const pluginsWithDocumentationNeeded = services.getPluginsWithDocumentationNeeded();
pluginsWithDocumentationNeeded.forEach(plugin => { pluginsWithDocumentationNeeded.forEach(plugin => {
const isDocExisting = services.checkIfPluginDocumentationFolderExists(plugin); const isDocExisting = services.checkIfPluginDocumentationFolderExists(
plugin
);
if (!isDocExisting) { if (!isDocExisting) {
services.createDocumentationDirectory(services.getPluginDocumentationPath(plugin)); services.createDocumentationDirectory(
services.getPluginDocumentationPath(plugin)
);
// create the overrides directory // create the overrides directory
services.createDocumentationDirectory(services.getPluginOverrideDocumentationPath(plugin)); services.createDocumentationDirectory(
services.getPluginOverrideDocumentationPath(plugin)
);
services.createPluginDocumentationFile(plugin); services.createPluginDocumentationFile(plugin);
shouldUpdateFullDoc = true; shouldUpdateFullDoc = true;
} else { } else {
const needToUpdatePluginDoc = services.checkIfPluginDocNeedsUpdate(plugin); const needToUpdatePluginDoc = services.checkIfPluginDocNeedsUpdate(
plugin
);
if (needToUpdatePluginDoc) { if (needToUpdatePluginDoc) {
services.createPluginDocumentationFile(plugin); services.createPluginDocumentationFile(plugin);
@ -54,7 +62,9 @@ module.exports = async cb => {
// If the documentation directory doesn't exist create it // If the documentation directory doesn't exist create it
services.createDocumentationDirectory(services.getDocumentationPath(api)); services.createDocumentationDirectory(services.getDocumentationPath(api));
// Create the overrides directory // Create the overrides directory
services.createDocumentationDirectory(services.getDocumentationOverridesPath(api)); services.createDocumentationDirectory(
services.getDocumentationOverridesPath(api)
);
// Create the documentation files per version // Create the documentation files per version
services.createDocumentationFile(api); // Then create the {api}.json documentation file services.createDocumentationFile(api); // Then create the {api}.json documentation file
shouldUpdateFullDoc = true; shouldUpdateFullDoc = true;
@ -96,7 +106,10 @@ module.exports = async cb => {
.sort((a, b) => a - b) .sort((a, b) => a - b)
.join('.'); .join('.');
}; };
const oldDoc = require(path.resolve(documentationPath, 'full_documentation.json')); const oldDoc = require(path.resolve(
documentationPath,
'full_documentation.json'
));
const oldDocTags = getDocTagsToString(oldDoc); const oldDocTags = getDocTagsToString(oldDoc);
const currentDocTags = getDocTagsToString(fullDoc); const currentDocTags = getDocTagsToString(fullDoc);
@ -113,8 +126,7 @@ module.exports = async cb => {
fs.writeFileSync( fs.writeFileSync(
path.resolve(documentationPath, 'full_documentation.json'), path.resolve(documentationPath, 'full_documentation.json'),
JSON.stringify(fullDoc, null, 2), JSON.stringify(fullDoc, null, 2),
'utf8', 'utf8'
); );
} }
cb();
}; };

View File

@ -9,7 +9,7 @@
*/ */
const _ = require('lodash'); const _ = require('lodash');
module.exports = async cb => { module.exports = async () => {
// set plugin store // set plugin store
const pluginStore = strapi.store({ const pluginStore = strapi.store({
environment: strapi.config.environment, environment: strapi.config.environment,
@ -27,7 +27,6 @@ module.exports = async cb => {
strapi.plugins.email.config.providers.push(require(installedProvider)); strapi.plugins.email.config.providers.push(require(installedProvider));
} }
try {
// if provider config does not exist set one by default // if provider config does not exist set one by default
const config = await pluginStore.get({ key: 'provider' }); const config = await pluginStore.get({ key: 'provider' });
@ -42,10 +41,4 @@ module.exports = async cb => {
await pluginStore.set({ key: 'provider', value }); await pluginStore.set({ key: 'provider', value });
} }
} catch (err) {
strapi.log.error(err);
strapi.stop();
}
cb();
}; };

View File

@ -8,20 +8,18 @@
* run jobs, or perform some special logic. * run jobs, or perform some special logic.
*/ */
module.exports = async cb => { module.exports = async () => {
const pluginStore = strapi.store({ const pluginStore = strapi.store({
environment: '', environment: '',
type: 'core' type: 'core',
}); });
if (!await pluginStore.get({key: 'application'})) { if (!(await pluginStore.get({ key: 'application' }))) {
const value = { const value = {
name: 'Default Application', name: 'Default Application',
description: 'This API is going to be awesome!' description: 'This API is going to be awesome!',
}; };
await pluginStore.set({ key: 'application', value }); await pluginStore.set({ key: 'application', value });
} }
cb();
}; };

View File

@ -9,7 +9,7 @@
*/ */
const _ = require('lodash'); const _ = require('lodash');
module.exports = async cb => { module.exports = async () => {
// set plugin store // set plugin store
const pluginStore = strapi.store({ const pluginStore = strapi.store({
environment: strapi.config.environment, environment: strapi.config.environment,
@ -27,7 +27,6 @@ module.exports = async cb => {
strapi.plugins.upload.config.providers.push(require(installedProvider)); strapi.plugins.upload.config.providers.push(require(installedProvider));
} }
try {
// if provider config does not exist set one by default // if provider config does not exist set one by default
const config = await pluginStore.get({ key: 'provider' }); const config = await pluginStore.get({ key: 'provider' });
@ -44,9 +43,4 @@ module.exports = async cb => {
await pluginStore.set({ key: 'provider', value }); await pluginStore.set({ key: 'provider', value });
} }
} catch (err) {
strapi.log.error(err);
strapi.stop();
}
cb();
}; };

View File

@ -10,12 +10,16 @@
const _ = require('lodash'); const _ = require('lodash');
const uuid = require('uuid/v4'); const uuid = require('uuid/v4');
module.exports = async cb => { module.exports = async () => {
if (!_.get(strapi.plugins['users-permissions'], 'config.jwtSecret')) { if (!_.get(strapi.plugins['users-permissions'], 'config.jwtSecret')) {
const jwtSecret = uuid(); const jwtSecret = uuid();
_.set(strapi.plugins['users-permissions'], 'config.jwtSecret', jwtSecret); _.set(strapi.plugins['users-permissions'], 'config.jwtSecret', jwtSecret);
await strapi.fs.writePluginFile('users-permissions', 'config/jwt.json', JSON.stringify({ jwtSecret }, null, 2)); await strapi.fs.writePluginFile(
'users-permissions',
'config/jwt.json',
JSON.stringify({ jwtSecret }, null, 2)
);
} }
const pluginStore = strapi.store({ const pluginStore = strapi.store({
@ -144,14 +148,14 @@ module.exports = async cb => {
unique_email: true, unique_email: true,
allow_register: true, allow_register: true,
email_confirmation: false, email_confirmation: false,
email_confirmation_redirection: `http://${ email_confirmation_redirection: `http://${strapi.config.currentEnvironment.server.host}:${strapi.config.currentEnvironment.server.port}/admin`,
strapi.config.currentEnvironment.server.host
}:${strapi.config.currentEnvironment.server.port}/admin`,
default_role: 'authenticated', default_role: 'authenticated',
}; };
await pluginStore.set({ key: 'advanced', value }); await pluginStore.set({ key: 'advanced', value });
} }
strapi.plugins['users-permissions'].services.userspermissions.initialize(cb); return strapi.plugins[
'users-permissions'
].services.userspermissions.initialize();
}; };

View File

@ -462,18 +462,14 @@ module.exports = {
return Promise.resolve(); return Promise.resolve();
}, },
async initialize(cb) { async initialize() {
const roleCount = await strapi.query('role', 'users-permissions').count(); const roleCount = await strapi.query('role', 'users-permissions').count();
// It has already been initialized. // It has already been initialized.
if (roleCount > 0) { if (roleCount > 0) {
try {
await this.updatePermissions(); await this.updatePermissions();
await this.removeDuplicate(); await this.removeDuplicate();
return cb(); return;
} catch (err) {
return cb(err);
}
} }
// Create two first default roles. // Create two first default roles.
@ -490,7 +486,7 @@ module.exports = {
}), }),
]); ]);
this.updatePermissions().then(() => cb(), err => cb(err)); return this.updatePermissions();
}, },
async updateRole(roleID, body) { async updateRole(roleID, body) {

View File

@ -366,60 +366,39 @@ class Strapi extends EventEmitter {
} }
async runBootstrapFunctions() { async runBootstrapFunctions() {
const execBootstrap = fn => {
if (!fn) return Promise.resolve();
return new Promise((resolve, reject) => {
const timeoutMs = this.config.bootstrapTimeout || 3500; const timeoutMs = this.config.bootstrapTimeout || 3500;
const timer = setTimeout(() => { const warnOnTimeout = () =>
setTimeout(() => {
this.log.warn( this.log.warn(
`The bootstrap function is taking unusually long to execute (${timeoutMs} miliseconds).` `The bootstrap function is taking unusually long to execute (${timeoutMs} miliseconds).`
); );
this.log.warn('Make sure you call it?'); this.log.warn('Make sure you call it?');
}, timeoutMs); }, timeoutMs);
let ranBootstrapFn = false; async function execBootstrap(fn) {
if (!fn) return;
const timer = warnOnTimeout();
try { try {
fn(err => { await fn();
if (ranBootstrapFn) { } finally {
this.log.error(
'You called the callback in `strapi.config.boostrap` more than once!'
);
return reject();
}
ranBootstrapFn = true;
clearTimeout(timer); clearTimeout(timer);
if (err instanceof Error) {
return reject(err);
} }
return resolve(err); }
const pluginBoostraps = Object.keys(this.plugins).map(plugin => {
return execBootstrap(
_.get(this.plugins[plugin], 'config.functions.bootstrap')
).catch(err => {
strapi.log.error(`Bootstrap function in plugin "${plugin}" failed`);
strapi.log.error(err);
strapi.stop();
}); });
} catch (e) {
if (ranBootstrapFn) {
this.log.error(
'The bootstrap function threw an error after its callback was called.'
);
return reject(e);
}
ranBootstrapFn = true;
clearTimeout(timer);
return resolve(e);
}
}); });
};
return Promise.all( await Promise.all(pluginBoostraps);
Object.values(this.plugins).map(plugin =>
execBootstrap(_.get(plugin, 'config.functions.bootstrap')) return execBootstrap(_.get(this.config, ['functions', 'bootstrap']));
)
).then(() => execBootstrap(this.config.functions.bootstrap));
} }
async freeze() { async freeze() {