M. Maiz Nadeem
M. Maiz Nadeem

Reputation: 109

Why is code working fine locally, but takes longer on Google App Engine Flexible Environment?

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

Answers (1)

John Hanley
John Hanley

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

Related Questions