Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

async/await syntax in lambda not working #100

Closed
2 tasks done
fredericbarthelet opened this issue Oct 6, 2020 · 5 comments
Closed
2 tasks done

async/await syntax in lambda not working #100

fredericbarthelet opened this issue Oct 6, 2020 · 5 comments
Labels
bug This issue is a bug. closed-for-staleness response-requested Waiting on additional info and feedback. Will move to "closing-soon" in 2 days.

Comments

@fredericbarthelet
Copy link

fredericbarthelet commented Oct 6, 2020

I found a similar issue but the symptoms look different #58

Known Issue

  • I'm using ATS data type endpoint: the endpoint should look like <prefix>-ats.iot.<region>.amazonaws.com

Describe the bug
Using aws-iot-device-sdk-js-v2 within the context of an AWS lambda with async/await syntax does not work. await statements for connection.connect(), identity.subscribeToCreateCertificateFromCsrAccepted, identity.subscribeToCreateCertificateFromCsrRejected and identity.publishCreateCertificateFromCsr seems ineffective.

SDK version number
1.3.1

Platform/OS/Hardware/Device
AWS lambda on nodejs12.x runtime, no custom layer

To Reproduce (observed behavior)

Deploying the following code to a lambda :

'use strict';

// NOTE: `aws-iot-device-sdk-v2` is bundled into the deployment package
// eslint-disable-next-line import/no-unresolved
const { mqtt, io, iot, iotidentity } = require('aws-iot-device-sdk-v2');

async function registerDevice(event) {
  io.enable_logging(io.LogLevel.INFO);
  const clientBootstrap = new io.ClientBootstrap();
  const client = new mqtt.MqttClient(clientBootstrap);

  const configBuilder = iot.AwsIotMqttConnectionConfigBuilder.new_mtls_builder(
    event.certificatePem,
    event.keyPair.PrivateKey
  );
  configBuilder.with_clean_session(false);
  configBuilder.with_client_id(`test-${Math.floor(Math.random() * 100000000)}`);
  configBuilder.with_endpoint('xxxxINTENTIONALLY_ANONYMISEDxxx-ats.iot.us-east-1.amazonaws.com');
  const config = configBuilder.build();

  const connection = client.new_connection(config);

  const identity = new iotidentity.IotIdentityClient(connection);

  await new Promise(resolve => setTimeout(resolve, 3000));

  console.log('waited 3 seconds')

  await connection.connect();

  console.log('connected')

  await identity.subscribeToCreateCertificateFromCsrAccepted({}, mqtt.QoS.AtLeastOnce);

  await identity.subscribeToCreateCertificateFromCsrRejected({}, mqtt.QoS.AtLeastOnce);

  await identity.publishCreateCertificateFromCsr({ csr: '' }, mqtt.QoS.AtLeastOnce);

  return 'success';
}

Running the lambda with response of createProvisioningClaim as input event prints the waited 3 seconds statement - showing async/await does seems to work, no syntax error there - but not the connected statement. A few info statement are shown, showing execution of connect did in fact started. However, the lambda runs just over 3s (the timeout period) and then resolve. No success string is returned from the lambda execution.

Running the same code on my machine nodejs runtime shows no problem at all.

Expected behavior
Resolving promises from connection.connect() and other asynchronous calls.

Logs/output
image

Additional context
The reason for executing this code in an lambda environment is for integration testing purposes.
Currently developing iot fleet provisioning pre-provision lambda hook as part of Serverless framework feature.
Lambda aims to simulate a device requesting provisioning via template provisioning feature (CSR) on a freshly deployed CloudFormation stack.

Current state of the PR : serverless/serverless#8324

@fredericbarthelet fredericbarthelet added bug This issue is a bug. needs-triage This issue or PR still needs to be triaged. labels Oct 6, 2020
@RianFuro
Copy link

RianFuro commented Feb 1, 2021

Huh, I'm facing a similar issue right now, in a different context. The call to await connection.connect() does not resolve for me, UNLESS express starts.

In essence, this works:

const app = express()
app.listen(port, () => {
    console.log(`Server is up at port ${port}`)
    connection.connect().then(() => console.log('connected!'))
});

while this does not:

const app = express()
connection.connect().then(() => {
    console.log('connected!')
    app.listen(port, () => {
       console.log(`Server is up at port ${port}`)
    });
})

In the latter case the promise returned from connection.connect() never resolves, the then callback is never called.
Removing express from my application does not solve the issue, so I don't believe it's the cause. Also, no error is raised from a promise rejection.

I'm working on my local environment:
Arch Linux 5.9.14-arch1-1
nodejs v15.5.0
"express": "^4.17.1",
"aws-iot-device-sdk-v2": "^1.3.6",
"aws-crt": "^1.3.8",

@JonathanHenson
Copy link
Contributor

I think the issue is most likely because connection.connect() does not take a reference to the V8 event-loop and when the line app.listen is executed asynchronously all references are gone and the application completes before the connection.connect() has had a chance to run.

You see the reverse behavior in the 2nd option, because app.listen takes a reference to the event-loop when the closure is created, and thus it keeps the application alive until after the connection completes.

One easy work around is to throw a timer into the application (or a loop or something)

@RianFuro
Copy link

RianFuro commented Feb 1, 2021

@JonathanHenson My application doesn't terminate though. In both cases the application stays alive, but in the first case, the promise from connection.connect() resolves (the log in the following statement is printed), while in the second it doesn't.
nvm me, it does actually terminate. So yeah, that's exactly what happens. Thanks!

@jmklix
Copy link
Member

jmklix commented Aug 9, 2021

@fredericbarthelet when using the latest version of the sdk are you still not able the use async/await in lambdas?

@jmklix jmklix added response-requested Waiting on additional info and feedback. Will move to "closing-soon" in 2 days. and removed needs-triage This issue or PR still needs to be triaged. labels Aug 9, 2021
@github-actions
Copy link

Greetings! It looks like this issue hasn’t been active in longer than a week. We encourage you to check if this is still an issue in the latest release. Because it has been longer than a week since the last update on this, and in the absence of more information, we will be closing this issue soon. If you find that this is still a problem, please feel free to provide a comment or add an upvote to prevent automatic closure, or if the issue is already closed, please feel free to open a new one.

@github-actions github-actions bot added closing-soon This issue will automatically close in 5 days unless further comments are made. closed-for-staleness and removed closing-soon This issue will automatically close in 5 days unless further comments are made. labels Aug 16, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug This issue is a bug. closed-for-staleness response-requested Waiting on additional info and feedback. Will move to "closing-soon" in 2 days.
Projects
None yet
Development

No branches or pull requests

4 participants