Tabla de Contenidos
En abril de 2021 AWS lanzó la posibilidad para que desde una instancia de RDS PostgreSQL se pueden hacer invocaciones a funciones Lambda. Una función Lambda nos permite ejecutar código sin tener que aprovisionar o manejar servicios y sin preocuparnos por la escalabilidad. Anteriormente escribí como crear una función lambda con Java y pueden encontrar el artículo aquí.
Gracias a este nuevo lanzamiento nos resulta posible invocar funciones Lambda directamente desde una base de datos de Amazon RDS para PostgreSQL; ya sea a través de procedimientos almacenados o funciones definidas por el usuario. Esto nos permite ampliar las capacidades de la base de datos e invocar aplicaciones externas para actuar sobre los cambios de datos.
Por ejemplo, podemos invocar una función Lambda que envié correos electrónicos por medios de SES cuando se registra un cambio en la base de datos; o quizás enviar un mensaje a una cola de SQS.
Las posibilidades son ilimitadas.
Este este artículo vamos a hacer un ejercicio al respecto, primeramente debemos saber que necesitamos estar usando al menos la versión 12.6 o la 13.2 en adelante de PostgreSQL; para nuestro ejemplo usaremos la versión 13.2-R1.
Prerrequisitos
Seguidamente abordaremos los prerrequisitos que debemos hacer para poder ejecutar nuestro Lambda desde PostgreSQL.
Extensión en PostgreSQL
El primer paso que debemos hacer es instalar una nueva extensión en nuestra base de datos.
CREATE EXTENSION IF NOT EXISTS aws_lambda CASCADE;
El resultado debe ser exitoso y además nos indica que se agrega una extensión adicional que es aws_commons
.
Función Lambda
El siguiente paso es tener una función Lambda ya disponible para usar, de ella debemos tomar nota del nombre (o su ARN, versión o alias). Como se aprecia en la siguiente imagen, en nuestro caso el ARN es: arn:aws:lambda:us-east-1:338068911589:function:DemoLambda
Política de IAM
Ahora debemos dar permisos a RDS para que pueda invocar nuestra Lambda. Así que debemos crear una política de IAM que da permisos de ejecución a nuestra función; observen que usamos el ARN del cual tomamos nota antes.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": "lambda:InvokeFunction",
"Resource": "arn:aws:lambda:us-east-1:338068911589:function:DemoLambda"
}
]
}
En mi caso a esta política le puse el nombre RDS-Lambda-Policy; como se ilustra de seguido.
Debemos tomar nota del ARN de está política y que en mi ejemplo es: arn:aws:iam::338068911589:policy/RDS-Lambda-Policy.
Rol de IAM
Continuamos creando un rol de IAM. Este rol será asumido por RDS para ejecutar la función Lambda y este sería creado desde el CLI de esta manera:
aws iam create-role --role-name rds-lambda-role --assume-role-policy-document '{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "rds.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}'
Debemos asociar nuestra política a este rol; como vemos en la siguiente imagen:
El resultado sería este:
Asignar el Rol a RDS
El último paso de preparación es asignar este rol rds-lambda-role
a nuestra instancia de RDS. Esto lo hacemos en Manage IAM Roles
de nuestra instancia. Es importante que en feature
se seleccione Lambda.
Debemos esperar algunos minutos a que el role este asociado y activo.
Demostración
Luego de todo lo anterior; llego el momento de poder ejecutar nuestra función desde PostgreSQL.
Esto se hace por medio de la función aws_lambda.invoke
, como se ilustra de seguido:
SELECT * FROM aws_lambda.invoke(aws_commons.create_lambda_function_arn('DemoLambda', 'us-east-1'),
'{"name": "Gerardo",
"greeting": "Hola"}'::json
);
y obtenemos nuestra respuesta exitosa!
Observen que dado que la ejecución fue sincrónica, tenemos acceso a la respuesta que nos da el Lambda. Por tanto, podemos usar esa respuesta para implementar lógica adicional en un procedimiento almacenado o función.
Si revisamos en la consola de Lambda, veremos nuestras invocaciones reflejadas en las métricas.
Ahora, desglosemos esta invocación.
SELECT * FROM aws_lambda.invoke(aws_commons.
create_lambda_function_arn('DemoLambda', 'us-east-1'),
'{"name": "Gerardo",
"greeting": "Hola"}'::json
);
Notaran que el aws_lambda.invoke
tiene como primer parámetro una estructura aws_commons._lambda_function_arn_1
. Para obtenerla debemos usar la función create_lambda_function_arn
de la extensión aws_commons
. Esta recibe dos parámetros: el nombre, ARN o versión de la función y la región donde esta alojada.
Entonces, podemos usar varias maneras para obtener una estructura aws_commons._lambda_function_arn_1
; ya sea por nombre:
SELECT aws_commons.create_lambda_function_arn(
'DemoLambda',
'us-east-1'
)
o bien por ARN
SELECT aws_commons.create_lambda_function_arn(
'arn:aws:lambda:us-east-1:338068911589:function:DemoLambda',
'us-east-1'
)
¿Podría ejecutar el Lambda de manera asincrónica?
Y la respuesta es afirmativa y con un simple ajuste: agregar a la invocación un tercer parámetro ‘Event’
SELECT * FROM aws_lambda.invoke(aws_commons.create_lambda_function_arn('DemoLambda', 'us-east-1'),
'{"name": "Gerardo",
"greeting": "Hola"}'::json,
'Event'
);
Observen que no tenemos el resultado de la ejecución, así que podemos hacer uno de este tipo de llamada cuando no necesitamos conocer la respuesta del Lambda.
¿Y el Rollback?
Algo importante que deben considerar; imaginen que tienen un procedimiento almacenado que realiza un proceso determinado y uno de sus pasos es llamar a un Lambda. Supongamos que ya ejecutó ese paso y en los subsiguientes hay un error y por tanto se genera un rollback de la base de datos.
No olviden que a nivel de la BD el rollback fue exitoso y pero el Lambda si se ejecutó y RDS no es responsable por hacer un rollback de esa Lambda.
Es nuestra responsabilidad que invoquemos un proceso que reverse o compense de manera lógica lo que haya hecho esa función.
Por ejemplo: si el lambda enviaba un correo de confirmación, nuestra compensación quizás sea otro correo para indicar que se omita el previo.
Conclusión
Espero que este artículo les haya sido de utilidad y que se animen a realizar algunas pruebas con PostgreSQL y Lambdas; especialmente si forman parte de los proyectos en los cuales estén trabajando.
Inicia la conversación