在六边形架构中,周期性后台任务应该放在哪里?

huangapple go评论67阅读模式
英文:

Where in Hexagonal Architecture do periodic background tasks fit?

问题

我正在使用golang编写一个程序,该程序基于六边形架构进行结构化。我认为我对这个想法有了大致的理解,但有一些东西我无法弄清楚。

该程序的功能是监控多个IP摄像头的报警事件,接收器可以通过HTTP2.0 PUSH请求接收到报警事件的实时流。我的服务通过GET请求建立一个TCP/HTTP连接并保持打开状态,当摄像头触发报警事件时,摄像头将其推送回服务。

架构层次

适配器

  • HTTP处理程序
  • 内存中的JSON存储

端口

  • DeviceService接口
  • EventService接口
  • DeviceRepo接口
  • EventRepo接口

服务

  • DeviceService
  • EventService

领域

  • DeviceDomain
  • EventDomain

用户通过API向系统添加设备,请求包括所需的监控计划(接收器每天应该何时启动和停止)和URL。

调度程序负责定期检查接收器是否应该根据其计划启动。如果接收器应该为某个设备运行,它会为该设备启动一个接收器。

接收器建立与IP摄像头的连接,并循环处理报警事件流,将报警事件传递给EventService

EventService接收事件,并负责根据领域逻辑处理事件,并决定是发送电子邮件还是忽略它。它还将所有事件保存到eventrepo中。

我不确定的两部分代码应该放在哪里是调度程序和接收器。所以它们应该是:
a. 都在同一个包中,并放置在适配器层
b. 接收器在适配器层,调度程序在服务层
c. 调度程序和接收器都在服务层中?

我有点困惑,因为接收器不是由用户直接启动的,而是由一个持续检查条件的运行循环启动的。但我可能对不同品牌的摄像头有不同的接收器。这是一个实现细节,这意味着接收器应该在适配器层中。这让我认为选项b是最好的。

我可能想得太多了,但请告诉我你们认为最好的选项是什么,或者提出更好的建议。

英文:

I am working on a program in golang, which I am sructuring based on Hexagonal Architecture. I think I have my head wrapped mostly around the idea, but there is something I just can't figure out.

The function of the program is to monitor multiple IP cameras for alarm events, which a receiver can receive a live stream of alarm events over a HTTP2.0 PUSH REQUEST. (Just in-case thats not the technical term, my service establishes a TCP/HTTP connection from a GET request and keeps it open, and when the cameras triggers an alarm event, the camera pushes it back to the services)

Layers of Architecture

Adaptors

  • HTTP Handler
  • In-memory JSON Store

Ports

  • DeviceService Interface
  • EventService Interface
  • DeviceRepo Interface
  • EventRepo Interface

Services

  • DeviceService
  • EventService

Domain

  • DeviceDomain
  • EventDomain

The user adds a device to the system via API, the request includes the desired monitoring schedule (When the receiver should start and stop daily) and url.

A scheduler is responsible to periodically checking if a receiver is meant to be started based on its schedule. If it's meant to be running for a device it starts a receiver for that device.

The receiver establishes connection to the IP camera and loops over the alarm event stream processing the alarm events and passing them to the EventService.

The EventService receives the event, and is responsible for handling the event, based on the domain logic, and decides to send an email or ignore it. It also saves all events to the eventrepo.

The two parts of code i'm not sure where they sit is the scheduler and receiver. So should they be;
a. Both in the same package and placed at the Adaptors layer
b. The receiver in the Adaptors layer and the scheduler in the Service layer
c. Both scheduler and receivers in the Service layer?

I am just confused, as the receiver isn't started by the user directly, but started by a running loop which continually checks a condition. But I also might have different receivers for different brands of cameras. Which is an implementation detail, which means the receiver should be in the Adaptors layer. Which makes me think option b is best.

I'm possibly over thinking it, but let me know what you all think the best option is or suggest a better one.

答案1

得分: 2

如果可以帮到你的话,我的设计如下:

驱动角色:

  • 人类用户:通过驱动端口与应用程序交互,用于“添加设备”。
  • 设备(IP摄像头):通过另一个驱动端口向应用程序发送警报事件,用于“接收警报事件”。

被驱动角色:

  • 设备(IP摄像头):应用程序使用被驱动端口“检查设备”与设备进行交互,以便根据设备的计划每天启动和停止设备。
  • 警报接收者:当接收到警报事件且未被忽略时,应用程序向他们发送电子邮件。
  • 警报事件存储:用于持久化应用程序接收到的警报事件。

应用程序(“警报监视器”)执行以下业务逻辑:

  • 维护要监视的设备集合(“添加设备”)。
  • 它有一个“工作器”(调度程序),定期检查设备状态并根据设备的计划启动/停止它们。
  • 处理从设备接收到的警报事件。当接收到警报事件时,应用程序要么发送电子邮件,要么忽略它,并将事件存储在存储库中。

所以对我来说:

  • 调度程序是业务逻辑的一部分。
  • 接收器是设备的适配器。它处理HTTP相关的事务。

这是图片:

在六边形架构中,周期性后台任务应该放在哪里?

英文:

If it can help you, my design would be as follow:

Driver actors:

  • Human User: Interacts with the app using a driver port: "for adding devices"
  • Device (IP camera): Sends alarm events to the app using another driver port: "for receiving alarm events"

Driven actors:

  • Device (IP camera): The app interacts with the device using the driven port "for checking device", in order to start and stop it daily, according to the schedule of the device.
  • Warning Recipients: The app sends an email to them when an alarm event is received and it is not ignored.
  • Alarm Event Store: For persisting the alarm events the app receives.

The app ("Alarm Monitor") does the following business logic:

  • Maintains a collection of devices it has to monitor ("for adding devices").
  • It has a "worker" (the scheduler) that periodically checks the devices status and starts/stops them according to the schedule of the device.
  • It handles alarm events received from the devices. When an alarm event is received, the app either sends an email or ignore it. And stores the event in a repository.

So for me:

  • The scheduler is part of the business logic.
  • The receiver is the adapter of a device. It deels with http stuff.

Here is the picture:

在六边形架构中,周期性后台任务应该放在哪里?

答案2

得分: 1

"调度程序负责定期检查接收器是否应该根据其计划启动"

对于应用程序来说,无论是人工定期按下“autoStartReceivers”按钮,还是由调度过程完成,都没有太大关系。因此,这是基础设施问题,调度程序是驱动适配器。你可能会有一个ReceiverService.autoStartReceivers服务命令,该命令会定期由调度程序调用。

至于Receiver,我认为这取决于具体实现。如果Receiver不知道基础设施/供应商特定的细节,只进行协调,那么它可能属于应用程序/服务层。

例如,也许接收器使用抽象的EventSource(HTTP、WebSockets等)并使用EventDecoder(供应商特定)来适配事件,然后将其传递给EventProcessor,那么它实际上只是在进行编排EventSourceEventDecoder将是适配器。但是,如果Receiver知道特定的基础设施细节,那么它就成为一个适配器。

最终,上述所有内容都是支持事件处理核心领域的逻辑。核心领域逻辑实际上不关心事件是如何捕获的,可能也不关心结果操作如何进行。因此,你的核心领域在其最简单的形式中可能是actions = process(event)纯函数。

英文:

>"A scheduler is responsible to periodically checking if a receiver is meant to be started based on its schedule"

Ultimately it doesn't really matter to the application whether a human presses an "autoStartReceivers" button peridically or it's done by a scheduling process. Therefore that's an infrastructure concern and the scheduler is a driver adapter. You'd probably have a ReceiverService.autoStartReceivers service command that would be invoked by the scheduler periodically.

Now for the Receiver I'd say it depends on the implementation. If the Receiver doesn't know about infrastructure/vendor-specific details, but only does coordination then it may belong to the application/service layer.

For instance perhaps the receiver works with an abstract EventSource (HTTP, WebSockets, etc.) and uses an EventDecoder (vendor-specific) to adapt events and then relays them to an EventProcessor then it really only is doing orchestration. The EventSource & EventDecoder would be adapters. However if the Receiver knows about specific infrastructure details then it becomes an adapter.

Ultimately all the above is supporting logic for your core domain of event processing. The core domain logic wouldn't really care how events were captured and probably wouldn't care either how resulting actions are carried on. Therefore, your core domain in it's most simplistic form is probably actions = process(event) pure functions.

答案3

得分: 1

a. 同时位于适配器层的包中

b. 接收器位于适配器层,调度器位于服务层

c. 调度器和接收器都位于服务层?

接收器和调度器都是适配器。我认为它们不一定要放在同一个包中,但你可以这样做。所以对我来说,选择a是最好的答案,因为...

接收器将您的应用程序与外部设备(IP摄像头)连接起来。因此,接收器是EventService端口的适配器。

调度器通过DeviceService端口间接管理接收器的生命周期。它启用或禁用IP摄像头,从而导致接收器的连接和断开。

从您的应用程序核心的角度来看,调度器只是另一个适配器,告诉DeviceService端口启用或禁用某些IP摄像头。这也可以由用户通过在UI中点击按钮来完成。调度器只是用户的技术助手,根据时间表执行用户想要的任务。因此,调度器也是一个适配器。

英文:

> a. Both in the same package and placed at the Adaptors layer
>
> b. The receiver in the Adaptors layer and the scheduler in the Service layer
>
> c. Both scheduler and receivers in the Service layer?

The receiver and scheduler are both adapters. I don't think that they must be placed in the same package, but you can do that. So a is the best answer for me, because...

The receiver connects your application with an external device - the ip camara. Thus the receiver is an adapter for the EventService port.

The scheduler indirectly manages the lifecycle of the receiver through the DeviceService port. It enables or disables an ip camara and this leads to a connect and disconnect of the receiver.

From the perspective of your application core the scheduler is just another adapter that tells the DeviceService port to enable or disable some ip camara. This could also be done by a user who clicks on a button in the UI. The scheduler is just a technical assistance for the user which executes tasks that the user wants based on a schedule. Thus the scheduler is also an adapter.

huangapple
  • 本文由 发表于 2021年8月15日 13:44:02
  • 转载请务必保留本文链接:https://go.coder-hub.com/68789016.html
  • architecture
  • clean-architecture
  • domain-driven-design
  • go
  • hexagonal-architecture
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定