Handler

Handler #

Ada kategori aksi dalam pengelolaan server yang hanya perlu dilakukan saat ada perubahan nyata — reload nginx setelah konfigurasi diubah, restart aplikasi setelah kode di-deploy, atau reload systemd setelah unit file ditambahkan. Jika kamu memasukkan aksi-aksi ini sebagai task biasa, mereka akan selalu dijalankan tanpa peduli apakah ada yang berubah atau tidak. Di sinilah handler hadir: task khusus yang hanya berjalan saat dipicu oleh task lain, dan hanya jika task pemicunya benar-benar menghasilkan perubahan.

Handler vs Task Biasa #

Perbedaan fundamental antara handler dan task biasa ada di kapan mereka dijalankan:

# Task biasa: SELALU dijalankan saat playbook berjalan
tasks:
  - name: Deploy konfigurasi nginx
    template:
      src: nginx.conf.j2
      dest: /etc/nginx/nginx.conf

  - name: Reload nginx     ← SELALU reload, bahkan jika konfigurasi tidak berubah
    systemd:
      name: nginx
      state: reloaded

# Handler: hanya dijalankan jika task notify-nya menghasilkan "changed"
tasks:
  - name: Deploy konfigurasi nginx
    template:
      src: nginx.conf.j2
      dest: /etc/nginx/nginx.conf
    notify: Reload nginx   ← trigger handler hanya jika file BERUBAH

handlers:
  - name: Reload nginx     ← hanya dijalankan jika di-notify
    systemd:
      name: nginx
      state: reloaded

Dengan handler, nginx hanya di-reload saat konfigurasi benar-benar berubah. Jika konfigurasi tidak berubah (file sudah identik), tidak ada yang terjadi. Ini lebih efisien dan lebih aman.


Kapan Handler Dijalankan #

Handler tidak langsung dieksekusi saat di-notify. Mereka dikumpulkan dan dieksekusi setelah semua task dalam play selesai:

Task 1: Deploy nginx.conf     → changed → notify "Reload nginx"
Task 2: Deploy SSL cert       → changed → notify "Reload nginx"
Task 3: Deploy app config     → ok (tidak berubah)
Task 4: Update robots.txt     → changed → notify "Reload nginx"

--- Semua task selesai ---

Handler: Reload nginx          → dieksekusi SEKALI
         (meski di-notify 3 kali, hanya berjalan satu kali)

Perilaku ini sangat efisien — tidak peduli berapa banyak task yang mengubah konfigurasi nginx, reload hanya terjadi satu kali di akhir.

Karena handler dijalankan di akhir play, jika playbook berhenti di tengah jalan karena ada task yang gagal, handler yang sudah di-notify tidak akan dijalankan. Gunakan --force-handlers saat menjalankan playbook jika kamu ingin handler tetap berjalan meski ada kegagalan.

Mendefinisikan dan Memanggil Handler #

Handler didefinisikan di bagian handlers: play, dan dipanggil dari task menggunakan notify::

tasks:
  - name: Deploy konfigurasi nginx
    template:
      src: nginx.conf.j2
      dest: /etc/nginx/nginx.conf
    notify:
      - Reload nginx
      - Update log rotation   # Bisa notify beberapa handler sekaligus

  - name: Tambahkan virtual host baru
    template:
      src: vhost.conf.j2
      dest: /etc/nginx/sites-available/myapp.conf
    notify: Reload nginx       # Notify handler yang sama

handlers:
  - name: Reload nginx
    systemd:
      name: nginx
      state: reloaded

  - name: Update log rotation
    command: logrotate -f /etc/logrotate.d/nginx

Nama handler adalah identifier — pastikan nama di notify: sama persis (case-sensitive) dengan nama di handlers:.


Handler Berantai (listen) #

Ansible mendukung pola di mana beberapa handler “mendengarkan” satu event yang sama menggunakan listen:

handlers:
  - name: Restart stack aplikasi   # nama handler
    systemd:
      name: myapp
      state: restarted
    listen: "restart app stack"    # event yang didengarkan

  - name: Clear application cache
    command: redis-cli flushdb
    listen: "restart app stack"    # handler ini juga mendengarkan event yang sama

  - name: Notify monitoring
    uri:
      url: "https://monitoring.example.com/api/deployments"
      method: POST
    listen: "restart app stack"

# Di task, cukup notify event-nya:
tasks:
  - name: Deploy kode baru
    git:
      repo: https://github.com/org/app.git
      dest: /opt/app
    notify: "restart app stack"    # Trigger SEMUA handler yang listen event ini

Pola ini memisahkan concern dengan bersih — task tidak perlu tahu ada berapa handler yang akan bereaksi, cukup notify event yang relevan.


Memaksa Handler Berjalan Segera #

Secara default, handler berjalan di akhir play. Tapi ada kasus di mana kamu butuh handler berjalan lebih awal — misalnya saat ada task berikutnya yang bergantung pada hasil handler:

tasks:
  - name: Deploy konfigurasi database baru
    template:
      src: postgresql.conf.j2
      dest: /etc/postgresql/15/main/postgresql.conf
    notify: Restart PostgreSQL

  # Jalankan semua handler yang sudah di-notify sejauh ini
  - name: Flush handlers sekarang
    meta: flush_handlers

  # Task ini butuh PostgreSQL sudah restart dengan konfigurasi baru
  - name: Jalankan migrasi database
    command: python manage.py migrate

meta: flush_handlers memaksa semua handler yang sudah di-notify untuk dieksekusi saat itu juga, bukan menunggu akhir play.


Handler di dalam Role #

Saat menggunakan role, handler didefinisikan di roles/<rolename>/handlers/main.yml dan otomatis tersedia untuk semua task dalam role tersebut:

roles/nginx/
  ├── tasks/
  │   └── main.yml         # Task yang notify handler
  └── handlers/
      └── main.yml         # Definisi handler untuk role nginx
# roles/nginx/handlers/main.yml
---
- name: Reload nginx
  systemd:
    name: nginx
    state: reloaded

- name: Restart nginx
  systemd:
    name: nginx
    state: restarted

Handler yang didefinisikan dalam role hanya tersedia untuk task dalam role yang sama. Tapi jika kamu menggunakan listen, handler dari satu role bisa merespons notify dari role lain.


Ringkasan #

  • Handler adalah task khusus yang hanya dieksekusi saat di-notify oleh task lain, dan hanya jika task pemicunya menghasilkan perubahan (changed).
  • Handler dieksekusi di akhir play, bukan langsung saat di-notify — dan hanya sekali meski di-notify berkali-kali.
  • Gunakan notify: di task untuk memicu handler, dan definisikan handler di bagian handlers: play atau di handlers/main.yml role.
  • listen memungkinkan beberapa handler merespons satu event — berguna untuk memisahkan aksi-aksi yang terkait.
  • meta: flush_handlers untuk memaksa handler berjalan segera, bukan menunggu akhir play — gunakan saat task berikutnya bergantung pada hasil handler.
  • Handler tidak berjalan jika playbook berhenti karena error — gunakan --force-handlers jika diperlukan.

← Sebelumnya: Task & Module Execution   Berikutnya: Notify & Listen →

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