Php 在企业web应用程序中处理计划/有时间限制的任务

Php 在企业web应用程序中处理计划/有时间限制的任务,php,web-applications,cron,scheduled-tasks,domain-driven-design,Php,Web Applications,Cron,Scheduled Tasks,Domain Driven Design,表面上看,我面临的问题很简单。在企业web应用程序(LAMP stack)中,我们需要添加一些基于时间和计划的任务。例如 当用户登录并保持活动状态超过30分钟时,向他们发送幸运优惠券 每周一向订户发送一份时事通讯。[由cron作业轻松处理] 如果用户在3天内没有登录,开始跟踪她。[可通过cron作业完成,但…] 每月第一个工作日9点从用户账户中扣除电话账单金额 在随后的每个工作日9点重复失败的扣减,最多重试15次 我希望这能让你了解需要处理的事情 目前,我们几乎在所有可能的情况下都有cron

表面上看,我面临的问题很简单。在企业web应用程序(LAMP stack)中,我们需要添加一些基于时间和计划的任务。例如

  • 当用户登录并保持活动状态超过30分钟时,向他们发送幸运优惠券

  • 每周一向订户发送一份时事通讯。[由cron作业轻松处理]

  • 如果用户在3天内没有登录,开始跟踪她。[可通过cron作业完成,但…]

  • 每月第一个工作日9点从用户账户中扣除电话账单金额

  • 在随后的每个工作日9点重复失败的扣减,最多重试15次

我希望这能让你了解需要处理的事情

目前,我们几乎在所有可能的情况下都有cron作业,它们可以正常工作,但正如您在上述场景中看到的,我们几乎每秒钟都被迫运行这些cron(有点夸张,但几乎是)

为了更优雅地处理这个问题并更好地实现ddd概念,我们正在考虑让时钟滴答作响成为应用程序的头等公民

我们想创建一个简单的中央时钟滴答器类,它将每秒以时间事件的形式发出滴答声

滴答声将发布到中央事件总线

所有感兴趣的类都将订阅事件总线

我还不能弄清楚的是,这将导致在每个刻度上运行大量订户/注册人类代码。由于cron的情况已经如此,是否有更好的方法来处理订阅部分,以便只在需要通知特定订阅时才通知它


在我们开始用我提出的方法解决这个问题之前,有没有更好的方法来处理这类问题?整个场景中的关键点似乎是如何根据自域中发生Y事件以来经过的时间触发X事件。我相信我不是第一个面对这个问题的人,这个问题肯定早就解决了,但我不能偶然发现任何指向我正确方向的路标。

我过去处理这个问题的方式是,在我知道应该发生什么事情时,立即将命令排队,然后调度器会在时间到了

调度器只是一个作为服务运行的进程,它每N毫秒唤醒一次,以查找已超过其ScheduledTime的任何命令

例如:

  • 用户已登录。将命令排队30分钟,然后给他们优惠券。30分钟后,调度程序将发送命令。如果会话仍处于活动状态,则接受该命令并显示优惠券。否则,它将一事无成
您还提到了几个最好由传统调度器(您提到的cron)处理的示例,这些示例将触发批处理命令。根据您的域对新闻稿等内容的了解程度,您可以向域对象发出单独的命令,也可以简单地拉一个报告并运行一个作业来发送电子邮件

如果您确实在域中处理这些类型的进程,则域还应将下一个命令排入队列。一个传奇或过程管理者最适合这种类型的操作。例如

CreateNewsletter (This is the batch) -> NewsletterCreated
    Accounts.Each(SendAccountNewsletter) -> AccountNewsletterSent
        NewsletterCompleted (This is the batch) -> 
            Queue(command: CreateNewsletter, when: NextMondayAt9) (This is the next batch)
希望有帮助


p.S.如果你在公交车上发布滴答声,你将有大量噪音需要过滤

我过去处理这个问题的方法是,在我知道应该发生什么事情时,立即将命令排队,然后调度程序将在时机成熟时发出命令

调度器只是一个作为服务运行的进程,它每N毫秒唤醒一次,以查找已超过其ScheduledTime的任何命令

例如:

  • 用户已登录。将命令排队30分钟,然后给他们优惠券。30分钟后,调度程序将发送命令。如果会话仍处于活动状态,则接受该命令并显示优惠券。否则,它将一事无成
您还提到了几个最好由传统调度器(您提到的cron)处理的示例,这些示例将触发批处理命令。根据您的域对新闻稿等内容的了解程度,您可以向域对象发出单独的命令,也可以简单地拉一个报告并运行一个作业来发送电子邮件

如果您确实在域中处理这些类型的进程,则域还应将下一个命令排入队列。一个传奇或过程管理者最适合这种类型的操作。例如

CreateNewsletter (This is the batch) -> NewsletterCreated
    Accounts.Each(SendAccountNewsletter) -> AccountNewsletterSent
        NewsletterCompleted (This is the batch) -> 
            Queue(command: CreateNewsletter, when: NextMondayAt9) (This is the next batch)
希望有帮助

p.S.如果你在公交车上发布滴答声,你将有大量噪音需要过滤