Reputation: 109
I have this Node.JS application. I made its docker image from this base: https://hub.docker.com/r/bcgovimages/alpine-node-libreoffice When I compare the performance by running the image locally and deploying it on Google Cloud App Engine (GAE) Flexible Environment, there isn't a big difference expect for this function:
const getWordDocument = async (req, res) => {
try {
const doc = new Document(); // This is a Word Document created using docx npm library. I omitted previous code for readability.
const filename = uuidv4();
// Saving in Docx format
await Packer.toBuffer(doc).then((buffer) => {
fs.writeFileSync(`./assets/${filename}.docx`, buffer);
});
const environment = process.env.NODE_SERVER_ENV || "PROD";
// Executing libreoffice for .docx to .pdf conversion
exec(`${environment == "PROD" ? "libreoffice" : "soffice"} --headless --convert-to pdf ./assets/${filename}.docx --outdir ./assets/`, (error, stdout, stderr) => {
if (error) {
console.error(`Error converting file: ${error}`);
return;
}
// Uploading docs to Storage Bucket and sending their URLs back in response.
uploadDocs(filename)
.then((urls) => {
res.json({ urls: urls });
})
.catch((err) => {
console.error('Error uploading files:', error);
res.status(500).send('Error uploading files');
})
});
} catch (error) {
console.error('Error retrieving file:', error);
res.status(500).send('Error retrieving file');
}
};
async function uploadDocs(filename) {
try {
const bucketName = 'blah-blah-blah';
const folderName = 'purchase';
const uniqueIdentifier = uuidv4();
const objectNameDocx = `${folderName}/${uniqueIdentifier}/Document.docx`;
const objectNamePdf = `${folderName}/${uniqueIdentifier}/Document.pdf`;
const bucket = storage.bucket(bucketName);
await Promise.all([
new Promise((resolve, reject) => {
const docxFile = bucket.file(objectNameDocx);
const docxStream = docxFile.createWriteStream({
metadata: {
contentType: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
}
});
fs.createReadStream(`./assets/${filename}.docx`)
.pipe(docxStream)
.on('error', reject)
.on('finish', resolve);
}),
new Promise((resolve, reject) => {
const pdfFile = bucket.file(objectNamePdf);
const pdfStream = pdfFile.createWriteStream({
metadata: {
contentType: 'application/pdf'
}
});
fs.createReadStream(`./assets/${filename}.pdf`)
.pipe(pdfStream)
.on('error', reject)
.on('finish', resolve);
})
]);
fs.unlinkSync(`./assets/${filename}.docx`);
fs.unlinkSync(`./assets/${filename}.pdf`);
const docxSignedUrl = await bucket.file(objectNameDocx).getSignedUrl({
action: 'read',
expires: Date.now() + 60 * 60 * 1000,
});
const pdfSignedUrl = await bucket.file(objectNamePdf).getSignedUrl({
action: 'read',
expires: Date.now() + 60 * 60 * 1000,
});
return [...docxSignedUrl, ...pdfSignedUrl];
} catch (error) {
console.error('Error uploading files:', error);
throw error;
}
}
In my observation, the specific part ".docx to .pdf conversion using libreoffice" is taking a lot longer. Exec command may be a culprit. Because other parts of the application (interacting with storage bucket, apis etc) are working fine without delays.
When using this function, the whole operation takes:
My laptop is 8GB RAM, intel i5 12th Gen, so I don't think it's fast enough. I'm on a free quota on Google Cloud so maybe I'm not issued much resources? Can somebody point out the issue?
Here's the dockerfile:
FROM bcgovimages/alpine-node-libreoffice:latest
WORKDIR /app
COPY package*.json ./
RUN npm install
# Copy the rest of your application code
COPY . .
# Expose the port your app runs on
EXPOSE 8080
# Command to run your application
CMD ["node", "index.js"]
app.yaml:
runtime: custom
env: flex
entrypoint: node index.js
handlers:
- url: /.*
script: auto
secure: always
env_variables:
NODE_SERVER_ENV: "PROD"
I have to convert document on server because I can't embed fonts in MS Word Document, and converting to PDF here helps retain fonts.
Thank you.
Upvotes: 0
Views: 71
Reputation: 81454
Change app.yaml
and declare the cpu
and memory_bg
values. Then retest.
Start with cpu = 2 and memory_gb = 2. Increase as required.
Upvotes: 0