Tema
📓 Clase 6 — Arquitectura orientada a eventos
Curso AWS (emulador Floci) · 2026-08-09 · Carpeta:
02-Ejercicios/clase-06-eventos⬅️ Volver al índice de clases
🎯 Qué aprendí
- Qué significa que los servicios no se llamen entre sí y por qué eso cambia todo.
- Las tres formas de conectar: notificación directa, cola, y publicar/suscribir.
- SQS para desacoplar: qué pasa cuando el consumidor está caído.
- SNS para avisar a varios a la vez sin que el emisor los conozca.
- EventBridge como bus central con filtrado por contenido.
- Robustez: reintentos, colas de mensajes muertos y qué hacer con lo que falla siempre.
📖 PARTE TEÓRICA
🔀 1. Nadie llama a nadie
En el backend de CENATE, cuando pasa algo, alguien llama a alguien: un servicio invoca a otro, y si el segundo está caído, el primero falla también.
En una arquitectura de eventos, los servicios anuncian que algo pasó y se desentienden:
ACOPLADO (llamada directa) POR EVENTOS
────────────────────────── ───────────
ServicioA ──llama──▶ ServicioB ServicioA ──publica──▶ [ EVENTO ]
│ │
si B esta caido, ┌───────────┼───────────┐
A falla tambien ▼ ▼ ▼
ServicioB ServicioC ServicioD
✗ A debe conocer a B
✗ A espera a B ✓ A no sabe quien escucha
✗ agregar C = tocar A ✓ si B esta caido, el evento espera
✓ agregar D no toca A💡 La prueba de fuego: ¿puedes añadir un consumidor nuevo sin tocar el emisor? Si sí, está bien desacoplado. Si hay que modificar quien emite, sigues acoplado.
📬 2. Las tres formas de conectar
| Cómo funciona | Cuándo usarlo | |
|---|---|---|
| Notificación (S3 → Lambda) | El servicio avisa directamente a un destino | Una fuente, un destino, reacción inmediata |
| Cola (SQS) | El mensaje espera hasta que alguien lo recoge | El consumidor puede tardar, fallar o no estar |
| Publicar/suscribir (SNS) | Un mensaje llega a todos los suscritos | Varios interesados en lo mismo |
| Bus (EventBridge) | Reglas que filtran por contenido y enrutan | Muchos tipos de evento, muchos destinos |
📮 3. La cola: el amortiguador
Una cola convierte un problema de disponibilidad en un problema de tiempo:
productor ──▶ [ m1 m2 m3 m4 ] ──▶ consumidor
la cola │
si esta caido,
los mensajes ESPERAN
(hasta 14 dias)Dos mecanismos hacen que funcione sin coordinación:
- Tiempo de invisibilidad: al recoger un mensaje, desaparece para los demás durante N segundos (30 por defecto). Si el consumidor lo procesa y lo borra, se acabó. Si muere antes, el mensaje reaparece y otro lo intenta.
- Sondeo largo: en vez de preguntar mil veces por segundo, el consumidor espera hasta N segundos a que llegue algo. Menos llamadas, menos coste.
⚠️ Recoger no es borrar. Si no llamas a
delete-message, el mensaje vuelve a la cola al expirar la invisibilidad. Es un fallo clásico: la función procesa lo mismo una y otra vez.
📢 4. Publicar/suscribir: uno a muchos
SQS entrega cada mensaje a un consumidor. SNS lo entrega a todos los suscritos:
┌──▶ cola de facturacion
publicar ──▶ TEMA ──┼──▶ cola de notificaciones
└──▶ funcion de auditoriaEl emisor no sabe cuántos hay ni quiénes son. Añadir un cuarto suscriptor no toca su código.
💡 El patrón más habitual es SNS delante de varias SQS: el tema reparte, y cada cola amortigua a su consumidor. Se llama fan-out.
🚌 5. El bus: enrutar por contenido
EventBridge va un paso más allá: las reglas miran dentro del evento y deciden a dónde va.
json
{
"source": "cenate.citas",
"detail-type": "CitaCreada",
"detail": { "dni": "12345601", "especialidad": "Cardiologia" }
}Una regla con el patrón {"source": ["cenate.citas"]} captura ese evento; otra con {"detail": {"especialidad": ["Cardiologia"]}} captura solo las de esa especialidad. El emisor publica una vez y el bus reparte según reglas que se cambian sin tocarlo.
🛡️ 6. Qué pasa cuando algo falla siempre
Un mensaje que hace fallar al consumidor volverá una y otra vez, bloqueando la cola. La solución es la cola de mensajes muertos:
cola principal ──▶ consumidor ✗ falla
│ reaparece ✗ falla
│ reaparece ✗ falla ← intento 3
▼
COLA DE MENSAJES MUERTOS ← se aparta para revisarlo a manoSe configura con RedrivePolicy y un maxReceiveCount. Sin ella, un solo mensaje defectuoso puede parar todo el procesamiento.
💻 PARTE PRÁCTICA
bash
floci start
eval $(floci env)La cadena que ya montaste en el laboratorio, ahora entendiéndola por dentro:
aws s3 cp informe.txt s3://documentos/
│
▼
┌────────────┐ evento s3:ObjectCreated:*
│ S3 │ ──────────────┐
└────────────┘ ▼
┌─────────────┐
│ LAMBDA │
└──────┬──────┘
┌─────────────┴─────────────┐
▼ ▼
┌────────────┐ ┌────────────┐
│ DYNAMODB │ │ SQS │
└────────────┘ └────────────┘$ for i in 1 2 3; do aws sqs send-message --queue-url $Q --message-body "cita-$i"; done
$ sleep 15 && aws sqs get-queue-attributes --queue-url $Q \
--attribute-names ApproximateNumberOfMessages --query 'Attributes.*' --output text
0
[esm] recibido: cita-1
[esm] recibido: cita-2
[esm] recibido: cita-3Nadie invocó la función: la vació el disparador que conecta la cola con ella.
🏋️ EJERCICIOS CON SOLUCIÓN
🟢 Nivel 1 — El evento más simple: S3 dispara una función (1-8)
Ejercicio 1 — Crear la función que reacciona
Crea una función que registre en sus logs el nombre del archivo que la despertó.
💡 ¿Sabías que…? — el evento de S3 trae la ruta
Llega en event["Records"][0]["s3"]["object"]["key"]. La clave viene codificada como URL: los espacios aparecen como + y hay que decodificarlos.
python
# ejemplo de referencia
import urllib.parse
clave = urllib.parse.unquote_plus(record["s3"]["object"]["key"])Ver solución
python
import json, urllib.parse
def lambda_handler(event, context):
for r in event.get("Records", []):
clave = urllib.parse.unquote_plus(r["s3"]["object"]["key"])
print(f"[lab] llego: {clave}")
return {"n": len(event.get("Records", []))}Ejercicio 2 — Crear el bucket
Crea ej02-documentos.
💡 ¿Sabías que…? — el bucket debe existir antes del disparador
La configuración de notificaciones se guarda en el bucket. No se puede configurar sobre algo que no existe.
bash
# ejemplo de referencia
aws s3 mb s3://otro-bucketVer solución
bash
aws s3 mb s3://ej02-documentosEjercicio 3 — Dar permiso a S3
Autoriza a S3 a invocar tu función.
💡 ¿Sabías que…? — sin esto no pasa nada, y sin error
Es la trampa más costosa de toda la arquitectura de eventos: sin permiso, S3 simplemente no llama, y no queda rastro en ningún registro.
bash
# ejemplo de referencia
aws lambda add-permission --function-name otra --statement-id s3 \
--action lambda:InvokeFunction --principal s3.amazonaws.com \
--source-arn arn:aws:s3:::otro-bucketVer solución
bash
aws lambda add-permission --function-name ej01-fn --statement-id s3invoke \
--action lambda:InvokeFunction --principal s3.amazonaws.com \
--source-arn arn:aws:s3:::ej02-documentosEjercicio 4 — Conectar el disparador
Configura el bucket para que avise a la función cuando se cree un objeto.
💡 ¿Sabías que…? — se puede filtrar por tipo de evento
s3:ObjectCreated:* cubre subidas y copias. También existen s3:ObjectRemoved:* y filtros por prefijo o sufijo, para reaccionar solo a ciertos archivos.
bash
# ejemplo de referencia — solo los .pdf
# "Filter": {"Key": {"FilterRules": [{"Name":"suffix","Value":".pdf"}]}}Ver solución
bash
aws s3api put-bucket-notification-configuration --bucket ej02-documentos \
--notification-configuration '{"LambdaFunctionConfigurations":[{
"LambdaFunctionArn":"arn:aws:lambda:us-east-1:000000000000:function:ej01-fn",
"Events":["s3:ObjectCreated:*"]}]}'Ejercicio 5 — Dispararlo
Sube un archivo y comprueba que la función se ejecutó.
💡 ¿Sabías que…? — la cadena es asíncrona
aws s3 cp devuelve en cuanto S3 acepta el archivo, sin esperar a la función. Puede tardar unos segundos en aparecer el registro.
bash
# ejemplo de referencia
echo hola > a.txt && aws s3 cp a.txt s3://otro-bucket/Ver solución
bash
echo "informe" > informe.txt
aws s3 cp informe.txt s3://ej02-documentos/
sleep 8Ejercicio 6 — Leer los registros
Encuentra la línea que dejó la función.
💡 ¿Sabías que…? — el emulador ordena mal los streams
--order-by LastEventTime --descending se ignora y devuelve el más antiguo. Hay que coger el último de la lista con logStreams[-1].
bash
# ejemplo de referencia
aws logs describe-log-streams --log-group-name /aws/lambda/otra \
--query 'logStreams[-1].logStreamName' --output textVer solución
bash
G=/aws/lambda/ej01-fn
S=$(aws logs describe-log-streams --log-group-name $G \
--query 'logStreams[-1].logStreamName' --output text)
aws logs get-log-events --log-group-name $G --log-stream-name "$S" \
--query 'events[*].message' --output text | grep '\[lab\]'
# [lab] llego: informe.txtEjercicio 7 — Comprobar el desacoplamiento
Sube dos archivos seguidos y cuenta las invocaciones.
💡 ¿Sabías que…? — un evento por objeto
Cada objeto genera su propio evento. Subir diez archivos son diez invocaciones, posiblemente en paralelo.
bash
# ejemplo de referencia
for i in 1 2; do echo $i > f$i.txt && aws s3 cp f$i.txt s3://otro-bucket/; doneVer solución
bash
for i in 1 2; do echo "doc $i" > d$i.txt; aws s3 cp d$i.txt s3://ej02-documentos/; done
sleep 10
# dos lineas [lab] llego: en los registrosEjercicio 8 — Quitar el disparador
Elimina la notificación y comprueba que ya no reacciona.
💡 ¿Sabías que…? — una configuración vacía la borra
No hay comando de borrado: se envía una configuración vacía, que sustituye a la anterior.
bash
# ejemplo de referencia
aws s3api put-bucket-notification-configuration --bucket otro --notification-configuration '{}'Ver solución
bash
aws s3api put-bucket-notification-configuration --bucket ej02-documentos \
--notification-configuration '{}'
echo x > x.txt && aws s3 cp x.txt s3://ej02-documentos/
# ya no aparece ninguna linea nueva en los registros🔵 Nivel 2 — La cola: SQS (9-16)
Ejercicio 9 — Crear una cola
Crea ej09-cola y guarda su URL.
💡 ¿Sabías que…? — la cola se identifica por URL, no por nombre
Casi todos los comandos piden --queue-url. El nombre solo sirve para obtenerla la primera vez con get-queue-url.
bash
# ejemplo de referencia
Q=$(aws sqs create-queue --queue-name otra --query QueueUrl --output text)Ver solución
bash
Q=$(aws sqs create-queue --queue-name ej09-cola --query QueueUrl --output text)
echo "$Q"Ejercicio 10 — Enviar y recibir
Envía un mensaje y recógelo.
💡 ¿Sabías que…? — recibir no borra
El mensaje se vuelve invisible durante 30 segundos. Si no lo borras, reaparece. Es a propósito: garantiza que nada se pierde si el consumidor muere.
bash
# ejemplo de referencia
aws sqs send-message --queue-url $Q --message-body "prueba"
aws sqs receive-message --queue-url $QVer solución
bash
aws sqs send-message --queue-url "$Q" --message-body "cita-1" --query 'MessageId' --output text
aws sqs receive-message --queue-url "$Q" --query 'Messages[0].Body' --output text
# cita-1Ejercicio 11 — Borrarlo de verdad
Recoge un mensaje y elimínalo usando su recibo.
💡 ¿Sabías que…? — el recibo no es el identificador
ReceiptHandle es un identificador de esa recepción concreta, no del mensaje. Si el mensaje reaparece, su recibo cambia.
bash
# ejemplo de referencia
R=$(aws sqs receive-message --queue-url $Q --query 'Messages[0].ReceiptHandle' --output text)
aws sqs delete-message --queue-url $Q --receipt-handle "$R"Ver solución
bash
R=$(aws sqs receive-message --queue-url "$Q" --query 'Messages[0].ReceiptHandle' --output text)
aws sqs delete-message --queue-url "$Q" --receipt-handle "$R"Ejercicio 12 — Contar lo que hay pendiente
Averigua cuántos mensajes esperan en la cola.
💡 ¿Sabías que…? — el número es aproximado
Se llama ApproximateNumberOfMessages por algo: SQS es distribuido y el recuento puede ir ligeramente desfasado. Sirve para vigilar tendencias, no para cuadrar cuentas.
bash
# ejemplo de referencia
aws sqs get-queue-attributes --queue-url $Q \
--attribute-names ApproximateNumberOfMessages --query 'Attributes.*' --output textVer solución
bash
aws sqs get-queue-attributes --queue-url "$Q" \
--attribute-names ApproximateNumberOfMessages \
--query 'Attributes.ApproximateNumberOfMessages' --output textEjercicio 13 — Ver los ajustes de la cola
Consulta el tiempo de invisibilidad y cuánto se retienen los mensajes.
💡 ¿Sabías que…? — 30 segundos y 4 días por defecto
La invisibilidad debe ser mayor que lo que tarda el consumidor en procesar. Si tarda 45 segundos y la invisibilidad son 30, el mensaje reaparece y se procesa dos veces.
bash
# ejemplo de referencia
aws sqs get-queue-attributes --queue-url $Q --attribute-names AllVer solución
bash
aws sqs get-queue-attributes --queue-url "$Q" --attribute-names All \
--query 'Attributes.[VisibilityTimeout,MessageRetentionPeriod]' --output text
# 30 345600 (30 segundos, 4 dias)Ejercicio 14 — Activar el sondeo largo
Configura la cola para que las lecturas esperen hasta 5 segundos.
💡 ¿Sabías que…? — menos llamadas, menos coste
Sin sondeo largo, un consumidor pregunta constantemente y casi siempre recibe «nada». Cada pregunta se factura. Esperar reduce las llamadas drásticamente.
bash
# ejemplo de referencia
aws sqs set-queue-attributes --queue-url $Q --attributes ReceiveMessageWaitTimeSeconds=10Ver solución
bash
aws sqs set-queue-attributes --queue-url "$Q" \
--attributes ReceiveMessageWaitTimeSeconds=5Ejercicio 15 — Enviar varios de golpe
Manda tres mensajes y compruébalos.
💡 ¿Sabías que…? — `send-message-batch` ahorra viajes
Permite hasta 10 mensajes por llamada. Con volumen alto, la diferencia en latencia y coste es notable.
bash
# ejemplo de referencia
for i in 1 2 3; do aws sqs send-message --queue-url $Q --message-body "m$i"; doneVer solución
bash
for i in 1 2 3; do
aws sqs send-message --queue-url "$Q" --message-body "cita-$i" >/dev/null
done
aws sqs get-queue-attributes --queue-url "$Q" \
--attribute-names ApproximateNumberOfMessages --query 'Attributes.*' --output text
# 3Ejercicio 16 — Vaciar la cola
Bórralo todo de una vez.
💡 ¿Sabías que…? — `purge-queue` tarda hasta 60 segundos
No es instantáneo, y durante ese rato los mensajes enviados también pueden desaparecer. En producción, úsalo con cuidado.
bash
# ejemplo de referencia
aws sqs purge-queue --queue-url $QVer solución
bash
aws sqs purge-queue --queue-url "$Q"🟡 Nivel 3 — Publicar y suscribir: SNS (17-24)
Ejercicio 17 — Crear un tema
Crea el tema ej17-citas y guarda su ARN.
💡 ¿Sabías que…? — el tema es un punto de reunión
No guarda mensajes: los reparte al instante entre quienes estén suscritos. Si nadie escucha, el mensaje se pierde.
bash
# ejemplo de referencia
T=$(aws sns create-topic --name otro-tema --query TopicArn --output text)Ver solución
bash
T=$(aws sns create-topic --name ej17-citas --query 'TopicArn' --output text)
echo "$T"
# arn:aws:sns:us-east-1:000000000000:ej17-citasEjercicio 18 — Suscribir una cola
Haz que una cola reciba todo lo que se publique en el tema.
💡 ¿Sabías que…? — hace falta el ARN de la cola, no su URL
Es de los pocos sitios donde SQS pide ARN. Se obtiene con get-queue-attributes pidiendo QueueArn.
bash
# ejemplo de referencia
A=$(aws sqs get-queue-attributes --queue-url $Q --attribute-names QueueArn \
--query 'Attributes.QueueArn' --output text)Ver solución
bash
A=$(aws sqs get-queue-attributes --queue-url "$Q" --attribute-names QueueArn \
--query 'Attributes.QueueArn' --output text)
aws sns subscribe --topic-arn "$T" --protocol sqs --notification-endpoint "$A" \
--query 'SubscriptionArn' --output textEjercicio 19 — Publicar un mensaje
Publica en el tema y comprueba que llegó a la cola.
💡 ¿Sabías que…? — SNS envuelve el mensaje
Lo que llega a la cola no es tu texto pelado: es un JSON con Type, MessageId, TopicArn y tu contenido dentro de Message. Hay que desenvolverlo.
bash
# ejemplo de referencia
aws sns publish --topic-arn $T --message "algo paso"Ver solución
bash
aws sns publish --topic-arn "$T" --message "cita creada" --query 'MessageId' --output text
sleep 3
aws sqs receive-message --queue-url "$Q" --query 'Messages[0].Body' --output text
# {"Type":"Notification","MessageId":"...","Message":"cita creada",...}Ejercicio 20 — Suscribir una segunda cola
Añade otra cola al mismo tema y comprueba que ambas reciben.
💡 ¿Sabías que…? — esto es lo que SQS no puede hacer
Una cola entrega cada mensaje a un solo consumidor. Para que dos sistemas reciban lo mismo, hace falta un tema delante repartiendo a dos colas.
bash
# ejemplo de referencia
aws sns subscribe --topic-arn $T --protocol sqs --notification-endpoint $ARN2Ver solución
bash
Q2=$(aws sqs create-queue --queue-name ej20-cola2 --query QueueUrl --output text)
A2=$(aws sqs get-queue-attributes --queue-url "$Q2" --attribute-names QueueArn \
--query 'Attributes.QueueArn' --output text)
aws sns subscribe --topic-arn "$T" --protocol sqs --notification-endpoint "$A2" >/dev/null
aws sns publish --topic-arn "$T" --message "para las dos" >/dev/null
sleep 3
# ambas colas tienen 1 mensajeEjercicio 21 — Listar los suscriptores
Averigua cuántos hay suscritos al tema.
💡 ¿Sabías que…? — el emisor no los consulta nunca
Que se puedan listar es para operar y depurar. La aplicación que publica no debería consultarlos: si lo hace, ha vuelto a acoplarse.
bash
# ejemplo de referencia
aws sns list-subscriptions-by-topic --topic-arn $T --query 'length(Subscriptions)'Ver solución
bash
aws sns list-subscriptions-by-topic --topic-arn "$T" \
--query 'length(Subscriptions)' --output text
# 2Ejercicio 22 — Publicar con asunto
Manda un mensaje con un asunto además del cuerpo.
💡 ¿Sabías que…? — el asunto es para correo
Si el suscriptor es una dirección de correo, --subject es el asunto del mensaje. Para colas viaja como un campo más.
bash
# ejemplo de referencia
aws sns publish --topic-arn $T --subject "Alerta" --message "algo urgente"Ver solución
bash
aws sns publish --topic-arn "$T" --subject "Cita creada" \
--message "Paciente 12345601, Cardiologia" --query 'MessageId' --output textEjercicio 23 — Desuscribir uno
Quita la segunda cola del tema y comprueba que deja de recibir.
💡 ¿Sabías que…? — quitar un consumidor no toca al emisor
Es la otra cara del desacoplamiento: se añaden y se quitan destinos sin desplegar nada del lado que publica.
bash
# ejemplo de referencia
aws sns unsubscribe --subscription-arn $SUBVer solución
bash
SUB=$(aws sns list-subscriptions-by-topic --topic-arn "$T" \
--query 'Subscriptions[-1].SubscriptionArn' --output text)
aws sns unsubscribe --subscription-arn "$SUB"
aws sns list-subscriptions-by-topic --topic-arn "$T" --query 'length(Subscriptions)' --output text
# 1Ejercicio 24 — Publicar sin suscriptores
Crea un tema nuevo, publica y observa qué pasa.
💡 ¿Sabías que…? — el mensaje se pierde, sin error
SNS no almacena. Si nadie escucha en ese instante, el mensaje desaparece y publish devuelve éxito igualmente. Por eso el patrón sano es SNS delante de colas: la cola sí guarda.
bash
# ejemplo de referencia
aws sns create-topic --name tema-solitarioVer solución
bash
T2=$(aws sns create-topic --name ej24-solitario --query TopicArn --output text)
aws sns publish --topic-arn "$T2" --message "nadie me oye" --query 'MessageId' --output text
# devuelve un MessageId... y el mensaje se perdio🟠 Nivel 4 — El bus de eventos: EventBridge (25-32)
Ejercicio 25 — Ver el bus por defecto
Comprueba qué buses existen.
💡 ¿Sabías que…? — siempre hay uno llamado `default`
Recibe los eventos de los servicios de AWS y los tuyos. Se pueden crear buses adicionales para separar dominios.
bash
# ejemplo de referencia
aws events list-event-buses --query 'EventBuses[*].Name' --output textVer solución
bash
aws events list-event-buses --query 'EventBuses[*].Name' --output text
# defaultEjercicio 26 — Crear una regla
Crea una regla que capture los eventos con origen cenate.citas.
💡 ¿Sabías que…? — el patrón mira dentro del evento
Los valores van siempre en lista, aunque sea uno solo: {"source": ["cenate.citas"]}. Es el error de sintaxis más común.
bash
# ejemplo de referencia
aws events put-rule --name otra-regla --event-pattern '{"source":["mi.app"]}'Ver solución
bash
aws events put-rule --name ej26-regla \
--event-pattern '{"source":["cenate.citas"]}' \
--query 'RuleArn' --output textEjercicio 27 — Añadir un destino
Haz que la regla envíe lo capturado a tu cola.
💡 ¿Sabías que…? — `FailedEntryCount` es la confirmación
put-targets devuelve cuántos destinos fallaron. Un 0 significa que se registró bien.
bash
# ejemplo de referencia
aws events put-targets --rule otra-regla --targets "Id=1,Arn=$ARN_COLA"Ver solución
bash
aws events put-targets --rule ej26-regla --targets "Id=1,Arn=$A" \
--query 'FailedEntryCount' --output text
# 0Ejercicio 28 — Publicar un evento
Envía un evento al bus y comprueba que llegó a la cola.
💡 ¿Sabías que…? — la forma abreviada no admite JSON
--entries "Source=x,Detail={...}" falla al parsear las llaves. Hay que usar la forma JSON completa, normalmente con file://.
bash
# ejemplo de referencia — el formato que SI funciona
# [{"Source":"mi.app","DetailType":"Algo","Detail":"{\"clave\":\"valor\"}"}]Ver solución
bash
cat > ev.json <<'EOF'
[{"Source":"cenate.citas","DetailType":"CitaCreada",
"Detail":"{\"dni\":\"12345601\",\"especialidad\":\"Cardiologia\"}"}]
EOF
aws events put-events --entries file://ev.json --query 'FailedEntryCount' --output text
# 0
sleep 4
aws sqs receive-message --queue-url "$Q" --query 'Messages[0].Body' --output textEjercicio 29 — Examinar el sobre del evento
Mira qué campos añadió EventBridge a tu evento.
💡 ¿Sabías que…? — el bus enriquece el evento
Añade id, time, region, account y event-bus-name. Tu contenido queda dentro de detail. Ese sobre estándar es lo que permite enrutar sin conocer la aplicación.
bash
# ejemplo de referencia
aws sqs receive-message --queue-url $Q --query 'Messages[0].Body' --output text | python3 -m json.toolVer solución
json
{
"version": "0",
"id": "f5940edd-1c4c-455d-a001-6a18437fe543",
"source": "cenate.citas",
"detail-type": "CitaCreada",
"account": "000000000000",
"time": "2026-08-09T00:07:14Z",
"region": "us-east-1",
"detail": { "dni": "12345601", "especialidad": "Cardiologia" },
"event-bus-name": "default"
}Ejercicio 30 — Filtrar por contenido
Crea una regla que capture solo las citas de Cardiología.
💡 ¿Sabías que…? — aquí está la potencia del bus
El patrón puede mirar dentro de detail. El emisor publica una vez y cada consumidor recibe solo lo que le interesa, sin filtrar en su código.
json
// ejemplo de referencia
{"detail": {"estado": ["urgente"]}}Ver solución
bash
aws events put-rule --name ej30-cardio \
--event-pattern '{"source":["cenate.citas"],"detail":{"especialidad":["Cardiologia"]}}' \
--query 'RuleArn' --output textEjercicio 31 — Comprobar que el filtro descarta
Publica un evento de otra especialidad y comprueba que esa regla no lo captura.
💡 ¿Sabías que…? — lo que no encaja se descarta en silencio
No hay error ni aviso: el bus simplemente no enruta. Al depurar, lo primero es comprobar que el patrón coincide de verdad.
bash
# ejemplo de referencia — cambiar un valor del detailVer solución
bash
cat > ev2.json <<'EOF'
[{"Source":"cenate.citas","DetailType":"CitaCreada",
"Detail":"{\"dni\":\"23456702\",\"especialidad\":\"Neurologia\"}"}]
EOF
aws events put-events --entries file://ev2.json >/dev/null
# la regla ej30-cardio no lo enruta; la ej26-regla siEjercicio 32 — Listar reglas y destinos
Muestra las reglas existentes y a dónde envían.
💡 ¿Sabías que…? — el mapa del sistema está aquí
En una arquitectura de eventos, nadie llama a nadie: el mapa de quién reacciona a qué son justamente estas reglas.
bash
# ejemplo de referencia
aws events list-rules --query 'Rules[*].Name' --output textVer solución
bash
aws events list-rules --query 'Rules[*].[Name,State]' --output text
aws events list-targets-by-rule --rule ej26-regla --query 'Targets[*].Arn' --output text🔴 Nivel 5 — Que aguante los fallos (33-40)
Ejercicio 33 — Conectar una cola a una función
Haz que una función consuma automáticamente de una cola.
💡 ¿Sabías que…? — el disparador sondea por ti
El event source mapping consulta la cola constantemente y llama a la función cuando hay mensajes, borrándolos si termina bien. No escribes ningún bucle.
bash
# ejemplo de referencia
aws lambda create-event-source-mapping --function-name otra \
--event-source-arn $ARN_COLA --batch-size 10Ver solución
bash
aws lambda create-event-source-mapping --function-name ej33-consumidora \
--event-source-arn "$A" --batch-size 5 --query 'State' --output text
# EnabledEjercicio 34 — Comprobar que consume sola
Envía tres mensajes y verifica que la cola se vacía sin que tú hagas nada.
💡 ¿Sabías que…? — llegan en lote
Con --batch-size 5, la función puede recibir hasta 5 mensajes en un solo evento, dentro de Records. Hay que recorrerlos: procesar solo el primero es un fallo típico.
python
# ejemplo de referencia
for r in event.get("Records", []):
procesar(r["body"])Ver solución
bash
for i in 1 2 3; do aws sqs send-message --queue-url "$Q" --message-body "cita-$i" >/dev/null; done
sleep 15
aws sqs get-queue-attributes --queue-url "$Q" \
--attribute-names ApproximateNumberOfMessages --query 'Attributes.*' --output text
# 0 ← la funcion los consumioEjercicio 35 — Crear una cola de mensajes muertos
Crea ej35-dlq para apartar lo que falle repetidamente.
💡 ¿Sabías que…? — es una cola normal
No tiene nada especial: lo que la convierte en cola de mensajes muertos es que otra cola la señala en su RedrivePolicy.
bash
# ejemplo de referencia
aws sqs create-queue --queue-name otra-dlqVer solución
bash
DLQ=$(aws sqs create-queue --queue-name ej35-dlq --query QueueUrl --output text)
DA=$(aws sqs get-queue-attributes --queue-url "$DLQ" --attribute-names QueueArn \
--query 'Attributes.QueueArn' --output text)Ejercicio 36 — Conectarla a la cola principal
Configura que tras 3 intentos fallidos el mensaje pase a la cola de muertos.
💡 ¿Sabías que…? — sin esto, un mensaje malo bloquea todo
Un mensaje que siempre hace fallar al consumidor reaparece sin fin, consumiendo invocaciones y tapando a los buenos. La cola de muertos lo aparta tras N intentos.
bash
# ejemplo de referencia
--attributes 'RedrivePolicy={"deadLetterTargetArn":"ARN","maxReceiveCount":"5"}'Ver solución
bash
aws sqs set-queue-attributes --queue-url "$Q" \
--attributes "RedrivePolicy={\"deadLetterTargetArn\":\"$DA\",\"maxReceiveCount\":\"3\"}"Ejercicio 37 — Ajustar el tiempo de invisibilidad
Sube la invisibilidad a 60 segundos y explica cuándo hace falta.
💡 ¿Sabías que…? — debe superar el tiempo de proceso
Si la función tarda 45 segundos y la invisibilidad son 30, el mensaje reaparece mientras aún se procesa: se procesa dos veces. La regla práctica es dejarla al menos al doble del tiempo máximo esperado.
bash
# ejemplo de referencia
aws sqs set-queue-attributes --queue-url $Q --attributes VisibilityTimeout=120Ver solución
bash
aws sqs set-queue-attributes --queue-url "$Q" --attributes VisibilityTimeout=60
aws sqs get-queue-attributes --queue-url "$Q" --attribute-names VisibilityTimeout \
--query 'Attributes.*' --output text
# 60Ejercicio 38 — Una cola con orden garantizado
Crea una cola FIFO y observa la diferencia en el nombre.
💡 ¿Sabías que…? — el sufijo es obligatorio
El nombre debe terminar en .fifo. Garantizan orden y entrega única, a cambio de menos rendimiento. Las colas normales no garantizan el orden.
bash
# ejemplo de referencia
aws sqs create-queue --queue-name pedidos.fifo --attributes FifoQueue=trueVer solución
bash
aws sqs create-queue --queue-name ej38-orden.fifo --attributes FifoQueue=true \
--query 'QueueUrl' --output text
# http://localhost:4566/000000000000/ej38-orden.fifoEjercicio 39 — Diseñar el fan-out completo
Monta un tema que reparta a dos colas, cada una con su función consumidora.
💡 ¿Sabías que…? — es el patrón más usado en producción
SNS reparte, cada cola amortigua a su consumidor. Si uno se cae, su cola acumula sin afectar al otro. Ese aislamiento es la razón de meter colas entre medias.
┌──▶ cola A ──▶ funcion A
TEMA ─┤
└──▶ cola B ──▶ funcion BVer solución
bash
# 1. tema 2. dos colas 3. suscribir ambas 4. un ESM por cola
aws sns publish --topic-arn "$T" --message "evento para todos"
sleep 12
# ambas funciones registran el evento, de forma independienteEjercicio 40 — Desmontarlo todo
Elimina disparadores, colas, temas, reglas y funciones.
💡 ¿Sabías que…? — los disparadores se borran aparte
Borrar una cola no elimina el event source mapping que la apuntaba. Queda huérfano reintentando. Hay que borrarlo explícitamente.
bash
# ejemplo de referencia
aws lambda list-event-source-mappings --query 'EventSourceMappings[*].UUID' --output textVer solución
bash
for U in $(aws lambda list-event-source-mappings --query 'EventSourceMappings[*].UUID' --output text); do
aws lambda delete-event-source-mapping --uuid "$U" >/dev/null
done
aws events remove-targets --rule ej26-regla --ids 1 >/dev/null
aws events delete-rule --name ej26-regla
aws sns delete-topic --topic-arn "$T"
aws sqs delete-queue --queue-url "$Q"❓ Preguntas y respuestas (autoevaluación)
1. ¿Cuál es la prueba de que un sistema está bien desacoplado?
Que puedas añadir un consumidor nuevo sin tocar ni desplegar al emisor.
2. ¿Qué diferencia hay entre SQS y SNS?
La cola entrega cada mensaje a un solo consumidor; el tema lo entrega a todos los suscritos.
3. ¿Por qué recibir un mensaje no lo borra?
Para que reaparezca si el consumidor muere antes de terminar. Sin
delete-message, vuelve.
4. ¿Qué pasa si el tiempo de invisibilidad es menor que el de proceso?
El mensaje reaparece mientras aún se procesa y acaba procesándose dos veces.
5. ¿Para qué sirve una cola de mensajes muertos?
Para apartar lo que falla siempre, tras N intentos, y que no bloquee al resto.
6. ¿Qué pasa si publicas en un tema sin suscriptores?
El mensaje se pierde y
publishdevuelve éxito igual. SNS no almacena; por eso se pone una cola detrás.
7. ¿Qué añade EventBridge sobre SNS?
Reglas que filtran por el contenido del evento y enrutan a destinos distintos.
8. Publicas un evento y la regla no lo captura. ¿Primera sospecha?
Que el patrón no coincide. Recuerda que los valores van en lista:
{"source":["x"]}.
9. ¿Qué es un event source mapping?
El disparador que sondea una cola y llama a la función por ti, borrando los mensajes si termina bien.
10. Borras una cola y su función sigue dando errores. ¿Por qué?
El disparador sigue existiendo y reintentando. Hay que eliminarlo aparte.
📎 Apuntes relacionados
- Clase 4 — API REST · síncrono frente a asíncrono
- Clase 1 — CloudFormation · toda esta arquitectura cabe en una plantilla
- Comandos
🏁 Fin del curso
Has recorrido seis módulos y 240 ejercicios: infraestructura como código, bases de datos gestionadas, caché, API serverless, data lake y arquitectura por eventos.
Lo que queda por delante, si quieres seguir: IAM en profundidad, redes (VPC), contenedores (ECS/EKS) y observabilidad. Y sobre todo, llevar algo de esto a AWS real: el emulador enseña los conceptos, pero la factura enseña a diseñar.