Observador remoto

Si el proyecto fue más allá del alcance de la máquina local, lo más probable es que tenga que integrarse con algunos sistemas de terceros.


Quiero considerar el caso cuando el sistema externo mencionado desea recibir notificaciones de cualquier cambio en nuestro sistema. Por ejemplo, actualizar un catálogo de productos.


Tarea


Existe una plataforma de negociación que proporciona acceso a su base de productos a través de los servicios WEB. Los socios del sitio quieren saber sobre los cambios en la base de datos lo antes posible.


Opción de solución


Conocemos a todos nuestros socios, podemos solicitar documentación para su software.


Puede implementar el trabajo con la API de nuestros socios y, cuando cambie el catálogo de productos, notifíquelos directamente.


Con este enfoque, cada nuevo cliente tendrá que conectarse individualmente. Si el socio ha cambiado algo en el software, se necesitarán recursos para restaurar la funcionalidad. En general, gastos adicionales y una zona adicional de responsabilidad.


Realmente no quiero establecer lazos tan estrechos. Por lo tanto, haremos lo siguiente.


Tomemos el patrón de "observador" como base. Deje que nuestros colegas se suscriban a eventos y reciban las notificaciones que necesitan.


Implementación


Los registros de suscripción deben mantenerse en algún lugar. El tipo de almacenamiento permanecerá en la conciencia del desarrollador. Considere lo que necesita ser almacenado.


  • Evento. Puede haber muchos tipos de eventos y para no enviar alertas a todos, debe saber quién se ha suscrito a qué.
  • URL. . HTTP- URL. , .
  • . , ( , , ). , . - . .

, PHP.


, POST- URL. , b2b.api.my-soft.ru/event-subscription. URL event( ).


( Laravel):


public function subscribe()
{
    $request = $this->getRequest();
    $eventName = $request->input('event');
    $url = $request->input('callback');

    $validator = \Validator::make([
        'url' => $url,
        'event' => $eventName
    ], [
        'url' => 'url|required',
        'event' => 'required'
    ]);

    if ($validator->fails()) {
        throw new BadRequestHttpException($validator->errors()->first());
    }

    $repository = $this->getRepository();
    if (!$repository->eventAvailable($eventName)) {
        throw new BadRequestHttpException(trans('api.error.eventSubscription.wrongEvent'));
    }

    if (!$repository->canAddEvent($eventName)) {
        throw new BadRequestHttpException(trans('api.error.eventSubscription.maxCallbacks'));
    }

    $model = $repository->createModel([
        'client_id' => $request->attributes->get('client')->id,
        'event' => $eventName,
        'url' => $url
    ]);
    if ($repository->save($model)) {
        return $this->response($model);
    }
    throw new \Exception();
}

:


  • ,
  • ,
  • ( canAddEvent)
  • ,

.


. , . , .. . .


, , .


.


, , . , , .


, . .


$subscribersRepository->with(['event' => $event->getEventName()])->getActive()->each(function ($model) use ($event) {
    $this->dispatch(new \Commands\RemoteCallback(
        $model->id,
        $model->url,
        $event->getData()->toArray()
    ));
});

.


RemoteCallback :


public function handle(EventSubscriptionRepository $subscriptionRepository)
{
    $client = new \Guzzle\Http\Client();
    $res = $client->post($this->url, [], $this->data, ['connect_timeout' => 3, 'timeout' => 3]);
    try {
        if ($res->send()->getStatusCode() !== 200) {
            throw new \Exception();
        }
        $subscriptionRepository->dropErrors($this->subscriptionId);
    } catch (\Exception $e) {
        $subscriptionRepository->incrementError($this->subscriptionId);
    }
}

. POST- URL. , , .


. . HTTP != 200, . , 3 3 . , .


Durante el procesamiento de una solicitud de suscripción, se verifica la posibilidad de esto (método canAddEvent). Puede ser cualquier cosa, pero en mi caso se verifica el límite en el número de oyentes. No más de 3 para cada tipo de evento.


Además, por supuesto, se requiere autorización para trabajar con dichos métodos API.


Eso es básicamente eso. Se describe la opción más simple. Si es necesario, puede agregar soporte para SOAP o conexiones de socket o algo así. Y debe volver a enviar el mensaje si la respuesta no fue exitosa.


All Articles