logo Buffalo slack logo
Eventos
Guías

Eventos

Desde 0.13.0-beta.2

La librería de events permite a las aplicaciones en Go, incluyendo aplicaciones de Buffalo, escuchen y emitan mensajes de eventos globales.

Escuchar Eventos

Para iniciar a escuchar eventos, primero se debe registrar un events#Listener con la librería events.

func init() {
  _, err := events.Listen(func(e events.Event) {
    // do work
  })
}

Una vez registrada esta nueva función listener, se enviarán todos los eventos emitidos a través de la librería events.

Emitiendo Eventos

Cuando emitimos eventos, el atributo Kind debe ser una cadena única, pero constante. Es este atributo que los usuarios usarán para determinar cómo responder a los eventos que reciben.

Se recomienda asignar un espacio de nombres a este atributo como tal, con los eventos de error sean con el sufijo: :err.

"<package-name>:<additional-names>:<optional-error>"

"myapp:foo:start"
"myapp:foo:stop"
"mypkg:workers:bar:err"

Este patrón de nomenclatura facilita a los usuarios filtrar solo aquellos eventos que les interesan. Ve a Filtrando Eventos para mas detalles.


Hay varias maneras de emitir un events#Event en tu código de Go. Las funciones events#EmitError y events#EmitPayload aceptan un argumento de tipo payload interface{}. Se recomienda usar events#Payload para datos de entrada; cualquier otro tipo pasado será convertido a events#Payload con el argumento establecido en los datos de entrada con la llave data.

func MyHandler(c buffalo.Context) error {
e := events.Event{
    Kind:    "coke:myhandler:hello",
    Message: "hi!",
    Payload: events.Payload{"context": c},
}
if err := events.Emit(e); err != nil {
    return err
}
return c.Render(200, r.HTML("index.html"))
}
func MyHandler(c buffalo.Context) error {
  if err := events.EmitError("coke:myhandler:hello:err", errors.New("boom"), c); err != nil {
    return err
  }
  return c.Render(200, r.HTML("index.html"))
}
func MyHandler(c buffalo.Context) error {
  p := events.Payload{
    "message": "hi!",
  }
  if err := events.EmitPayload("coke:myhandler:hello", p); err != nil {
    return err
  }
  return c.Render(200, r.HTML("index.html"))
}

Filtrando Eventos

En la sección de Emitiendo Eventos se describe la convención de nomenclaturas para events#Event.Kind. Al comprobar el valor de events#Event.Kind.

events.Listen(func(e events.Event) {
  if e.Kind != buffalo.EvtRouteStarted {
    // do nothing
    return
  }
  // do work on the route event
})
events.Listen(func(e events.Event) {
  switch e.Kind {
  case buffalo.EvtAppStart, buffalo.EvtAppStop:
    // do work
  case "buffalo:dev:build:finished":
    // do work
  default:
    // do nothing
  }
})
func init() {
  events.Listen(func(e events.Event) {
    if !e.IsError() {
      // do nothing
      return
    }
    // do something with e.Error
  })
}
events.Listen(func(e events.Event) {
  if !strings.HasPrefix(e.Kind, "buffalo:") {
    // do nothing
    return
  }
  // do work only on events emitted by Buffalo
})

Dejar de escuchar Eventos

Cuando registramos un nuevo events#Listener, se retorna unaevents#DeleteFn. Esta función debe conservarse y usarse cuando desees eliminar el listener agregado.

deleteFn, err := events.Listen(func(e events.Event) {
  // do work
})
if err != nil {
  return err
}
defer deleteFn()

Escuchando con Complementos

Para permitir que un complemento reciba una version JSON de los eventos emitidos, el complemento puede establecer el valor de events#Command.BuffaloCommand al evento al listar los comandos disponibles para el complemento.

// availableCmd
var availableCmd = &cobra.Command{
  Use:   "available",
  Short: "a list of available buffalo plugins",
  RunE: func(cmd *cobra.Command, args []string) error {
    plugs := plugins.Commands{
      {Name: "listen", UseCommand: "listen", BuffaloCommand: "events", Description: listenCmd.Short, Aliases: listenCmd.Aliases},
    }
    return json.NewEncoder(os.Stdout).Encode(plugs)
  },
}
// listenCmd
var listenCmd = &cobra.Command{
  Use:   "listen",
  Short: "listens to github.com/gobuffalo/events",
  RunE: func(cmd *cobra.Command, args []string) error {
    if len(args) == 0 {
      return errors.New("must pass a payload")
    }

    e := events.Event{}
    err := json.Unmarshal([]byte(args[0]), &e)
    if err != nil {
      return errors.WithStack(err)
    }

    // do work with event
    return nil
  },
}

Integración de una cola de mensajería

A menudo se desea tomar los eventos emitidos y enviarlos a una cola de mensajes, como Kafka o Redis, para que se procesen externamente. La librería events no tiene una forma directa para esta funcionalidad, la forma mas directa para habilitar este comportamiento es registrar un events#Listener que luego puede transferir el evento a la cola de mensajes correspondientes.

events.Listen(func(e events.Event) {
  myMessageQ.DoWork(e)
})

Eventos Conocidos

Eventos de la Aplicación

Se sabe que Buffalo emite los siguientes eventos durante el ciclo de vida de la aplicación.

constante Cadena Se emite cuando Datos de entrada
buffalo.EvtAppStart "buffalo:app:start" Se llama buffalo#App.Serve app: buffalo#App
buffalo.EvtAppStartErr "buffalo:app:start:err" Ocurre un error llamando buffalo#App.Serve app: buffalo#App
buffalo.EvtAppStop "buffalo:app:stop" Se llama buffalo#App.Stop app: buffalo#App
buffalo.EvtAppStopErr "buffalo:app:stop:err" Ocurre un error llamando buffalo#App.Stop app: buffalo#App
buffalo.EvtRouteStarted "buffalo:route:started" Se está procesando una ruta solicitada route: buffalo#RouteInfo app: buffalo#App context: buffalo#Context
buffalo.EvtRouteFinished "buffalo:route:finished" Se completa una ruta solicitada route: buffalo#RouteInfo app: buffalo#App context: buffalo#Context
buffalo.EvtRouteErr "buffalo:route:err" Hay un problema al manejar el procesamiento de una ruta route: buffalo#RouteInfo app: buffalo#App context: buffalo#Context
buffalo.EvtWorkerStart "buffalo:worker:start" Se llama buffalo#App.Serve y se inician los Workers app: buffalo#App
buffalo.EvtWorkerStartErr "buffalo:worker:start:err" Se produce un error al iniciar los Workers app: buffalo#App
buffalo.EvtWorkerStop "buffalo:worker:stop" Se llama buffalo#App.Stop y se detienen los Workers app: buffalo#App
buffalo.EvtWorkerStopErr "buffalo:worker:stop:err" Se produce un error al detener los Workers app: buffalo#App
buffalo.EvtFailureErr "buffalo:failure:err" Algo no se puede procesar en absoluto. Es algo malo app: buffalo#App context: buffalo#Context

Eventos de Buffalo Dev

Se sabe que los siguientes eventos son emitidos por buffalo dev durante el ciclo de vida del desarrollo.

Cadena Se emite cuando Datos de entrada
"buffalo:dev:raw" Se modifica un archivo aplicable event: fsnotify#Event
"buffalo:dev:build:started" Comienza una una construcción event: fsnotify#Event cmd: string of the go build command (example: "go build foo")
"buffalo:dev:build:finished" Se completa una construcción event: fsnotify#Event pid: PID of the newly running binary build_time: the duration of the build
"buffalo:dev:build:err" Ocurre un error en la construcción event: fsnotify#Event cmd: string of the go build command (example: "go build foo")