From afc6df1d4d7ad0afb6f38c998f058b22b486bee6 Mon Sep 17 00:00:00 2001 From: Nate Stuyvesant Date: Wed, 1 Feb 2017 00:04:15 -0500 Subject: [PATCH 1/3] fix app: prevent excess sync()s when seeding db Change app.js to seed database in promise chain before startServer, move seeding conditional to seed.js and wrap in function. --- templates/app/server/app.js | 7 +- templates/app/server/config/seed(models).js | 125 ++++++++++---------- 2 files changed, 66 insertions(+), 66 deletions(-) diff --git a/templates/app/server/app.js b/templates/app/server/app.js index 7dbbcba9f..ba25f0b5d 100644 --- a/templates/app/server/app.js +++ b/templates/app/server/app.js @@ -10,6 +10,7 @@ mongoose.Promise = require('bluebird');<% } %><% if (filters.sequelize) { %> import sqldb from './sqldb';<% } %> import config from './config/environment'; import http from 'http'; +<% if(filters.models) { %>import seedDatabaseIfNeeded from './config/seed';<% } %> <% if (filters.mongoose) { %> // Connect to MongoDB mongoose.connect(config.mongo.uri, config.mongo.options); @@ -17,11 +18,6 @@ mongoose.connection.on('error', function(err) { console.error('MongoDB connection error: ' + err); process.exit(-1); // eslint-disable-line no-process-exit }); -<% } %><% if(filters.models) { %> -// Populate databases with sample data -if(config.seedDB) { - require('./config/seed'); -} <% } %> // Setup server var app = express(); @@ -43,6 +39,7 @@ function startServer() { <% if(filters.sequelize) { %> sqldb.sequelize.sync() .then(startServer) +<% if(filters.models) { %> .then(seedDatabaseIfNeeded)<% } %> .catch(function(err) { console.log('Server failed to start due to error: %s', err); }); diff --git a/templates/app/server/config/seed(models).js b/templates/app/server/config/seed(models).js index 627aa5a36..cd4f07d33 100644 --- a/templates/app/server/config/seed(models).js +++ b/templates/app/server/config/seed(models).js @@ -6,67 +6,70 @@ 'use strict';<% if (filters.mongooseModels) { %> import Thing from '../api/thing/thing.model';<% if (filters.auth) { %> import User from '../api/user/user.model';<% } %><% } %><% if (filters.sequelizeModels) { %> -import sqldb from '../sqldb'; -var Thing = sqldb.Thing;<% if (filters.auth) { %> -var User = sqldb.User;<% } %><% } %> +import sqldb from '../sqldb';<% } %> +import config from './environment/'; -<% if (filters.mongooseModels) { %>Thing.find({}).remove()<% } - if (filters.sequelizeModels) { %>Thing.sync() - .then(() => { - return Thing.destroy({ where: {} }); - })<% } %> - .then(() => { - <% if (filters.mongooseModels) { %>Thing.create({<% } - if (filters.sequelizeModels) { %>Thing.bulkCreate([{<% } %> - name: 'Development Tools', - info: 'Integration with popular tools such as Webpack, Gulp, Babel, TypeScript, Karma, ' - + 'Mocha, ESLint, Node Inspector, Livereload, Protractor, Pug, ' - + 'Stylus, Sass, and Less.' - }, { - name: 'Server and Client integration', - info: 'Built with a powerful and fun stack: MongoDB, Express, ' - + 'AngularJS, and Node.' - }, { - name: 'Smart Build System', - info: 'Build system ignores `spec` files, allowing you to keep ' - + 'tests alongside code. Automatic injection of scripts and ' - + 'styles into your index.html' - }, { - name: 'Modular Structure', - info: 'Best practice client and server structures allow for more ' - + 'code reusability and maximum scalability' - }, { - name: 'Optimized Build', - info: 'Build process packs up your templates as a single JavaScript ' - + 'payload, minifies your scripts/css/images, and rewrites asset ' - + 'names for caching.' - }, { - name: 'Deployment Ready', - info: 'Easily deploy your app to Heroku or Openshift with the heroku ' - + 'and openshift subgenerators' - <% if (filters.mongooseModels) { %>});<% } - if (filters.sequelizeModels) { %>}]);<% } %> - }); +export default function seedDatabaseIfNeeded() { + if(config.seedDB) { + <% if (filters.sequelizeModels) { %>let Thing = sqldb.Thing;<% if (filters.auth) { %> + let User = sqldb.User;<% } %><% } %> + + <% if (filters.mongooseModels) { %>Thing.find({}).remove()<% } + if (filters.sequelizeModels) { %>return Thing.destroy({ where: {} })<% } %> + .then(() => { + <% if (filters.mongooseModels) { %>Thing.create({<% } + if (filters.sequelizeModels) { %>return Thing.bulkCreate([{<% } %> + name: 'Development Tools', + info: 'Integration with popular tools such as Webpack, Gulp, Babel, TypeScript, Karma, ' + + 'Mocha, ESLint, Node Inspector, Livereload, Protractor, Pug, ' + + 'Stylus, Sass, and Less.' + }, { + name: 'Server and Client integration', + info: 'Built with a powerful and fun stack: MongoDB, Express, ' + + 'AngularJS, and Node.' + }, { + name: 'Smart Build System', + info: 'Build system ignores `spec` files, allowing you to keep ' + + 'tests alongside code. Automatic injection of scripts and ' + + 'styles into your index.html' + }, { + name: 'Modular Structure', + info: 'Best practice client and server structures allow for more ' + + 'code reusability and maximum scalability' + }, { + name: 'Optimized Build', + info: 'Build process packs up your templates as a single JavaScript ' + + 'payload, minifies your scripts/css/images, and rewrites asset ' + + 'names for caching.' + }, { + name: 'Deployment Ready', + info: 'Easily deploy your app to Heroku or Openshift with the heroku ' + + 'and openshift subgenerators' + <% if (filters.mongooseModels) { %>});<% } + if (filters.sequelizeModels) { %>}]);<% } %> + }) + .then(() => console.log('finished populating things')) + .catch(err => console.log('error populating things', err)); <% if (filters.auth) { %> -<% if (filters.mongooseModels) { %>User.find({}).remove()<% } - if (filters.sequelizeModels) { %>User.sync() - .then(() => User.destroy({ where: {} }))<% } %> - .then(() => { - <% if (filters.mongooseModels) { %>User.create({<% } - if (filters.sequelizeModels) { %>User.bulkCreate([{<% } %> - provider: 'local', - name: 'Test User', - email: 'test@example.com', - password: 'test' - }, { - provider: 'local', - role: 'admin', - name: 'Admin', - email: 'admin@example.com', - password: 'admin' - <% if (filters.mongooseModels) { %>})<% } - if (filters.sequelizeModels) { %>}])<% } %> - .then(() => { - console.log('finished populating users'); + <% if (filters.mongooseModels) { %>User.find({}).remove()<% } + if (filters.sequelizeModels) { %>User.destroy({ where: {} })<% } %> + .then(() => { + <% if (filters.mongooseModels) { %>User.create({<% } + if (filters.sequelizeModels) { %>return User.bulkCreate([{<% } %> + provider: 'local', + name: 'Test User', + email: 'test@example.com', + password: 'test' + }, { + provider: 'local', + role: 'admin', + name: 'Admin', + email: 'admin@example.com', + password: 'admin' + <% if (filters.mongooseModels) { %>})<% } + if (filters.sequelizeModels) { %>}])<% } %> + .then(() => console.log('finished populating users')) + .catch(err => console.log('error populating users', err));<% } %> }); - });<% } %> + } +} From 42ec90a543ac2dd40001fa5fb6a239b924f39af1 Mon Sep 17 00:00:00 2001 From: Nate Stuyvesant Date: Wed, 1 Feb 2017 00:13:50 -0500 Subject: [PATCH 2/3] fix (app): prevent excess sync() calls during db seed Previously, .sync() was being called once in server/config/seed.js and once during sqldb.sequelize.sync() in server/app.js. As a result, duplicate queries were being sent to the database if the tables needed to be defined causing an error when it tries to define constraints a second time (like for an identity column). Seed.js is wrapped in a function and contains the conditional to determine whether to seed the database. This makes it easy to include in the promise chain under sqldb.sequelize.sync(). --- templates/app/server/app.js | 1 + 1 file changed, 1 insertion(+) diff --git a/templates/app/server/app.js b/templates/app/server/app.js index ba25f0b5d..82d630da5 100644 --- a/templates/app/server/app.js +++ b/templates/app/server/app.js @@ -44,6 +44,7 @@ sqldb.sequelize.sync() console.log('Server failed to start due to error: %s', err); }); <% } else { %> +seedDatabaseIfNeeded(); setImmediate(startServer); <% } %> // Expose app From d0fad3ef876f0d0d43eb1c7271e7b1387b657e71 Mon Sep 17 00:00:00 2001 From: Nate Stuyvesant Date: Wed, 1 Feb 2017 00:23:13 -0500 Subject: [PATCH 3/3] fix (app): prevent excess sync() calls during seed Previously, .sync() was being called once in server/config/seed.js and once during sqldb.sequelize.sync() in server/app.js. As a result, duplicate queries were being sent to the database if the tables needed to be defined causing an error when it tries to define constraints a second time (like for an identity column). Seed.js is wrapped in a function and contains the conditional to determine whether to seed the database. This makes it easy to include in the promise chain under sqldb.sequelize.sync(). --- templates/app/server/app.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/templates/app/server/app.js b/templates/app/server/app.js index 82d630da5..88b97fb0f 100644 --- a/templates/app/server/app.js +++ b/templates/app/server/app.js @@ -37,14 +37,14 @@ function startServer() { }); } <% if(filters.sequelize) { %> -sqldb.sequelize.sync() +sqldb.sequelize.sync()<% if(filters.models) { %> + .then(seedDatabaseIfNeeded)<% } %> .then(startServer) -<% if(filters.models) { %> .then(seedDatabaseIfNeeded)<% } %> .catch(function(err) { console.log('Server failed to start due to error: %s', err); }); -<% } else { %> -seedDatabaseIfNeeded(); +<% } else { %><% if(filters.models) { %> +seedDatabaseIfNeeded();<% } %> setImmediate(startServer); <% } %> // Expose app