有关排队以在 asp.net-mvc 应用程序中通过电子邮件发送的更新的建议

本文关键字:电子邮件 更新 排队 asp 应用程序 net-mvc | 更新日期: 2023-09-27 18:31:33

我有一个 asp.net-mvc应用程序(SQL Server后端),它是一个基本的CRUD网络应用程序,用于跟踪采购订单。 其中一个功能是能够订阅订单,因此如果有人进行任何更改,您会收到电子邮件通知。 在将更新提交到数据库之后和之后,我在表单发布后触发电子邮件通知。

问题是,有一天,一个订单有大量更新,一个人在一天内收到了 24 封电子邮件更新。 用户要求他每天只收到 1 封包含所有更改摘要的电子邮件。 这似乎是一个合理的要求,我已经在其他情况下看到了这一点(每天或每周收到单个批量通知),但我正在努力找出构建它的最佳方法。 我知道我需要保留有关他们希望如何接收更新的用户设置,但之后我可以:

  • 有一个临时更新表或
  • 每天对所有订单
  • 运行一次查询,查看具有"每天一次"检查的任何用户的订单是否有任何更改。
  • 其他?

由于我在其他地方看到过这种情况,我认为可能会有一个推荐的模式或建议来支持这一点。

有关排队以在 asp.net-mvc 应用程序中通过电子邮件发送的更新的建议

这里有三件事需要解决:

  • 存储一堆可能的消息
  • 在发送之前聚合消息
  • 发送消息

存储消息很简单,您可以创建一个数据库表,其中包含具有收件人 ID 的各个消息。

然后,聚合消息完全取决于您,您可能希望允许用户指定他们想要单个消息、每日或每周摘要。将邮件合并到一封电子邮件后,可以发送该邮件,并删除聚合中使用的邮件。(您可能只想软删除它们,或将它们移动到日志表中)。

至于用于聚合和发送的技术,您需要一个异步作业来处理消息队列并发送电子邮件。

如果不想使用任何其他库,可以设置操作方法来执行作业,只需从计划的 Windows 作业或任何站点活动的 ping er 服务定期调用操作方法。您可能希望保护此操作方法,或者设置一些逻辑以每天仅处理几次队列。

如果第三方库不是问题,那么 Scott Hanselman 不久前收集了一个可能的选项列表,请参阅此处。正如其他人提到的,Hangfire.io 是一个受欢迎的选择。

我会使用日期来解决问题:

任何订单都有一个"上次更新"的日期时间。每个用户都有一个"上次运行"日期时间和频率。然后,您可以每##分钟运行一次流程,根据用户偏好获取所有需要通知的用户,并找到具有上次更新日期>用户上次运行属性的所有订单。

关键是,应用中需要一些后台作业处理组件来计划工作并监视运行情况。我使用 hangfire.io 来完成这项工作,取得了很好的结果<</p>

div class="answers">

用记事本编写的代码 我明天会检查它。

更新:我已经检查了底部的代码,它在SQL Server中工作正常。

执行所需操作的最快和最简单的方法是将字段last_update_date添加到订单表,然后:

这段代码返回一段时间内所有更新的记录以及订阅订单的用户

select o.*, u.* from orders o 
inner join user_subscribtions us on us.order_id = o.order_id
inner join users_intervals ui on ui.user_id = us.user_id and ui.interval = @interval
inner join users u on u.user_id = us.user_id
where o.last_update_date >= DATEADD(HOUR, @interval, GETDATE());

如果您有服务器并且可以创建服务

运行 2 个作业,这些作业将使用不同的时间间隔参数执行相同的过程。第一个作业将每 24 小时执行一次过程,参数为 -24(小时)第二个作业将每周执行一次上述过程,参数为 -168(小时 = 周),该过程将更新该时间段内的所有订单并将他们的数据插入电子邮件表格

    create procedure getAllUpdatedOrders @interval datetime as
    begin
    insert into emails_to_send
    select o.*, u.* from orders o 
    inner join user_subscribtions us on us.order_id = o.order_id
    inner join users_intervals ui on ui.user_id = us.user_id and ui.interval = @interval
    inner join users u on u.user_id = us.user_id
    where o.last_update_date >= DATEADD(HOUR, @interval, GETDATE());
    end
    GO

然后,您需要定期检查表emails_to_send并从该表发送所有电子邮件的服务。

exec getAllUpdatedOrders -24; - 过去24小时内更新的所有订单+订阅订单和每日邮件的用户

exec getAllUpdatedOrders -168; - 上周内更新的所有订单 + 订阅订单和每周邮件的用户

如果您需要显示过去 24 小时或一周内某个订单的所有更新,则需要将此类更新存储在某个单独的表中至少一周并加入上述查询

获取订阅用户和订单在一段时间内更新的示例:

--drop TABLE orders;

--drop TABLE user_subscribtions;

--drop TABLE users_intervals;

CREATE TABLE orders(order_id int, last_update_date datetime);
CREATE TABLE user_subscribtions(id int, order_id int, user_id int);
CREATE TABLE users_intervals(id int, interval int, user_id int);
insert into orders values(1, '2015-02-15');
insert into orders values(2, '2015-02-02');
insert into user_subscribtions values(1, 1, 10);
insert into user_subscribtions values(1, 1, 11);
insert into users_intervals values(1, -24, 10);
insert into users_intervals values(1, -168, 11);
select o.*, us.* from orders o 
inner join user_subscribtions us on us.order_id = o.order_id
inner join users_intervals ui on ui.user_id = us.user_id and ui.interval = -24
where o.last_update_date >= '2015-02-15';

摘要类型更新系统的情况下,我会考虑将所有电子邮件存储到单独的表中,并创建一个触发器 - 每天运行一次的 Windows 服务或运行控制台的计划任务以触发将发送给表中一个人的消息编译为一封电子邮件的函数, 并处理发送。

您甚至可以更进一步,将更新类型拆分为优先级;某些类型会导致即时消息,而其他类型则排队等待每日摘要。此外,如果您跟踪首选项,您可以让用户决定他们是否需要摘要类型的更新或单个消息。选择总是一件好事。

跟踪最后一条消息的发送

时间应该很容易,但您应该记住,无论最后一条消息是何时发送的,客户都会想知道一些事情。让他们决定选择。

您肯定需要某种形式的后台处理,大量的解决方案,但是不知道这个网站的托管位置和方式,我将等待在这方面提供建议。

至于通知本身。这听起来像是一个超级简单的请求,但是用户期望从他们的通知中获得什么样的时间范围?他们是使用它们来检查订单还是只是数据?即时通知的好处是您可以实时了解发生的事情,用户可能会喜欢。然而,在高容量的情况下,他们宁愿使用一封电子邮件将所有商场聚集在一起,以保存垃圾邮件。但是,当您将此类通知(尤其是在日常级别上)混为一谈时,您将自己与收到通知的事情断开连接(最多 24 小时)。两者兼而有之非常困难,因为该应用程序以某种方式需要知道"我即将收到一堆订单,所以我应该等待发送这些订单"或"这只是一个订单,我在一段时间内不会有另一个订单,所以我现在可以发送它",我敢打赌这是用户更喜欢的, 但是很难构建(预知很难)。

我想你可能想问用户他们对通知的期望是什么。如果他们希望这些通知提醒他们这些信息,并可能触发某些内容,那么每日摘要可能对他们来说并不理想(除了高容量情况之外)。

我将继续假装用户更喜欢每日摘要(因为这是您实际上必须更改某些内容的情况)。我将构建一个系统,其中您有一个核心的"通知"表,您可以在其中存储每个事件将触发通知的记录,然后是第二个带有UserId和NotificationId的多对多表,然后是一个指示通知是否已发送的标志。然后,您只需要在某个地方放置一个应用程序,以设定的时间间隔(每天,每小时等)检查多对多表中需要发送的电子邮件,对它们进行分组,然后发送它们。

通知

  • 通知标识
  • 。(与通知相关的其他栏目)

用户

  • 用户标识

用户通知

  • UserNotificationId(某种形式的主键)
  • 用户标识 (FK)
  • 通知标识 (FK)
  • 已发送(位)

您还可以借助这些表上的一些 DateTime 列和用户首选项,设置一个系统,其中应用程序等待 15 分钟发送通知,如果在这 15 分钟的时间跨度内发生另一个通知,它会重置冷却时间,直到 15 分钟过去没有新事件,然后对所有通知进行分组并发送它们。这肯定更复杂,但对用户来说可能是"两全其美"。高容量情况将被方便地集中在一起,而其他通知只会延迟 15 分钟(或任何"冷却时间"

通知是表面上很简单的事情之一,但是一旦您深入研究用户想要从中得到什么,就会被吹走,因此为什么没有一种适合所有人的鞋子。

我认为

这是我在一个项目中所做的两个解决方案。

  1. 使用触发器并通过 SQL 邮件发送电子邮件
  2. 使用 Windows 服务并每天运行一次,您只需一封电子邮件即可发送所有摘要信息。

我不认为我们在这里讨论实际的逻辑,相反,我们正在讨论方法。我主要看到两种选择:

  1. 每次触发规范化数据的电子邮件通知时计算和创建摘要类型的电子邮件(使用 #last-update)

  2. 对数据进行非规范化,事先准备汇总内容,并按照预定时间发送。

如果一个人选择了所有电子邮件通知,那么您可以立即发送电子邮件,否则您可以一天设置一次,并根据@tede24的建议使用 Quazrtz 或 Hangfire 异步发送这些通知。我个人更喜欢挂火和使用它。