AWS Lambda Function "Process exited before completing request" caused by hanging? - javascript

I have developed a node application which I would like to have called as an AWS Lambda Application.
The application works as intended as an AWS Lambda, however my CloudWatch logs always finish with the following error: Process exited before completing request.
I wrote some code to ensure that my context.succeed() and context.fail() calls were taking place and they are. However, when ran locally, I also noted a lag between my logging of success in start.js and the command prompt appearing again, making me believe there could be some node processes still taking place once those calls have been made. Could that be causing the error, and if so what is a good way to triage and resolve the issue?
The relevant code is below:
lambda-handle.js
import log from './log';
import database from './database';
import User from './database/models/user';
export function handle(event, context) {
log.info('CS Blogs Feed Aggregator Started');
database.sync()
.then(() =>
User.findAll({
attributes: ['id', 'blogFeedURI']
}))
.then(users => {
users.forEach(user => {
log.info({ user }, 'User loaded from database');
});
})
.then(() => {
// context.done() called so AWS knows function completed successfully
context.succeed();
})
.catch(error => {
context.fail(error);
});
}
start.js (used to test context.succeed/fail being called)
// This function invokes the AWS Lambda Handle as AWS would
// but allows you to do it from your local machine for development
// or from a non-AWS server
import { handle } from './lambda-handle';
import log from './log';
handle({}, {
succeed: result => {
log.info({ result: result || 'No result returned' }, 'Process succeeded');
},
fail: error => {
log.error({ error: error || 'No error returned' }, 'Process failed');
}
});
The code is being transpiled by babel before being deployed. However, I suspect there is more of a logic issue so I have shown you the original source code.
If any more information is required the repository is available here: https://github.com/csblogs/feed-downloader/tree/fix/lambda-implementation-details
Thanks

I am pretty sure this is caused by at least 1 native module dependency in bunyan(dtrace-provider). Native modules need to be built/installed on the system that they will run on. So in the case of Lambda you need to run npm install on a linux ec2 instance or possibly vagrant to get the right version of dtrace-provider built.
See:
Cross-compile node module with native bindings with node-gyp
https://aws.amazon.com/blogs/compute/nodejs-packages-in-lambda/ (scroll to Native Modules)
You could probably just remove Bunyan to verify it works and then go down the ec2/vagrant compile route if that fixes it.

Related

Why is Sentry.captureMessage not working inside winston Transport log function

I’m trying to get Sentry working with winston (using winston-transport-sentry-node) but it doesn’t seem to work, despite using just a very basic configuration. So out of curiosity, I tried writing my own very simple winston transport class that sends Sentry message for every log like so
import * as Sentry from '#sentry/node'
import * as TransportStream from 'winston-transport'
export class SentryCustomTransport extends TransportStream {
constructor(opts) {
super(opts)
Sentry.init({
dsn: process.env.SENTRY_DSN,
environment: process.env.ENV_NAME,
sampleRate: 1,
tracesSampleRate: 1,
})
Sentry.captureMessage('Test message constructor')
}
log(info, callback) {
setImmediate(() => {
this.emit('logged', info);
})
console.log('Called log function')
const eventId = Sentry.captureMessage('Test message log')
console.log('Event ID:', eventId)
callback()
}
}
After calling winston logger, I can see an entry in Sentry with message "Test message constructor" but not "Test message log". What's even weirder is I can see the console log prints, including the event ID returned from the calls to Sentry.captureMessage() in the log() function.
I'm not sure what's going on, and kind of have no idea how to make it work. What am I missing here?
winston version: 3.8.2
#sentry/node version: 7.37.2
winston-transport-sentry-node version: 2.7.0
I managed to find the cause of the issue myself. The context of my issue was I'm writing a CLI command in NestJS. Part of the command's implementation (rather incorrectly) include a call to process.exit() function which immediately terminates the command without giving it a chance to do proper clean up (and flushing of data). I'm guessing it's because of this the Sentry module didn't get the chance to actually push the created Sentry event to Sentry server.
Removing the calls to process.exit() and letting the command finishes normally resolves the issue.

Error: Body must be a string. Received: undefined. - When using Amplify, AppSync, and GraphQL from React/NextJS client

When I try to make a call from my front-end (NextJS) I get the following error Error: Body must be a string. Received: undefined.
I can successfully make a call from my AppSync console, but not from my front-end. I have pushed the following schema.graphql file with amplify push:
type Mutation {
...
cancelCard(input: CancelCardInput!): AWSJSON
#function(name: "myp-service-prod-cancel-stepfunction-lambda")
}
I'm seeing logs in CloudWatch when I trigger the Lambda from the Lambda and AppSync consoles, but something is blocking the calls from my javascript:
import { cancelCard } from "../src/graphql/mutations";
const lambdaResponse = await API.graphql(
graphqlOperation(cancelCard, {
input: { id: cardId },
})
)
The problem was that I had performed amplify codegen configure and updated from javascript to typescript. As a result, Amplify had updated my src/ folder to have .ts files in, but not removed the .js files. This meant that where I had:
src/graphql/
mutations.ts
mutations.js
My app was ignoring the mutations.ts file.
Deleting the js files solved the issue.

When I try to deploy my function in firebase, it shows me "Error: Functions did not deploy properly". How to solve this?

I want to send message through firebase cloud message via firebase cloud function. Here's my code below
const functions = require("firebase-functions");
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
const axios = require('axios');
//import axios from 'axios';
exports.abc = functions.pubsub.schedule('every 50 minutes').onRun(async (context) => {
let response=await axios.get(
'https://coronavirus-19-api.herokuapp.com/countries/bangladesh'
);
console.log(response.data);
let body=response.data.todayDeaths;
console.log(body);
let message = {
notification: {
'title': 'Today death',
'body': `${body}`,
},
topic:'allUser'
};
admin.messaging().send(message)
.then(response=>{
console.log("Successfully sent",response);
}).catch(error=>{
console.log("failed",response);
});
console.log('This will be run every 2 minutes!');
return null;
});
But when I tried to deploy my function, I am getting an error
Functions deploy had errors with the following functions:
abc(us-central1)
To try redeploying those functions, run:
firebase deploy --only "functions:abc"
To continue deploying other features (such as database), run:
firebase deploy --except functions
Error: Functions did not deploy properly.
And this the error notification from log of firebase cloud function
Provided module can't be loaded.
Did you list all required modules in the package.json dependencies?
Detailed stack trace: Error: Cannot find module 'axios'
Require stack:
and also
Error: function terminated. Recommended action: inspect logs for termination reason.
Additional troubleshooting documentation can be found at
https://cloud.google.com/functions/docs/troubleshooting#logging Function cannot be
initialized.
{"code":3,"message":"Function failed on loading user code. This is likely due to a bug in the
user code. Error message: Error: please examine your function logs to see the error cause:
https://cloud.google.com/functions/docs/monitoring/logging#viewing_logs. Additional
troubleshooting documentation can be found at
https://cloud.google.com/functions/docs/troubleshooting#logging. Please visit
https://cloud.google.com/functions/docs/troubleshooting for in-depth troubleshooting
documentation."},"authenticationInfo":
how to solve this?

Jest Call retries were exceeded

I have error in the following below test. My node version is : v12.10.0. is there any alternative of setTimeout?
test('demo code', async () => {
const cc = await projectSetup(project);
const onNotification = jest.fn();
cc.sendNotification();
await waitForExpect(() => {
expect(onNotification).toHaveBeenCalledTimes(2);
});
});
The Error log is as
Call retries were exceeded
at ChildProcessWorker.initialize (../../../node_modules/jest-worker/build/workers/ChildProcessWorker.js:230:21)
just add jest.useFakeTimers(); after your imports
...
jest.useFakeTimers();
test('demo code', async () => {
const cc = await projectSetup(project);
const onNotification = jest.fn();
cc.sendNotification();
await waitForExpect(() => {
expect(onNotification).toHaveBeenCalledTimes(2);
});
});
it works in my code
In my case, the actual problem was with the promise handling.
I got the same issue when I was running all my test cases in one go with the jest.
Solution:
Try running one test separately then see what error is coming.
I got the below error after running one problematic test separately where earlier I was getting the Call retries were exceeded:
[UnhandledPromiseRejection: This error originated either by throwing inside of an async function without a catch block or by rejecting a promise which was not handled with .catch(). The promise rejected with the reason "TypeError: Cannot read property 'code' of undefined".] {
code: 'ERR_UNHANDLED_REJECTION'
}
With this, I was sure that the problem is with the catch block and when I added it in the async service API function then the test case worked perfectly fine.
Maybe you can also try the same and see if it works for you or not.
I am using the below config:
node: 15.13.0
npm: 7.8.0
jest: 26.6.3
Try running npm doctor using the latest npm version. It's a great tool and it helped me diagnose permission and ownership issues right away.
Takeaway:
Verify File/Folder Permissions & Ownership
Encountered same error when updating the vue-jest version to below listed versions
#vue/vue3-jest: ^27.0.0-alpha.4
#vue/cli-plugin-unit-jest: ~5.0.0,
node: v17.9.0 or v16.14.2
Error disappeared, once downgraded it to node version v14.x.x
Hunch is - the latest node versions are not compatible with the dependencies.
I was able to run the test's successfully doing the following;
Install npm i -D jest-canvas-mock
Update the jest.config.ts file to have:
export default {
...
testEnvironment: "jsdom",
setupFiles: ["jest-canvas-mock"],
}

"fetch is not found globally and no fetcher passed" when using spacejam in meteor

I'm writing unit tests to check my api. Before I merged my git test branch with my dev branch everything was fine, but then I started to get this error:
App running at: http://localhost:4096/
spacejam: meteor is ready
spacejam: spawning phantomjs
phantomjs: Running tests at http://localhost:4096/local using test-in-console
phantomjs: Error: fetch is not found globally and no fetcher passed, to fix pass a fetch for
your environment like https://www.npmjs.com/package/unfetch.
For example:
import fetch from 'unfetch';
import { createHttpLink } from 'apollo-link-http';
const link = createHttpLink({ uri: '/graphql', fetch: fetch });
Here's a part of my api.test.js file:
describe('GraphQL API for users', () => {
before(() => {
StubCollections.add([Meteor.users]);
StubCollections.stub();
});
after(() => {
StubCollections.restore();
});
it('should do the work', () => {
const x = 'hello';
expect(x).to.be.a('string');
});
});
The funniest thing is that I don't even have graphql in my tests (although, I use it in my meteor package)
Unfortunately, I didn't to find enough information (apart from apollo-link-http docs that has examples, but still puzzles me). I did try to use that example, but it didn't help and I still get the same error
I got the same error importing a npm module doing graphql queries into my React application. The app was compiling but tests were failing since window.fetch is not available in the Node.js runtime.
I solved the problem by installing node-fetch https://www.npmjs.com/package/node-fetch and adding the following declarations to jest.config.js:
const fetch = require('node-fetch')
global.fetch = fetch
global.window = global
global.Headers = fetch.Headers
global.Request = fetch.Request
global.Response = fetch.Response
global.location = { hostname: '' }
Doing so we instruct Jest on how to handle window.fetch when it executes frontend code in the Node.js runtime.
If you're using nodejs do the following:
Install node-fetch
npm install --save node-fetch
Add the line below to index.js:
global.fetch = require('node-fetch');
The problem is this: fetch is defined when you are in the browser, and is available as fetch, or even window.fetch
In the server it is not defined, and either needs to be imported explicity, or a polyfill like https://www.npmjs.com/package/unfetch (as suggested in the error message) needs to be imported by your test code to make the problem go away.

Categories