Observador remoto

Se o projeto foi além do escopo da máquina local, provavelmente você precisará se integrar a alguns sistemas de terceiros.


Quero considerar o caso em que o sistema externo mencionado deseja receber notificações de quaisquer alterações em nosso sistema. Por exemplo, atualizando um catálogo de produtos.


Tarefa


Existe uma plataforma de negociação que fornece acesso à sua base de produtos por meio de serviços WEB. Os parceiros do site desejam saber sobre alterações no banco de dados o mais rápido possível.


Opção de solução


Conhecemos todos os nossos parceiros, podemos solicitar documentação para seu software.


Você pode implementar o trabalho com a API de nossos parceiros e, ao alterar o catálogo de produtos, notificá-los diretamente.


Com essa abordagem, cada novo cliente precisará ser conectado individualmente. Se o parceiro alterou algo no software, serão necessários recursos para restaurar a funcionalidade. Em geral, despesas adicionais e uma zona extra de responsabilidade.


Eu realmente não quero estabelecer laços tão estreitos. Portanto, faremos o seguinte.


Vamos tomar o padrão de "observador" como base. Permita que nossos colegas se inscrevam em eventos e recebam as notificações de que precisam.


Implementação


Os registros de assinatura devem ser mantidos em algum lugar. O tipo de armazenamento permanecerá na consciência do desenvolvedor. Considere o que precisa ser armazenado.


  • Evento. Pode haver muitos tipos de eventos e, para não enviar alertas a todos, você precisa saber quem se inscreveu no 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 o processamento de uma solicitação de assinatura, a possibilidade disso é verificada (método canAddEvent). Pode ser qualquer coisa, mas no meu caso o limite do número de ouvintes é verificado. Não mais que 3 para cada tipo de evento.


Além disso, é claro, é necessária autorização para trabalhar com esses métodos de API.


É basicamente isso. A opção mais simples é descrita. Se necessário, você pode adicionar suporte para conexões SOAP ou soquete ou algo assim. E você precisa reenviar a mensagem se a resposta não tiver sido bem-sucedida.


All Articles