jsreport/jsreport-core

How to execute in aws lambda?

Closed this issue · 6 comments

I'm having trouble getting PDF generation working in an aws-lambda environment (works fine on a Mac laptop).

From what I can tell so far, this is largely because of various jsreport-*** modules/extensions attempting to write into places other than the folder specified in the options:tempDirectory folder. There is only one writable folder in a nodeJS lambda environment so these attempts fail.
I'm working around this by copying the entire data/ subtree into the writable area /tmp which seems to help.
My latest issue is with the extension loading logic. I've disabled discovery and I'm explicitly useing the modules I need but I'm still seeing something in the jsreport-core/lib/extensions/extensionManager.js failing with this message:

error: Error when loading extension Error: ENOENT: no such file or directory, scandir '/var/runtime/node_modules/awslambda/node_modules'

I've found one more option whose use is unclear to me but appears to be used in the extension loading logic: parentModuleDirectory. I'm going to experiment with that to see what it does.

Any help/suggestions appreciated.

hi! can you show the code that you are using to start jsreport (the entry point file)?

options:

{
    "certificate": {
        "key": "certificates/jsreport.net.key",
        "cert": "certificates/jsreport.net.cert"
    },
    "authentication": {
        "cookieSession": {
            "secret": "<your strong secret>"
        },
        "admin": {
            "username": "admin",
            "password": "password"
        },
        "enabled": false
    },
    "httpPort": 5488,
    "httpsPort": null,
    "logger": {
        "error": {
            "transport": "console",
            "level": "error"
        }
    },
    "blobStorage": "inMemory",
    "tempDirectory": "/tmp",
    "dataDirectory": "/tmp/jsreport/data",
    "rootDirectory": "/var/task",
    "phantom": {
        "strategy": "dedicated-process",
        "timeout": 60000
    },
    "tasks": {
        "strategy": "dedicated-process",
        "timeout": 10000,
        "allowedModules": "*"
    },
    "scripts": {
        "allowedModules": [],
        "timeout": 60000
    },
    "sample-template": {
        "createSamples": true
    },
    "connectionString": {
        "name": "fs",
        "syncModifications": false
    },
    "discover": false,
    "autoTempCleanup": false,
    "parentModuleDirectory": "/tmp"
}

code:

  const jsreport = require('jsreport-core')(options);
	jsreport.use(require('jsreport-assets')())
	jsreport.use(require('jsreport-data')())
	jsreport.use(require('jsreport-fs-store')())
	jsreport.use(require('jsreport-handlebars')());
	jsreport.use(require('jsreport-html-to-xlsx')())
	jsreport.use(require('jsreport-images')())
	jsreport.use(require('jsreport-phantom-pdf')())
	jsreport.use(require('jsreport-scripts')())
	jsreport.use(require('jsreport-templates')())
	jsreport.use(require('jsreport-text')())

	return jsreport.init()
	.then(function() {
		console.log('Starting …')
		return jsreport.render({
			template: { shortid: options.templateID },
			data: options.data,
		})
		.then(function(res) {
			return res.content
		})
		.catch(function(e) {
			return Promise.reject(e)
		})
	})
	.catch(function(e) {
		return Promise.reject(e)
	})

It this is not a supported scenario I can switch to using an ec2 instance with fewer constraints.
Was just looking to keep with lambdas if possible.

It this is not a supported scenario I can switch to using an ec2 instance with fewer constraints.
Was just looking to keep with lambdas if possible.

it should be a supported scenario, however any of us have took the chance to try jsreport in lambda successfully and make it easier. we just know that some other users has been able to make it run, also we know that phantomjs doesn't normally run on the lambda, it needs to be compiled somehow in their OS and is kind of very complex.

From what I can tell so far, this is largely because of various jsreport-*** modules/extensions attempting to write into places other than the folder specified in the options:tempDirectory folder. There is only one writable folder in a nodeJS lambda environment so these attempts fail.

hmm can you please describe what other directories are being attempted to write? i don't remember any other than data and temp directory.

My latest issue is with the extension loading logic. I've disabled discovery and I'm explicitly useing the modules I need but I'm still seeing something in the jsreport-core/lib/extensions/extensionManager.js failing with this message:

error: Error when loading extension Error: ENOENT: no such file or directory, scandir '/var/runtime/node_modules/awslambda/node_modules'

I've found one more option whose use is unclear to me but appears to be used in the extension loading logic: parentModuleDirectory. I'm going to experiment with that to see what it does.

i think you don't need to configure anything with parentModuleDirectory in this case, but i could be wrong, anyway it seems like parentModuleDirectory should not affect anything because auto discover it is disabled.

thanks for the issue report, we will try to improve the lambda support, for now i think you are better with an ec2 instance, or if somehow you figure it out how to make it run in lambda please share the knowledge so we can improve the situation in general.

Thanks so much for the detailed response.
I'll get back to you with more details as I know them. It's good to know that someone else has made this work. That helps me :)

I published an article on how to use jsreport in aws lambda.

https://jsreport.net/learn/aws-lambda-serverless