Translate

lunes, 17 de febrero de 2025

Concurrencia en Erlang parte 13


Soy una persona un poco desorganizada. Con suerte, todavía necesitas recordatorios de lo que tienes que hacer, porque vamos a escribir una de estas aplicaciones de recordatorio de eventos que te incitan a hacer cosas y te recuerdan las citas.

El primer paso es saber qué diablos estamos haciendo. "Una aplicación de recordatorios", dices. "Por supuesto", digo yo. Pero hay más. ¿Cómo planeamos interactuar con el software? ¿Qué queremos que haga por nosotros? ¿Cómo representamos el programa con procesos? ¿Cómo sabemos qué mensajes enviar?

Como dice la cita, "Caminar sobre el agua y desarrollar software a partir de una especificación son fáciles si ambos están congelados". Así que obtengamos una especificación y apeguémonos a ella. Nuestro pequeño software nos permitirá hacer lo siguiente:

  • Agregar un evento. Los eventos contienen una fecha límite (el momento en el que se debe advertir), un nombre de evento y una descripción.
  • Mostrar una advertencia cuando haya llegado el momento.
  • Cancelar un evento por nombre.

Sin almacenamiento en disco persistente. No es necesario para mostrar los conceptos arquitectónicos que veremos. Sería un fastidio para una aplicación real, pero en su lugar solo mostraré dónde se podría insertar si quisiera hacerlo y también señalaré algunas funciones útiles. Dado que no tenemos almacenamiento persistente, tenemos que poder actualizar el código mientras se está ejecutando.

La interacción con el software se realizará a través de la línea de comandos, pero debería ser posible ampliarla más adelante para que se puedan utilizar otros medios (por ejemplo, una GUI, acceso a una página web, software de mensajería instantánea, correo electrónico, etc.)

Esta es la estructura del programa que elegí para hacerlo:

Hay 5 componentes: Un cliente (1) que puede comunicarse con un servidor de eventos (2) y 3 pequeños círculos etiquetados como 'x', 'y' y 'z'. Los tres están vinculados al servidor de eventos.

Donde el cliente, el servidor de eventos y x, y y z son todos procesos. Esto es lo que cada uno de ellos puede hacer:

Servidor de eventos

  • Acepta suscripciones de clientes
  • Reenvía notificaciones de procesos de eventos a cada uno de los suscriptores
  • Acepta mensajes para agregar eventos (e iniciar los procesos x, y, z necesarios)
  • Puede aceptar mensajes para cancelar un evento y, posteriormente, matar los procesos de eventos
  • Puede ser finalizado por un cliente
  • Puede hacer que su código se vuelva a cargar a través del shell.

Cliente

Se suscribe al servidor de eventos y recibe notificaciones como mensajes. Por lo tanto, debería ser fácil diseñar un grupo de clientes que se suscriban al servidor de eventos. Cada uno de ellos podría ser potencialmente una puerta de entrada a los diferentes puntos de interacción mencionados anteriormente (GUI, página web, software de mensajería instantánea, correo electrónico, etc.)

  • Pide al servidor que agregue un evento con todos sus detalles
  • Pide al servidor que cancele un evento
  • Monitorea el servidor (para saber si se cae)
  • Apaga el servidor de eventos si es necesario

x, y y z:

  • Representan una notificación que espera ser activada (básicamente son solo temporizadores vinculados al servidor de eventos)
  • Envían un mensaje al servidor de eventos cuando se acaba el tiempo
  • Reciben un mensaje de cancelación y mueren

Tenga en cuenta que todos los clientes (mensajería instantánea, correo, etc. que no están implementados en este libro) reciben notificaciones sobre todos los eventos, y una cancelación no es algo sobre lo que advertir a los clientes. Aquí el software está escrito para usted y para mí, y se supone que solo un usuario lo ejecutará.

Esto representa cada proceso que tendremos. Al dibujar todas las flechas allí y decir que son mensajes, hemos escrito un protocolo de alto nivel, o al menos su esqueleto.

Se debe tener en cuenta que usar un proceso por evento para recordar probablemente sea excesivo y difícil de escalar en una aplicación del mundo real. Sin embargo, para una aplicación de la que será el único usuario, esto es suficiente. Un enfoque diferente podría ser usar funciones como timer:send_after/2-3 para evitar generar demasiados procesos.