假设有一个系统,当发生某些事情时,数据库中的行会被填充:
- 当用户简单登录时,会在表
user_logins
中向数据库中插入一行登录类型和时间 - 当操作员呼叫用户时,在表
outgoing_calls
中的数据库中插入一行,其中包含操作员id、用户id和日期 - 当操作员不回答用户调用时,会在数据库中插入一行,其中包含日期、用户id和类型调用
然后,在一段时间后,比如一个月,我们需要一份关于谁给谁打电话、有多少电话没有被接听等的报告。应该使用什么模式来组织此功能?
乍一看,这个过程看起来像是日志记录,但当我们以某种格式存储消息(dateprocessId messageWithPlaceHolders)时,日志记录就是一个过程。因此,使用日志记录系统是不太合适的。
从另一个角度来看,它看起来像是事件处理,但当"事件"发生、没有侦听器、没有队列时,没有必要执行任何操作。只是存储到数据库以便进一步报告。
那么,应该使用什么模式或技术来有效地实现此功能呢?
您的要求是每月生成一份谁打电话给谁的报告,这样您就可以了解您的电话是否成功(或您有什么原因)。
您不需要考虑与日志记录或事件处理或其他类似之处。只需自上而下地分析问题,就可以获得完成任务所需的最少工作量:
- 你需要每月生成一份报告
- 为此,您需要运行一个每月至少生成一次结果的作业
- 为此,您需要以工作能够理解的格式存储事件
因此,一个好的解决方案是每月运行一次批处理作业。这可以是手动运行的java进程、cron作业、hadoop任务等等。。。取决于您的技术堆栈。您的事件需要在发生时存储。同样,根据您的堆栈,它可以是关系数据库、键值存储、带有日志行的文件。。。,在您的技术堆栈中最容易使用的。
所有这些选择都可能是好的,但有些可能更好。例如,我建议不要使用纯字符串日志记录。您需要提取时间、数字等结构化属性,因此更喜欢有助于保持类型安全的格式。
我会使用在您的业务服务模式中实现它:
void login(User user) {
entityManager.persist(new UserLogin(user));
}
void call(Operator op, User user) {
entityManager.persist(new PhoneCall(op, user));
}
void missedCall(User user, Operator op) {
entityManager.persist(new MissedCall(user, op));
}
假设您的业务服务在未接来电时得到通知。如果仅仅是没有答案就应该触发数据库更新,我会改变逻辑,记录成功的答案:
void answeredCall(UserCall call, Operator op) {
entityManager.merge(call).setAnsweredBy(op);
}
并报告CCD_ 3。
在任何一种情况下,我都会通过查询数据库来进行报告。
替代
如果您的业务服务中的大多数操作都需要这样记录,我可能会使用AOP拦截器来实现自动化。