gpt4 book ai didi

java - 防止从Google App Engine发送重复的每日报告电子邮件

转载 作者:太空宇宙 更新时间:2023-11-04 13:54:44 24 4
gpt4 key购买 nike

我们出现了问题。我们的客户抱怨他们的收件箱中收到重复的电子邮件。几天中,完全相同的电子邮件最多可能有5或6个实例。我们不明白为什么。该代码已至少被重写过一次,但问题仍然存在。

我会尽力解释这一点...但是有点复杂:O(

我们希望每天晚上(清晨)向用户发送包含使用情况统计信息的每日报告。因此,我们有一项计划工作:

<cron>
<url>/redacted/report/url</url>
<description>Send out daily reports to active subscribers</description>
<schedule>every 2 hours</schedule>
</cron>


cron作业点击servlet get方法:

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
AccountFilter filter = AccountFilter.forWebSafeName(req.getParameter("filter"));
createTasks(filter, null);
}


使用空游标调用createTasks方法:

private void createTasks(AccountFilter accountFilter, String cursor) {
try {
PagedResults<Account> pagedAccounts = accountRepository.getAccounts(accountFilter.getFilter(), 50, cursor);
createTaskBatch(pagedAccounts);

// If there are still more results in cursor, then send cursor back to this servlet's doPost method so we don't hit the request time limit
if (pagedAccounts.getCursor() != null) {
getQueue(QUEUE_NAME).add(withUrl(WORKER_URL).param(CURSOR_KEY, pagedAccounts.getCursor()).param(FILTER_KEY, accountFilter.getWebSafeName()));
}
} catch(Exception ex) {
logger.log(Level.WARNING, "Problem creating daily report task batch for filter " + accountFilter.getWebSafeName(), ex);
}
}


它将抓取50个帐户并对其进行遍历,从而为此时应发送的电子邮件创建新的排队作业。在创建新的排队任务之前,有代码可以明确检查上次报告发送的时间戳并更新时间戳。这应该在不发送报告而不是发送重复报告的一边犯错:

private void createTaskBatch(PagedResults<Account> pagedAccounts) {
// GAE datastore query might return duplicate results?!
List<Account> list = pagedAccounts.getResults();
Set<Account> noDuplicates = new HashSet<>(list);
int dups = list.size() - noDuplicates.size();
if ( dups > 0 ){
logger.warning ("Accounts paged results contained " + dups + " duplicates!");
}
for (Account account : noDuplicates) {
try {
if (lastReportSentOver12HoursAgo(account)) {
List<Parent> parents = parentRepository.getVerifiedParentsForAccount(account.getId());
if (eitherParentSubscribed(parents)) {
List<AccountUser> users = accountUserRepository.listUsers(account.getId());
List<Device> devices = getUserDevices(account, users);
if (!devices.isEmpty()) {
DateTimeZone tz = getMostCommonTimezone(devices);
if ( null == tz ){
logger.warning("No timezone found for account: " + account.getId() );
}
else{
// Send early in the morning as the report contains the previous day's stats
if (now(tz).getHourOfDay() < 7) {
// mark sent now because queue might not be processed for a while
// and the next cursor set might contain some of the same accounts
accountRepository.markReportSent(account.getId(), now());
getQueue(QUEUE_NAME).add(withUrl(DailyReportServlet.WORKER_URL).param(DailyReportServlet.ACCOUNT_ID, account.getId()).param(DailyReportServlet.COMMON_TIMEZONE, tz.getID()));
}
}
}
}
}
} catch(Exception ex) {
logger.log(Level.WARNING, "Problem creating daily report task for " + account.getId(), ex);
}
}
}


Servlet POST方法负责通过游标方法处理结果的后续页面:

public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
AccountFilter accountFilter = AccountFilter.forWebSafeName(req.getParameter(FILTER_KEY));
logger.log(Level.INFO, "doPost hit from task queue with filter " + accountFilter.getWebSafeName());
String cursor = req.getParameter(CURSOR_KEY);
createTasks(accountFilter, cursor);
}


还有另一个处理每个报告任务的servlet,它仅创建电子邮件内容并在com.sendgrid.SendGrid类上发送呼叫。

最终可能会在Datastore中保持一致性,但是应该在几秒钟内解决该问题,但我看不出这如何解决抱怨的客户数量和某些客户看到的重复数量。

救命!有任何想法吗?我们在某个地方呆呆吗?

更新

为了清楚起见...电子邮件发送任务队列最终使用此方法,该方法可以捕获异常并将其报告给我们。对于重复的案例,我们没有看到例外:

private void sendReport(Account account, DateTimeZone tz) throws IOException, EntityNotFoundException {
try {
boolean sent = false;
Map<String, Object> root = buildEmailData(account, tz);
for (Parent parent : parentRepository.getVerifiedParentsForAccount(account.getId())) {
if (parent.getEmailPreferences().isSubscribedReports()) {
emailBuilder.send(account, parent, root, "report", EmailSender.NOTIFICATION);
sent = true;
}
}
if ( sent ){
accountRepository.markReportSent(account.getId(), now());
}
} catch (Exception ex) {
String message = "Problem building report email for account " + account.getId();
logger.log(Level.WARNING, message, ex);;
new TeamNotificationEvent( message + " : exception: " + ex.getMessage()).fire();
throw new IOException(message, ex);
}
}


附加调试日志记录后的更新2

我看到两个POSTS同时进入具有相同光标的相同任务队列:

09:35:08.397 2015-04-30 200 0 B 3.78s / ws / notification / daily-report-task-creator
  0.1.0.2--[30 / Apr / 2015:01:35:08 -0700]“ POST / ws / notification / daily-report-task-creator HTTP / 1.1” 200 0“ http://screentimelabs.appspot.com/ws/notification/daily-report-task-creator”“ AppEngine-Google; (+ http://code.google.com/appengine)“” screentimelabs.appspot.com“ ms = 3782 cpu_ms = 662 queue_name = dailyReports task_name = 8168414365365326983 instance = 00c61b117c33a909790f0d1882657e04f40b2c7e app_engine_release = 1.9.20
    09:35:04.618 com.screentime.service.taskqueue.reports.DailyReportTaskCreatorServlet createTasks:调用过滤器的createTasks:带有游标的ACTIVE:E-ABAIICO2oQc35zY3JlZW50aW1lbGFic3InCxIHQWNjb3VudCIaamFybW8ua2AcCbbA8B2B3B

09:35:08.432 2015-04-30 200 0 B 8.84s / ws / notification / daily-report-task-creator
  0.1.0.2--[30 / Apr / 2015:01:35:08 -0700]“ POST / ws / notification / daily-report-task-creator HTTP / 1.1” 200 0“ http://screentimelabs.appspot.com/ws/notification/daily-report-task-creator”“ AppEngine-Google; (+ http://code.google.com/appengine)“” screentimelabs.appspot.com“ ms = 8837 cpu_ms = 1348 queue_name = dailyReports task_name = 50170612326424582061 instance = 00c61b117c2bffe8de313e96fea8aeb813f4b20f app_engine_release = 1.9.20 trace_id = 7e5c034f2e6e
    09:34:59.608 com.screentime.service.taskqueue.reports.DailyReportTaskCreatorServlet createTasks:调用过滤器的createTasks:带有游标的ACTIVE:E-ABAIICO2oQc35zY3JlZW50aW1lbGFic3InCxIHQWNjb3VudCIaamFybW8ua2AcCbBn8A2A2C

搜索1个特定的帐户ID,我看到以下请求:

09:35:08.397 2015-04-30 200 0 B 3.78s / ws / notification / daily-report-task-creator

09:35:08.432 2015-04-30 200 0 B 8.84s / ws / notification / daily-report-task-creator

09:35:08.443 2015-04-30 200 0 B 6.73s / ws / notification / daily-report-task-creator

2015-04-30 09:35:10.541 200 0 B 4.03s / ws / notification / daily-report-task-creator

09:35:10.690 2015-04-30 200 0 B 11.09s / ws / notification / daily-report-task-creator

2015-04-30 09:35:13.678 200 0 B 862ms / ws / notification / daily-report-worker

2015-04-30 09:35:13.829 500 0 B 1.21s / ws / notification / daily-report-worker

2015-04-30 09:35:14.677 200 0 B 1.56s / ws / notification / daily-report-worker

09:35:14.961 2015-04-30 200 0 B 346ms / ws / notification / daily-report-worker

有些具有重复的游标值。

最佳答案

我会猜测,因为我看不到任务队列代码。您可能没有正确处理任务队列中的错误。如果任务队列因错误而结束,则gae将对其重新排队。因此,如果已经发送了一些电子邮件,该任务仍将再次运行。您需要一种方法来记住您在任务队列中已处理的内容,因此重试不会重新处理这些内容。

关于java - 防止从Google App Engine发送重复的每日报告电子邮件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29940899/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com