Enviar hooks

Al ocurrir un evento se deben gatillar los hooks registrados para dicho evento.

Model Driven

La lógica del envío del evento está desarrollada en callbacks del modelo. Al ocurrir cualquier acción de guardado / eliminación de datos, se debe gatillar la acción que busca las suscripciones del modelo (y sus "parents"), y las envía.

Ejemplo: El siguiente ejemplo gatilla el evento de creación de un pago para suscripciones al recurso payment, pero también al recurso invoice

# Invoice Model
class Invoice < NotificableModel
  has_many :payments
end

# Payment Model
class Payment < NotificableModel
  belongs_to :invoice
  after_create :notify_create
end

# Base Class with event notification Behavior
class NotificableModel < ActiveRecord::Base
  def notify_create
    notify :create
  end

  def notify(method)
    # payment
    me = class.name.underscore.to_sym.singularize

    # para :payment => [:invoice]
    parents = class
              .reflect_on_all_associations(:belongs_to)
              .map(&:name)

    # payment.create
    event_name = "#{me}.{method}"

    # Enviar el evento de creación de payment
    # para suscripciones al recurso payment
    Subscriptions.send_event event_name, self

    parents.each do |parent|
      # Enviar el evento de creación de payment
      # para suscripciones padres, por ejemplo a invoce
      Subscriptions.send_event event_name, self, parent
    end
  end
end

API Driven

Otra forma de implementación sería intervenir el API REST de manera que las notificaciones de los eventos tengan relación directa con el endpoint invocado una vez que la ejecución de este finalice satisfactoriamente.

Legacy Driven

En un software Legado, hipotéticamente escrito en PHP, posiblemente existan entidades DTO (Data tansfer Objects) y DAO (Data Access Objects), en dicho caso se puede simular el trabajo con modelos.

  • El DTO debe implementar Notificable y métodos callbacks
    • after_create
    • after_update
    • after_destroy
  • DAO ya implementa métodos save(), destroy(), etc()
  • Para mantener separada la lógica de notificación y evitar notificar por error en DAO se pueden implementar métodos saveAndNotify(), destroyAndNotify()
  • Los métodos <operation>AndNotify() harán <operation>() (del DAO) y luego notify(<operation>). Este último método hace callback del método del entity (DTO) dependiendo de qué operación se está realizando
Entity->after_create()
Entity->after_update()
  • Por su parte Entity que implementa Notificable ya puede funcionar como NotificableModel descrito en el ejemplo Ruby.
  • También la lógica de envío de notificación debiera estar en el Abstracto Notificable.

Async / Background

Tanto la búsqueda de suscriptores como el envío del hook vía POST debe hacerse en una tarea asíncrona (y en background) respecto del flujo (callabck del modelo) que gatilló el evento. De esta forma se establece un mecanismo elegante y a la vez eficiente.

Si tomamos el ejemplo anterior, el método Subscriptions.send_event debería ser capaz simplemente de:

  • Instanciar un mecanismo asíncrono de envío de mensajes (Worker, Job)
  • Encolar el evento con los datos básicos (event_name, resource_id, parent_id)

Luego el mecanismo asíncrono (Worker, Job, Queue) deberá ser capaz de:

  • Buscar todos los suscriptores al recurso-evento
  • Construir el payload de evento definido en el capítulo anterior
  • Enviar vía POST a todos los targets de cada suscriptor encontrado
  • Manejar el código de retorno para reencolar, finalizar, o eliminar la suscripción (410). Puede verlo en Manejo de Reintentos
Model->Notificable: Enviar Evento
Notificable->Queue_1: Encola Evento
Worker_1->Database: Buscar Suscripciones
Database-->Worker_1: suscripciones
Worker_1->Worker_1: Payload suscriptor
Worker_1->Queue_2: Encola notificaciones
Queue_2->Suscriptor: POST Webhok
Suscriptor-->Queue_2: Status Code
Queue_2->Queue_2: Análisis Retorno

results matching ""

    No results matching ""