Closed awolden closed 5 years ago
@awolden I'm interested in hearing thoughts about this. I haven't experimented much with AWS lambda so I'm not sure what would be involved.
Wouldn't it just be using the renderBatch
logic? If so, we can just pull that out of this package or provide a way so you can link to it.
@goatslacker Funny you should mention renderBatch
, I built a PoC where I directly called renderBatch
. The only real issue I ran into was that the renderBatch promise doesn't actually return the results and it is highly coupled to express objects. If the renderBatch
was a little more decoupled from express, it would be easy to seamlessly integrate it into a lambda.
Quick PoC:
"use strict";
const renderBatch = require('hypernova-lambda/lib/utils/renderBatch');
const requireDir = require('require-dir');
const components = requireDir('../components');
const defaultConfig = {
bodyParser: {
limit: 1024 * 1000,
},
devMode: false,
endpoint: '/batch',
files: [],
logger: {},
plugins: [],
port: 8080,
};
module.exports = function makeRequest(e, context) {
/*---------
Mock things that look like express
----------*/
const requestObject = {
body: e.payload
}
const responseObject = new MockResponse();
// set-up hypernova config
const config = Object.assign({}, defaultConfig, {
getComponent(name) {
return components[name];
}
});
// initialize renderer
const renderer = renderBatch(config, () => false);
// call renderer with mock objects
renderer(requestObject, responseObject);
// wait for renderer to complete and return the results
responseObject.waitForCompletion().then((results) => {
context.succeed(results);
})
.catch(err => context.failure(err));
}
class MockResponse {
waitForCompletion() {
return new Promise((resolve, reject) => {
this.resolve = resolve;
this.reject = reject;
});
}
status(statusCode) {
this.statusCode = statusCode;
return this;
}
end() {
if(!this.returnValue || this.returnValue.error){
return this.reject(this.returnValue.error || 'Unknown error');
}
return this.resolve(this.returnValue);
}
json() {
this.returnValue = arguments[0];
return this;
}
}
If whatever server you're using has a concept of a "request" and "response" then this should be as easy as:
import BatchManager from './BatchManager';
import { processBatch } from './lifecycle';
export default (req, res) => {
const jobs = req.body;
const config = {};
const manager = new BatchManager(req, res, jobs, config);
return processBatch(jobs, config.plugins, manager).then(() => manager).catch(() => manager);
};
The promise can return the BatchManager instance and then you'll be able to pull the statusCode
from there or call getResults()
yourself to get all the results.
The jobs
being pulled from req.body
can be configured of course, same with config
.
@goatslacker, sorry for the delayed response on this, I haven't looked into this much further than the PoC I have above. Node AWS Lambda's do not have a concept of req
or res
, but it should be easy enough to mock objects that look like req/res. I like your suggested solution using processBatch
. I will give it a try!
Thanks for the help.
-Alex
@awolden there's a npm package to implement it into a lambda https://www.npmjs.com/package/hypernova-lambda
@ljharb looks like this question was answered. I even shared an existing package using the approach discussed aboved.
I've been looking into this project and I am really excited about it. I am curious if there has been any talk about having the flexibility to use a server environment that is not express. Namely the use-case I find most interesting would be the ability to run hypernova as a lambda, which would require a more stateless implementation.
Thanks!