Skip to content

Commit

Permalink
Fix(#252): Updates (#264)
Browse files Browse the repository at this point in the history
* #252: Updated graphql schema description

* #252: Add changes to automatically create storage at RESTAPI start up

* #252: Refactored pixel data endpoint

* #252: Added a centralized log writer
  • Loading branch information
tholulomo authored Oct 17, 2022
1 parent b100066 commit 216a1d3
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 24 deletions.
70 changes: 52 additions & 18 deletions resfulservice/src/controllers/pixelatedController.js
Original file line number Diff line number Diff line change
@@ -1,42 +1,76 @@
const csv = require('csvtojson');
const PixelData = require('../models/pixelated');
const deleteFile = require('../utils/fileManager');
const { errorWriter, successWriter } = require('../utils/logWriter');

exports.uploadPixelData = async (req, res, next) => {
try {
req.logger.info('pixelData Upload Function Entry:');
if (!req.files?.uploadfile) return res.status(400).json({ message: 'PixelData csv not uploaded', statusCode: 400 });
if (!req.userId) {
req.logger?.error('[uploadPixelData]: User not authenticated to upload data');
if (!req.user) {
deleteFile(req.files.uploadfile[0].path, req);
return res.status(401).json({ message: 'Not authenticated', statusCode: 401 });
return next(errorWriter(req, 'Not authenticated', 'uploadPixelData', 401));
}

if (!req.files?.uploadfile) {
return next(errorWriter(req, 'PixelData csv not uploaded', 'uploadPixelData', 400));
}

const dataExists = await PixelData.findOne({});
if (dataExists) {
deleteFile(req.files.uploadfile[0].path, req);
return next(errorWriter(req, 'Pixeldata already exists', 'uploadPixelData', 403));
}

const pixelDataArray = await csv().fromFile(req.files.uploadfile[0].path);
PixelData.insertMany(pixelDataArray);
res.status(201).json({ message: 'success', statusCode: 201 });
return deleteFile(req.files.uploadfile[0].path, req);
if (pixelDataArray.length === 0) {
deleteFile(req.files.uploadfile[0].path, req);
return next(errorWriter(req, 'PixelData csv is empty', 'uploadPixelData', 400));
}
await insertMany(req, pixelDataArray);
deleteFile(req.files.uploadfile[0].path, req);
successWriter(req, { message: 'success' }, 'uploadPixelData');
return res.status(201).json({ message: 'success' });
} catch (error) {
req.logger?.error(`[uploadPixelData]: ${error}`);
return res.status(500).json({ message: 'Internal server error', statusCode: 500 });
next(error);
}
};

exports.updatePixelData = async (req, res, next) => {
try {
req.logger.info('pixelData Update Function Entry:');
if (!req.userId) {
req.logger?.error('[updatePixelData]: User not authenticated to update data');
deleteFile(req.files.uploadfile[0].path, req);
return res.status(401).json({ message: 'Not authenticated', statusCode: 401 });
if (!req.user) {
req.files.uploadfile.forEach(({ path }) => {
deleteFile(path, req);
});
return next(errorWriter(req, 'Not authenticated', 'updatePixelData', 401));
}
const pixelDataArray = await csv().fromFile(req.files.uploadfile[0].path);
await PixelData.deleteMany({});
PixelData.insertMany(pixelDataArray);
res.status(201).json({ message: 'success', statusCode: 201 });
return deleteFile(req.files.uploadfile[0].path, req);

if (!req.files?.uploadfile) {
return next(errorWriter(req, 'PixelData csv not uploaded', 'updatePixelData', 400));
}
if (req.body.dataExists) {
await PixelData.deleteMany({});
successWriter(req, 'Successfully deleted all existing pixel data in mongoDB', 'updatePixelData');
}
req.files.uploadfile.forEach(async ({ path }) => {
const pixelDataArray = await csv().fromFile(path);
await insertMany(req, pixelDataArray);
deleteFile(path, req);
});
successWriter(req, { message: 'success' }, 'updatePixelData');
return res.status(201).json({ message: 'success' });
} catch (error) {
req.logger?.error(`[updatePixelData]: ${error}`);
return res.status(500).json({ message: 'Internal server error', statusCode: 500 });
error.message = 'Internal Server Error';
next(error);
}
};

async function insertMany (req, pixelData) {
try {
await PixelData.insertMany(pixelData, { ordered: false });
} catch (e) {
errorWriter(req, e, 'insertMany');
}
}
6 changes: 5 additions & 1 deletion resfulservice/src/models/pixelated.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ const pixelDataSchema = new Schema({
type: String
},
geometry_condensed: {
type: String
type: String,
unique: true,
dropDups: true
},
geometry_full: {
type: String
Expand Down Expand Up @@ -82,4 +84,6 @@ const pixelDataSchema = new Schema({
}
}, { timestamps: true });

pixelDataSchema.index({ geometry_condensed: 1 });

module.exports = mongoose.model('PixelData', pixelDataSchema);
6 changes: 3 additions & 3 deletions resfulservice/src/routes/pixelated.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@

const express = require('express');
const router = express.Router();
const pixelatedController = require('../controllers/pixelatedController');
const isAuth = require('../middlewares/isAuth');

router.route('/').post(isAuth, pixelatedController.uploadPixelData);
router.route('/edit').post(isAuth, pixelatedController.updatePixelData);
router.route('/')
.post(isAuth, pixelatedController.uploadPixelData)
.put(isAuth, pixelatedController.updatePixelData);

module.exports = router;
3 changes: 1 addition & 2 deletions resfulservice/src/utils/iterator.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,7 @@ exports.iteration = (arr, iterationFn, batchSize) => new Promise((resolve, rejec
let pendingPromises = [];
const pausePromises = async () => {
try {
// eslint-disable-next-line no-extra-boolean-cast
if (!!pendingPromises.length) {
if (pendingPromises.length) {
await Promise.all(pendingPromises);
}
resolve();
Expand Down
32 changes: 32 additions & 0 deletions resfulservice/src/utils/logWriter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/**
* Writes error to logger and return the error
* @param {*} req
* @param {*} error
* @param {String} fnName
* @param {Number} code
* @param {String} type
* @returns {Error} error
*/
exports.errorWriter = (req, error, fnName = 'N/A', code, type) => {
if (!error) {
req.logger?.emerg(`[${fnName}]: No error info provided`);
return new Error('Server Error');
}

if (type) req.logger[type](`[${fnName}]: error - ${error}`);
else req.logger?.error(`[${fnName}]: error - ${error}`);
const err = new Error(error);
if (code) err.statusCode = code;
return err;
};

/**
* Writes successful executions into logger
* @param {*} req
* @param {*} message
* @param {String} fnName
* @returns
*/
exports.successWriter = (req, message, fnName) => {
return req.logger?.notice(`${fnName}(): Success - ${message}`);
};

0 comments on commit 216a1d3

Please sign in to comment.