diff --git a/.circleci/config.yml b/.circleci/config.yml index 526064bd..415e36c5 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -6,7 +6,7 @@ version: 2 jobs: ui-build: docker: - - image: circleci/node:7.10 + - image: circleci/node:8.10 working_directory: ~/carpal/frontend @@ -49,10 +49,13 @@ jobs: - run: name: Deploy to S3 command: aws s3 sync /tmp/build/ s3://carpal-ui-rides-dev/ --delete - services-deploy: + services-build: docker: - - image: circleci/node:7.10 - working_directory: ~/carpal/backend/src + - image: circleci/node:8.10 + - image: mysql:5.7 + environment: + MYSQL_ROOT_PASSWORD: admin + working_directory: ~/carpal/backend steps: - checkout: path: ~/carpal @@ -62,17 +65,31 @@ jobs: # fallback to using the latest cache if no exact match is found - v1-dependencies- - run: npm install + - run: npm run refresh-db + - run: npm test - save_cache: paths: - node_modules key: v1-dependencies-{{ checksum "package.json" }} + services-deploy: + docker: + - image: circleci/node:8.10 + working_directory: ~/carpal/backend + steps: + - checkout: + path: ~/carpal + - restore_cache: + keys: + - v1-dependencies-{{ checksum "package.json" }} + # fallback to using the latest cache if no exact match is found + - v1-dependencies- - run: ./writeSecrets.sh - - run: npm test - run: npm run deploy-sls workflows: version: 2 - ui-build-deploy: + application-build-deploy: jobs: + - services-build - ui-build - ui-deploy: requires: @@ -83,4 +100,4 @@ workflows: - services-deploy: filters: branches: - only: master \ No newline at end of file + only: master diff --git a/backend/package.json b/backend/package.json index 3da54aab..6058113e 100644 --- a/backend/package.json +++ b/backend/package.json @@ -5,7 +5,6 @@ "test": "mocha './src/test/**/*.test.js'", "start": "node src/test/expressApis.js", "refresh-db": "node ./src/main/database/index.js", - "refresh-test-db": "node ./src/test/database/refreshDatabase.js", "deploy-sls": "sls deploy" }, "dependencies": { diff --git a/backend/serverless.yml b/backend/serverless.yml index 491ccd13..08e6a2b1 100644 --- a/backend/serverless.yml +++ b/backend/serverless.yml @@ -2,7 +2,7 @@ service: carpal provider: name: aws - runtime: nodejs6.10 + runtime: nodejs8.10 region: ap-southeast-2 stage: dev memorySize: 128 diff --git a/backend/src/main/database/DatabaseManager.js b/backend/src/main/database/DatabaseManager.js index fa3b4eb0..97221fd6 100644 --- a/backend/src/main/database/DatabaseManager.js +++ b/backend/src/main/database/DatabaseManager.js @@ -28,12 +28,13 @@ class DatabaseManager { connection.query(queryString, (error, results, fields) => { if (closeConnection) { let closePromise = this.closeConnection(connection); - return closePromise.finally(() => { - if (error) { - return reject(error); - } - resolve(results); - }); + return closePromise + .then(() => { + resolve(results); + }) + .catch(error1 => { + reject(error1 || error); + }); } if (error) { console.log("Error executing", queryString, error); diff --git a/backend/src/main/database/RefreshDatabase.js b/backend/src/main/database/RefreshDatabase.js index 46f731e1..e7c9f9ee 100644 --- a/backend/src/main/database/RefreshDatabase.js +++ b/backend/src/main/database/RefreshDatabase.js @@ -1,8 +1,9 @@ const fs = require('fs'); const path = require('path'); +const DatabaseManager = require('./DatabaseManager'); +const createDB = '2018-08-04-1-create-database.sql'; const changeSet = [ - '2018-08-04-1-create-database.sql', '2018-08-04-2-create-location-table.sql', '2018-08-04-3-create-rides-table.sql', '2018-08-04-4-create-driver-table.sql', @@ -12,18 +13,27 @@ const changeSet = [ class RefreshDatabase { constructor(databaseManager) { + const dbConfig = Object.assign({}, databaseManager.databaseConfig); + + delete dbConfig.database; + this.databaseManagerNoDb = new DatabaseManager(dbConfig); this.databaseManager = databaseManager; } async executeAll() { - for (let fileName of changeSet) { - await this.execute(fileName); - } + this.execute(createDB, this.databaseManagerNoDb) + .then(() => { + let result = Promise.resolve(); + changeSet.forEach(fileName => { + result = result.then(this.execute(fileName, this.databaseManager)) + }); + return result; + }) } - async execute(fileName) { + execute(fileName, databaseManager) { let sql = fs.readFileSync(path.resolve(__dirname, './changes/' + fileName)).toString().trim(); - return this.databaseManager.query(sql); + return databaseManager.query(sql); } } diff --git a/backend/src/main/database/changes/2018-08-04-1-create-database.sql b/backend/src/main/database/changes/2018-08-04-1-create-database.sql index 95e1904f..62719596 100644 --- a/backend/src/main/database/changes/2018-08-04-1-create-database.sql +++ b/backend/src/main/database/changes/2018-08-04-1-create-database.sql @@ -1 +1 @@ -CREATE DATABASE IF NOT EXISTS carpal; \ No newline at end of file +CREATE SCHEMA IF NOT EXISTS carpal; \ No newline at end of file diff --git a/backend/src/main/rides/CreateRideService.js b/backend/src/main/rides/CreateRideService.js index db4ae7a1..4533c0fe 100644 --- a/backend/src/main/rides/CreateRideService.js +++ b/backend/src/main/rides/CreateRideService.js @@ -5,6 +5,7 @@ const rideSchema = require('../schema/ride.json'); const RideStatus = require('./RideStatus'); const RideRepository = require('./RideRepository'); const RideMapper = require('./RideMapper'); +const PromiseUtils = require('../utils/PromiseUtils'); class CreateRideService { @@ -16,8 +17,9 @@ class CreateRideService { createRide(body, loginData) { const connection = this._databaseManager.createConnection(); - return this._createRide(body, loginData, connection) - .finally(() => this._databaseManager.closeConnection(connection)); + const createRidePromise = this._createRide(body, loginData, connection); + const closeConnection = () => this._databaseManager.closeConnection(connection); + return PromiseUtils.promiseFinally(createRidePromise, closeConnection); } _createRide(rideObject, loginData, connection) { diff --git a/backend/src/main/rides/FindOneRideService.js b/backend/src/main/rides/FindOneRideService.js index f53981f4..5aee8b83 100644 --- a/backend/src/main/rides/FindOneRideService.js +++ b/backend/src/main/rides/FindOneRideService.js @@ -2,6 +2,7 @@ const RideRepository = require('./RideRepository'); const RidesMapper = require('./RideMapper'); +const PromiseUtils = require('../utils/PromiseUtils'); class FindOneRideService { @@ -16,8 +17,9 @@ class FindOneRideService { } const connection = this._databaseManager.createConnection(); - return this._findOne(id, loginData, connection) - .finally(() => this._databaseManager.closeConnection(connection)); + const findOnePromise = this._findOne(id, loginData, connection); + const closeConnection = () => this._databaseManager.closeConnection(connection); + return PromiseUtils.promiseFinally(findOnePromise, closeConnection); } _findOne(id, loginData, connection) { diff --git a/backend/src/main/rides/ListRidesService.js b/backend/src/main/rides/ListRidesService.js index 3192e62c..d5ee4827 100644 --- a/backend/src/main/rides/ListRidesService.js +++ b/backend/src/main/rides/ListRidesService.js @@ -2,6 +2,7 @@ const RideRepository = require('./RideRepository'); const RidesMapper = require('./RideMapper'); +const PromiseUtils = require('../utils/PromiseUtils'); class ListRidesService { @@ -13,9 +14,10 @@ class ListRidesService { listRides(query, loginData) { const connection = this._databaseManager.createConnection(); - return this._listRides(query, loginData, connection) - .then(rides => rides.map(RidesMapper.entityToDto)) - .finally(() => this._databaseManager.closeConnection(connection)); + const listRidesPromise = this._listRides(query, loginData, connection) + .then(rides => rides.map(RidesMapper.entityToDto)); + const closeConnection = () => this._databaseManager.closeConnection(connection); + return PromiseUtils.promiseFinally(listRidesPromise, closeConnection); } _listRides(query, loginData, connection) { diff --git a/backend/src/main/rides/RideRepository.js b/backend/src/main/rides/RideRepository.js index 520edab7..fd2dce1b 100644 --- a/backend/src/main/rides/RideRepository.js +++ b/backend/src/main/rides/RideRepository.js @@ -5,13 +5,14 @@ const moment = require('moment'); class RideRepository { constructor(databaseManager) { this._databaseManager = databaseManager; + this._dbName = this._databaseManager.databaseConfig.database; } create(ride, connection) { const escape = (data) => connection.escape(data); const locationFrom = `POINT(${ride.locationFrom.latitude}, ${ride.locationFrom.longitude})`; const locationTo = `POINT(${ride.locationTo.latitude}, ${ride.locationTo.longitude})`; - let query = `INSERT INTO rides(client, + let query = `INSERT INTO ${this._dbName}.rides(client, facilitatorEmail, pickupTimeAndDateInUTC, locationFrom, @@ -60,7 +61,7 @@ class RideRepository { const escape = (data) => connection.escape(data); const locationFrom = `POINT(${ride.locationFrom.latitude}, ${ride.locationFrom.longitude})`; const locationTo = `POINT(${ride.locationTo.latitude}, ${ride.locationTo.longitude})`; - let query = `UPDATE rides SET client = ${escape(ride.client)}, + let query = `UPDATE ${this._dbName}.rides SET client = ${escape(ride.client)}, facilitatorEmail = ${escape(ride.facilitatorId)}, pickupTimeAndDateInUTC = ${escape(moment(ride.pickupTimeAndDateInUTC).format('YYYY-MM-DD HH:mm:ss'))}, locationFrom = ${locationFrom}, @@ -120,7 +121,7 @@ class RideRepository { where.push(`facilitatorEmail = ${escape(jsonQuery.facilitatorId)}`) } - let query = `SELECT * FROM rides ${where.length ? ' WHERE ' + where.join(' AND ') : ''} ORDER BY pickupTimeAndDateInUTC ASC;`; + let query = `SELECT * FROM ${this._dbName}.rides ${where.length ? ' WHERE ' + where.join(' AND ') : ''} ORDER BY pickupTimeAndDateInUTC ASC;`; console.log(query); return this._databaseManager.query(query, connection) .then(rides => diff --git a/backend/src/main/rides/UpdateRideService.js b/backend/src/main/rides/UpdateRideService.js index 08f331f5..86f0d267 100644 --- a/backend/src/main/rides/UpdateRideService.js +++ b/backend/src/main/rides/UpdateRideService.js @@ -4,6 +4,7 @@ const jsonValidator = require('jsonschema'); const rideSchema = require('../schema/ride.json'); const RideRepository = require('./RideRepository'); const RideMapper = require('./RideMapper'); +const PromiseUtils = require('../utils/PromiseUtils'); class UpdateRideService { @@ -14,9 +15,9 @@ class UpdateRideService { updateRide(id, ride, loginData) { const connection = this._databaseManager.createConnection(); - let updatePromise = this._updateRide(id, ride, loginData, connection); - return updatePromise.finally(() => this._databaseManager.closeConnection(connection)); + const closeConnection = () => this._databaseManager.closeConnection(connection); + return PromiseUtils.promiseFinally(updatePromise, closeConnection); } _updateRide(id, rideObject, loginData, connection) { diff --git a/backend/src/main/utils/PromiseUtils.js b/backend/src/main/utils/PromiseUtils.js new file mode 100644 index 00000000..2772cf9e --- /dev/null +++ b/backend/src/main/utils/PromiseUtils.js @@ -0,0 +1,17 @@ +class PromiseUtils { + static promiseFinally(promise, finallyFn) { + return new Promise((resolve, reject) => { + promise + .then(result => { + return Promise.resolve(finallyFn()) + .then(() => resolve(result)) + }) + .catch(error => { + return Promise.resolve(finallyFn()) + .then(() => resolve(reject(error))); + }); + }); + } +} + +module.exports = PromiseUtils; \ No newline at end of file