Ever since AWS made a serverless option of AWS RDS Aurora generally available, I've been on the edge of my seat, eagerly anticipating all the vario...
For further actions, you may consider blocking this person and/or reporting abuse
Hey Adnan. Thank you so much for taking the time to develop this example. How would you introduce another model to this solution? Set's say I wanted to add UsersModel. I've created the users.js within the models directory. the db.js you have only passes in one model ( const Models = { Note }) could that be an array of models? const Models = [Note, User, etc]? If so how does the handler.js know which model?
Add another model to the object.
In db.js:
Once you want to require the models in the handler.js you can choose which one you want.
It's up to you to use what you like more. I personally think destructuring is freaking awesome. :)
Thanks so much, I'll try the above. thanks again
What do you mean with destructuring?
Object destructuring
Last question, what would be the best way to associate those two tables? I've found many examples, but it would require a refactoring of the model's .js file.
To install mysql locally on a mac (mojave):
brew install mysql@5.7 to install an older version of mysql. Then everything works fine locally.
To answer Weiren's question:
in the secrets.json file:
"DB_HOST": "superdupercluster.cluster-.rds.amazonaws.com"
Fixes the connection refused issue you are seeing, as 127.0.0.1 works for the local machine, but not for whatever machine that the Lambda function runs on.
However, now I am getting the same issue as sobhanthankur:
{
"errorType": "SequelizeConnectionError",
"errorMessage": "Unknown database 'test'",
"trace": [
"SequelizeConnectionError: Unknown database 'test'",
" at Promise.tap.then.catch.err (/var/task/node_modules/sequelize/lib/dialects/mysql/connection-manager.js:133:19)",
" at tryCatcher (/var/task/node_modules/bluebird/js/release/util.js:16:23)",
" at Promise._settlePromiseFromHandler (/var/task/node_modules/bluebird/js/release/promise.js:517:31)",
" at Promise._settlePromise (/var/task/node_modules/bluebird/js/release/promise.js:574:18)",
" at Promise._settlePromise0 (/var/task/node_modules/bluebird/js/release/promise.js:619:10)",
" at Promise._settlePromises (/var/task/node_modules/bluebird/js/release/promise.js:695:18)",
" at _drainQueueStep (/var/task/node_modules/bluebird/js/release/async.js:138:12)",
" at _drainQueue (/var/task/node_modules/bluebird/js/release/async.js:131:9)",
" at Async._drainQueues (/var/task/node_modules/bluebird/js/release/async.js:147:5)",
" at Immediate.Async.drainQueues as _onImmediate",
" at runCallback (timers.js:705:18)",
" at tryOnImmediate (timers.js:676:5)",
" at processImmediate (timers.js:658:5)"
]
}
Do we need to initialize the Aurora database and create the database named 'test' first, and then Sequelize will automatically create the notes table in that database for us? Or is there a missing permission for the lambda role/policy?
Yes, you need to create it manually. I mentioned it in the article:
I've yet to find the free time to explore the Lambda role/policy to let Sequelize create it automatically. But, I'd ideally not want my Lambda role to have access to create/delete/edit databases. It could end badly. Only letting them change the data is a bit more safe for my liking.
Hello.
Did you solve the issue?
Could you help me to solve this issue?
Hi Adnan, Thank you so much with your wonderful article. I did exactly same as it till doing offline test. I got an issue which it can not connect to the Aurora DB. The things I have tried is :
What I missed during the process that cause the issue?
In the secrets.json file, What should be changed according to my RDS configuration ( especially DB_HOST and DB_NAME)
Had the same exact issue and as someone with a mac with no mysql installed this was the solution for me. Remember a local instance of mysql needs to still be available.
Install mysql locally
brew install mysql
Start MySQL
mysql.server start OR service mysqld start
Make change to user auth
Per stack overflow need to edit password auth
mysql -u root
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'password'
mysql -u root -p
"password"
Make sure to change the db.js DB_PASSWORD
db.js
"DB_PASSWORD": "password"
and voila it worked for me
Hi Adnan,
Great work buddy!
I just got one question - how would you associate another model to the Note model?
Let's say we have a User model and we would like to implement Note.belongsTo(User).
I have made something like this but it keeps me getting an error like "note is not associated to user"
const User = require('./User');
module.exports = (sequelize, type) => {
const Note = sequelize.define('note', {
id: {
type: type.INTEGER,
primaryKey: true,
autoIncrement: true
},
title: type.STRING,
description: type.STRING
})
}
Hi @softnayr were you able to solve the "note is not associated to user" issue
Hey Adnan. Can you please explain a little how database connections in serverless framework work? More specifically how many database connections would your code create if you call the same endpoint multiple time and if you call the same endpoint from two different source simultaneously.
I have a serverless project integrated with express and sequelize, such that a single lambda has multiple routes. The F.E calls 6 api end points for different graphs simultaneously. My code create 6 connections instead of one, and the CPU utilization on my RDS instance goes up to 60-80% :| ...
This is a cool question. The keyword here is simultaneously. This has nothing to do with the Serverless Framework, and everything to do with the way AWS Lambda works under the hood.
When your front end sends 6 concurrent requests to a Lambda function, it will spawn 6 instances and every instance will handle one request. If you were to send 6 requests sequentially, one instance would be enough.
Because, in this case, you have 6 Lambda function instances, every one of those will create a database connection. Makes sense?
The way to handle this is to have one Lambda function dedicated to only database interaction, while the other act as proxies. This is very hard to configure. I'd suggest you use a serverless database that can scale as easily as Lambda. :)
Very cool question, feel free to hit me up through the chat here in dev.to if you have any more topics like these. I'd love to nerd out.
Can somebody please help me out with this error
{
"errorType": "SequelizeConnectionError",
"errorMessage": "Unknown database 'test_aurora'",
"trace": [
"SequelizeConnectionError: Unknown database 'test_aurora'",
" at Promise.tap.then.catch.err (/var/task/node_modules/sequelize/lib/dialects/mysql/connection-manager.js:133:19)",
" at tryCatcher (/var/task/node_modules/bluebird/js/release/util.js:16:23)",
" at Promise._settlePromiseFromHandler (/var/task/node_modules/bluebird/js/release/promise.js:517:31)",
" at Promise._settlePromise (/var/task/node_modules/bluebird/js/release/promise.js:574:18)",
" at Promise._settlePromise0 (/var/task/node_modules/bluebird/js/release/promise.js:619:10)",
" at Promise._settlePromises (/var/task/node_modules/bluebird/js/release/promise.js:695:18)",
" at _drainQueueStep (/var/task/node_modules/bluebird/js/release/async.js:138:12)",
" at _drainQueue (/var/task/node_modules/bluebird/js/release/async.js:131:9)",
" at Async._drainQueues (/var/task/node_modules/bluebird/js/release/async.js:147:5)",
" at Immediate.Async.drainQueues as _onImmediate",
" at runCallback (timers.js:705:18)",
" at tryOnImmediate (timers.js:676:5)",
" at processImmediate (timers.js:658:5)"
]
}
I answered this question here:
Yes, you need to create it manually. I mentioned it in the article:
I've yet to find the free time to explore the Lambda role/policy to let Sequelize create it automatically. But, I'd ideally not want my Lambda role to have access to create/delete/edit databases. It could end badly. Only letting them change the data is a bit more safe for my liking.
You need to manually connect to the Aurora cluster and create a database.
Hey Adnan, I'm trying to query the database using
const user = await User.findAll({
where: {
user_email: event.pathParameters.user_email
}
The event.pathParameters.user_email has a %40 instead of the @ symbol.
any suggestions?
Hi Adnan!
Thanks for this amazing guide.
I wanted to ask if, performance-wise, it is fine to require "db" into every lambda function?
As far as I am aware of Sequelize (and my knowledge is limited) whenever we run an express app having models created using Sequelize, it first checks if all tables exist, and if they don't it creates them first.
Isn't it overhead in every lambda execution?
Let me know if I am mistaken.
Thank You again for this awesome post :)
Hello Adnan, I am getting this error while connecting to database!
Serverless: Failure: connect ETIMEDOUT
SequelizeConnectionError: connect ETIMEDOUT
at Promise.tap.then.catch.err (D:\litmus-workspace\litmus-serverless\node_modules\sequelize\lib\dialects\mysql\connection-manager.js:133:19)
at tryCatcher (D:\litmus-workspace\litmus-serverless\node_modules\bluebird\js\release\util.js:16:23)
at Promise._settlePromiseFromHandler (D:\litmus-workspace\litmus-serverless\node_modules\bluebird\js\release\promise.js:517:31)
at Promise._settlePromise (D:\litmus-workspace\litmus-serverless\node_modules\bluebird\js\release\promise.js:574:18)
at Promise._settlePromise0 (D:\litmus-workspace\litmus-serverless\node_modules\bluebird\js\release\promise.js:619:10)
at Promise._settlePromises (D:\litmus-workspace\litmus-serverless\node_modules\bluebird\js\release\promise.js:695:18)
at _drainQueueStep (D:\litmus-workspace\litmus-serverless\node_modules\bluebird\js\release\async.js:138:12)
at _drainQueue (D:\litmus-workspace\litmus-serverless\node_modules\bluebird\js\release\async.js:131:9)
at Async._drainQueues (D:\litmus-workspace\litmus-serverless\node_modules\bluebird\js\release\async.js:147:5)
at Immediate.Async.drainQueues as _onImmediate
at runCallback (timers.js:705:18)
at tryOnImmediate (timers.js:676:5)
at processImmediate (timers.js:658:5)
at process.topLevelDomainCallback (domain.js:120:23)
I have exactly followed your steps but I am getting this error. My database inbound traffic is set to all but still I am getting this error. I was able to connect to my database through SSH tunneling.
Hello Virendra,
Good morning.
Have you resolved this issue? Please let me know.
Thanks,
Rohan.
I need a boilerplate with AWS Node.js Lambda, AWS Cognito, JWT, MongoDB, Cloudformation for user authentication and authorization
dev.to/realpchauhan/user-authentic...
Hey Adnan,
Great tutorial!!
Just wondered if you have any experience with that Lambda consistently timeout, although i get a db connection its keeps timing out and never returns anything? (input from other are of-course welcome to :) )
Hi Adnan. thanx for sharing. it's very useful. at work we recently ported an app from php to react + cognito + gateway + lambda + vpc to connect to a Vertica DB and just started moving to Aurora Serverless.
can i ask why you are add in msql2 in the package.json? i couldn't see it used in the code. maybe is a necessary peer dependency for Sequelize as soon as you define the dialect you want to use?
Hello Adnan,
Thank you for this article which has given me a really great start.
The steps which you wrote worked really good until I tried to connect publish SNS message to a topic
After little research I figured out that as we are putting the lambda in Aurora's serverless VPC it is not allowing me connect to any internet facing external services.
Can you suggest me a solution ?
Cheers
What do you think is the best way to add parameter validation for POST/PUT calls in this example? Also is there any testing library you would recommend?
Thanks for the great tutorial!
After deploying and test the endpoints, the response was 502 Bad Gateway. How can we be able to address this one?
Is there a reason why you don't create the aurora database with cloudformation?