将更新排队的建议通过asp.net-mvc应用程序发送出去?

时间:2016-01-23 23:19:00

标签: c# asp.net-mvc email notifications scheduled-tasks

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

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

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

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

7 个答案:

答案 0 :(得分:3)

这里有三件事需要解决:

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

存储邮件非常简单,您可以使用收件人ID创建包含各个邮件的数据库表。

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

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

如果您不想使用任何其他库,则可以设置操作方法来执行此作业,并且只需从计划的Windows作业或任何site-alive pinger服务定期调用操作方法。您可能希望保护此操作方法,或者放置一些逻辑来一天只处理几次队列。

如果第三方图书馆不成问题,那么Scott Hanselman会在不久前收集一份可能的选项列表see here。正如其他人所提到的,Hangfire.io是一种受欢迎的选择。

答案 1 :(得分:2)

我会用日期来做这个伎俩:

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

关键是您需要在应用中使用一些后台作业处理组件来安排工作并监控运行。我使用hangfire.io来完成工作,效果很好

答案 2 :(得分:1)

写在记事本中的代码我将在明天检查。

更新:我已经检查了底部的代码,它在SQL Server中运行良好。

最简单,最简单的方法是将字段last_update_date添加到orders表中,然后:

这段代码会在一段时间内返回所有更新的记录,并且用户订阅了订单

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';

答案 3 :(得分:0)

在digest-type update sysem的情况下,我会考虑将所有电子邮件存储到单独的表中,并创建一个触发器 - 一天运行一次的Windows服务或运行控制台触发的计划任务一种功能,可以将表中的一个人的消息编译成一封电子邮件,然后处理发送。

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

跟踪上次发送消息的时间应该很容易,但是您应该记住,无论上次发送消息的时间是什么,客户都想知道。让他们决定选择。

答案 4 :(得分:0)

你肯定需要某种形式的后台处理,大量的解决方案,但不知道这个网站在哪里以及如何托管我将等待在这方面提供建议。

至于通知本身。这听起来像一个超级简单的请求,但是用户对通知的期望是什么样的时间框架?他们是否使用它们来检查订单,还是只是数据给他们?关于即时通知的好处是你知道用户可能喜欢的实时发生的事情。然而,在高容量的情况下,他们会更喜欢将所有商城集中在一起的一封电子邮件,以节省垃圾邮件。但是当你把这样的通知(特别是在每日级别)上混淆时,你将自己(最多24小时)与你收到通知的东西断开连接。这两者都很难,因为应用程序会以某种方式需要知道“我即将获得一堆订单,所以我应该等待发送这些订单”或“这只是一个订单,我不会再有另一个订单所以我现在可以发送它“,我打赌是用户更喜欢的,但建筑师很难(预知很难)。

我想你可能想要问用户他们对通知的期望是什么。如果他们希望这些通知提醒他们这些信息,并可能触发他们的结果,那么每日摘要可能并不适合他们(在大量情况之外)。

我将继续假装用户更喜欢每日摘要(因为这是您实际需要更改内容的情况)。我将构建一个系统,在该系统中,您有一个核心“通知”表,其中存储将触发通知的每个事件的记录,然后存储具有UserIds和NotificationIds的第二个多对多表,然后是表示通知已发送的标记或不。然后你只需要一个应用程序到某个地方,在设定的时间间隔(每天,每小时等)检查多对多的表,它需要发送的电子邮件,分组,并发送出去。

通知

  • NotificationId
  • ...(与通知相关的其他栏目)

用户

  • 用户ID
  • ...

UserNotifications

  • UserNotificationId(某种形式的主键)
  • UserId(FK)
  • NotificationId(FK)
  • 已发送(位)

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

通知是表面上看起来很简单的事情之一,但是一旦你深入了解用户想要的东西就会被吹走,因此为什么没有一个适合所有人的鞋子。

答案 5 :(得分:0)

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

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

  2. 取消规范化数据并预先准备好摘要内容,并按照预定时间发送。

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

答案 6 :(得分:0)

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

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