Notify & Listen

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 #

  • notify memicu handler hanya saat task menghasilkan status changed — jika tidak ada perubahan, handler tidak berjalan.
  • Satu task bisa notify beberapa handler sekaligus dengan menggunakan list.
  • listen memisahkan 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_handlers untuk memaksa handler berjalan lebih awal dari akhir play.

← Sebelumnya: Handler   Berikutnya: Condition & Loop →

About | Author | Content Scope | Editorial Policy | Privacy Policy | Disclaimer | Contact