Notify & Listen #
Artikel sebelumnya memperkenalkan handler — task yang hanya berjalan saat dipicu. Artikel ini membahas lebih dalam dua mekanisme yang mengontrol pemicuan itu: notify dan listen. Memahami keduanya secara mendalam memungkinkan kamu membangun rantai reaksi yang tepat antara perubahan konfigurasi dan aksi-aksi yang harus mengikutinya.
Cara Kerja Notify #
notify adalah instruksi di dalam task yang memberitahu Ansible: “jika task ini menghasilkan perubahan, tandai handler dengan nama ini untuk dijalankan nanti.”
tasks:
- name: Deploy konfigurasi aplikasi
template:
src: app.conf.j2
dest: /etc/myapp/app.conf
notify: Restart aplikasi # Tandai handler "Restart aplikasi" jika file berubah
handlers:
- name: Restart aplikasi
systemd:
name: myapp
state: restarted
Kata kunci di sini adalah “jika task menghasilkan perubahan”. Notify hanya aktif saat status task adalah changed. Jika template menghasilkan file yang identik dengan yang sudah ada, status task adalah ok — dan notify tidak akan terpicu.
Skenario 1: konfigurasi BERUBAH
Task "Deploy konfigurasi aplikasi" → changed
→ Handler "Restart aplikasi" DITANDAI
→ Di akhir play: handler DIEKSEKUSI
Skenario 2: konfigurasi TIDAK berubah
Task "Deploy konfigurasi aplikasi" → ok
→ Tidak ada yang ditandai
→ Di akhir play: handler TIDAK dieksekusi
Notify ke Beberapa Handler #
Satu task bisa memicu beberapa handler sekaligus menggunakan list:
tasks:
- name: Update SSL certificate
copy:
src: files/app.crt
dest: /etc/ssl/certs/app.crt
notify:
- Reload nginx
- Update certificate cache
- Alert monitoring team
handlers:
- name: Reload nginx
systemd:
name: nginx
state: reloaded
- name: Update certificate cache
command: update-ca-certificates
- name: Alert monitoring team
uri:
url: "https://hooks.slack.com/services/xxx"
method: POST
body_format: json
body:
text: "SSL certificate diperbarui di {{ inventory_hostname }}"
Listen: Notify Berbasis Event #
Saat kamu menggunakan notify: "Nama Handler", kamu membuat coupling langsung antara task dan nama handler. Ini bekerja dengan baik untuk skenario sederhana, tapi bisa menjadi masalah saat project berkembang — terutama saat menggunakan role yang dibuat orang lain.
listen memungkinkan pendekatan yang lebih longgar: handler “mendengarkan” nama event tertentu, dan task cukup memicu event tersebut tanpa peduli handler apa yang akan bereaksi.
# NOTIFY BY NAME — coupling langsung ke nama handler
tasks:
- name: Deploy konfigurasi
template:
src: app.conf.j2
dest: /etc/app/app.conf
notify: Restart aplikasi # Harus tahu nama handler persis
handlers:
- name: Restart aplikasi
systemd:
name: myapp
state: restarted
---
# LISTEN — coupling melalui nama event
tasks:
- name: Deploy konfigurasi
template:
src: app.conf.j2
dest: /etc/app/app.conf
notify: config changed # Trigger event "config changed"
handlers:
- name: Restart aplikasi
systemd:
name: myapp
state: restarted
listen: config changed # Bereaksi terhadap event "config changed"
- name: Clear cache aplikasi
command: /opt/app/bin/clear-cache
listen: config changed # Handler ini juga bereaksi terhadap event yang sama
- name: Log perubahan konfigurasi
lineinfile:
path: /var/log/config-changes.log
line: "{{ ansible_date_time.iso8601 }} - Konfigurasi diperbarui"
listen: config changed # Dan handler ini juga
Urutan Eksekusi Handler #
Handler dieksekusi dalam urutan yang mereka didefinisikan, bukan urutan mereka di-notify:
handlers:
# Handler didefinisikan dalam urutan ini:
- name: Stop aplikasi # 1. Pertama
systemd:
name: myapp
state: stopped
- name: Migrasi database # 2. Kedua
command: python manage.py migrate
- name: Start aplikasi # 3. Ketiga
systemd:
name: myapp
state: started
tasks:
- name: Deploy kode baru
git:
repo: https://github.com/org/app.
dest: /opt/app
notify:
- Start aplikasi # Di-notify pertama...
- Stop aplikasi # Di-notify kedua...
- Migrasi database # Di-notify ketiga...
# Tapi urutan eksekusi tetap mengikuti definisi handler:
# 1. Stop aplikasi → 2. Migrasi database → 3. Start aplikasi
Ini penting untuk dipahami — urutan notify tidak mempengaruhi urutan eksekusi handler. Yang menentukan urutan adalah posisi definisi handler dalam blok handlers:.
Debugging: Handler Tidak Terpicu #
Ada beberapa alasan umum mengapa handler tidak terpicu seperti yang diharapkan:
# Masalah 1: Nama tidak cocok (case-sensitive)
tasks:
- name: Deploy config
template:
src: app.conf.j2
dest: /etc/app/app.conf
notify: restart aplikasi # huruf kecil
handlers:
- name: Restart Aplikasi # Huruf kapital — TIDAK COCOK, handler tidak jalan
systemd:
name: myapp
state: restarted
# Masalah 2: Task tidak menghasilkan "changed"
tasks:
- name: Install nginx
apt:
name: nginx
state: present
notify: Reload nginx # Tidak akan terpicu jika nginx sudah terinstal (status: ok)
# Masalah 3: Playbook berhenti sebelum handler dieksekusi
# Jika ada task yang gagal sebelum akhir play, handler tidak dieksekusi
# Solusi: gunakan --force-handlers
# ansible-playbook site.yml --force-handlers
# Cara debug: tambahkan verbosity untuk melihat apakah handler di-notify
ansible-playbook -i inventory/ site.yml -v # verbose level 1
ansible-playbook -i inventory/ site.yml -vv # verbose level 2
Memastikan Handler Berjalan Meski Task Tidak Changed #
Ada situasi di mana kamu ingin handler selalu berjalan, terlepas dari status task. Gunakan changed_when: true untuk memaksa task selalu melaporkan changed:
tasks:
- name: Trigger reload konfigurasi (paksa)
command: echo "trigger reload"
changed_when: true # Selalu "changed", handler selalu di-notify
notify: Reload konfigurasi
Tapi gunakan pola ini dengan hemat — memaksa status changed mengurangi nilai idempotency playbook kamu.
Ringkasan #
notifymemicu handler hanya saat task menghasilkan statuschanged— jika tidak ada perubahan, handler tidak berjalan.- Satu task bisa
notifybeberapa handler sekaligus dengan menggunakan list.listenmemisahkan coupling antara task dan handler — task memicu event, handler mendengarkan event — membuat kode lebih modular.- Handler dieksekusi dalam urutan definisinya, bukan urutan notify — penting untuk urutan operasi yang bergantung satu sama lain.
- Sumber masalah paling umum: nama yang tidak cocok (case-sensitive), task tidak menghasilkan
changed, atau playbook berhenti sebelum akhir play.- Gunakan
meta: flush_handlersuntuk memaksa handler berjalan lebih awal dari akhir play.