远程观察者

如果项目超出了本地计算机的范围,则很可能必须与某些第三方系统集成。


我想考虑当提到的外部系统想要接收我们系统中任何更改的通知时的情况。例如,更新产品目录。


任务


有一个交易平台,可通过WEB服务访问其产品库。该站点的合作伙伴希望尽快了解数据库中的更改。


解决方案选项


我们知道我们所有的合作伙伴,我们可以要求其软件提供文档。


您可以使用我们合作伙伴的API实施工作,并且在更改产品目录时,请直接通知他们。


使用这种方法,每个新客户端都必须分别连接。如果合作伙伴更改了软件中的某些内容,则需要资源来恢复功能。通常,额外的费用和额外的责任范围。


我真的不想建立如此紧密的联系。因此,我们将执行以下操作。


让我们以“观察者”模式为基础。让我们的同事订阅事件并接收他们所需的通知。


实作


订阅记录必须保存在某个地方。存储类型将保持开发人员的良心。考虑需要存储什么。


  • 事件。事件可能有很多类型,为了不向所有人发送警报,您需要知道谁订阅了什么。
  • 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 . , .


在处理订阅请求期间,将检查这种可能性(canAddEvent方法)。可以是任何东西,但在我的情况下,将检查侦听器数量的限制。每种类型的事件不得超过3个。


另外,当然,需要授权才能使用此类API方法。


基本上就是这样。描述了最简单的选项。如有必要,您可以添加对SOAP或套接字连接等的支持。如果响应失败,则需要重新发送该消息。


All Articles