Emulasi Step Functions (state machine Task/Choice/Parallel/Wait, eksekusi dan inspect history) dan EventBridge (event bus, rules, pattern matching, scheduled cron) di Floci — plus saga order-processing end-to-end

Dua layanan orkestrasi menentukan arsitektur aplikasi AWS yang rapi: Step Functions untuk workflow stateful, EventBridge untuk event bus terpusat. Keduanya sulit diuji tanpa emulator — state machine punya banyak cabang eksekusi, dan event scheduling butuh waktu nyata berjalan.
Floci mengemulasikan keduanya cukup dalam untuk saga produksi sederhana. Episode ini membahas keduanya lalu menyatukannya dalam studi kasus order-processing.
State machine didefinisikan dalam Amazon States Language:
aws --endpoint-url=http://localhost:4566 stepfunctions create-state-machine \
--name order-saga \
--role-arn arn:aws:iam::000000000000:role/dummy \
--definition '{
"StartAt": "Validate",
"States": {
"Validate": {"Type": "Task", "Resource": "arn:aws:lambda:us-east-1:000000000000:function:validate",
"Next": "Charge"},
"Charge": {"Type": "Task", "Resource": "arn:aws:lambda:us-east-1:000000000000:function:charge",
"Retry": [{"ErrorEquals": ["States.TaskFailed"], "IntervalSeconds": 1, "MaxAttempts": 2}],
"Catch": [{"ErrorEquals": ["States.ALL"], "Next": "Refund", "ResultPath": "$.error"}],
"Next": "Notify"},
"Refund": {"Type": "Task", "Resource": "arn:aws:lambda:us-east-1:000000000000:function:refund", "Next": "NotifyFail"},
"NotifyFail": {"Type": "Succeed"},
"Notify": {"Type": "Task", "End": true}
}
}'Tipe state inti yang didukung mencakup Task (panggil Lambda), Choice (cabang kondisional via Variable/Operator), Parallel (eksekusi bersamaan), Wait (delay detik/timestamp), dan Succeed/Fail.
EXEC=$(aws --endpoint-url=http://localhost:4566 stepfunctions start-execution \
--state-machine-arn arn:aws:states:us-east-1:000000000000:stateMachine:order-saga \
--input '{"order_id":"ORD-9","amount":250000}' --query executionArn --output text)
aws --endpoint-url=http://localhost:4566 stepfunctions describe-execution \
--execution-arn "$EXEC" --query status # SUCCEEDED
aws --endpoint-url=http://localhost:4566 stepfunctions get-execution-history \
--execution-arn "$EXEC" --query 'events[].{t:type,d:stateEnteredEventDetails.name}'get-execution-history adalah alat debugging terpenting: setiap transisi state terekam dengan input/output-nya — kalian bisa melihat persis data apa yang salah di cabang Choice atau Retry mana yang habis.
aws --endpoint-url=http://localhost:4566 events create-event-bus --name app-bus >/dev/null
aws --endpoint-url=http://localhost:4566 events put-rule \
--name high-value-orders \
--event-pattern '{"source":["app.orders"],"detail-type":["OrderCreated"],"detail":{"amount":[{"numeric":[">",1000000]}]}}'
aws --endpoint-url=http://localhost:4566 events put-targets \
--rule high-value-orders \
--targets '[{"Id":"billing-queue","Arn":"arn:aws:sqs:us-east-1:000000000000:billing"}]'Pattern matching mendukung prefix ({"prefix":"ORD-"}), exact match, array any-of, hingga numeric comparison — cukup untuk aturan routing realistis.
Rule bisa berjalan periodik seperti CloudWatch Events klasik:
aws --endpoint-url=http://localhost:4566 events put-rule --name nightly-cleanup \
--schedule-expression 'rate(1 minute)'
# atau cron: cron(0 2 * * ? *) = tiap hari jam 02:00 UTCIni mengaktifkan pola job terjadwal lokal — mis. cleanup session DynamoDB tiap menit saat testing.
Target outline: saga sederhana order-processing (validate → charge → notify) via Step Functions + scheduler EventBridge.
set -euo pipefail
export AWS_ENDPOINT_URL=http://localhost:4566
# 3 lambda mini: validate, charge, notify
for fn in validate charge notify; do
mkdir -p saga && cat > saga/handler.py <<EOF
def handler(event, context):
print("$fn:", event)
return {**event, "$fn": True}
EOF
(cd saga && zip -q ../$fn.zip handler.py)
aws lambda create-function --function-name $fn \
--runtime python3.12 --handler handler.handler \
--zip-file fileb://$fn.zip \
--role arn:aws:iam::000000000000:role/dummy >/dev/null
done
# deploy state machine definition dari bagian Step Functions di atas,
# start-execution dengan payload order, lalu:
docker compose logs floci | grep -E 'validate|charge|notify' # urutan eksekusi terlihatUji kegagalan juga: buat fungsi charge melempar exception → jalankan ulang execution → amati history menunjukkan Retry dua kali lalu bercabang ke Refund. Itulah nilai sesungguhnya saga di emulator: skenario failure yang mahal di produksi jadi murah direproduksi.
Rangkuman episode ini:
Episode 14 kita tarik napas dan memetakan medan luasnya: peta coverage ±47 layanan Floci, cara membaca matrix dukungan resmi, dan metode mengetes fitur niche sendiri. Sampai jumpa!