0

I have a db of "event" (a conference, birthday party etc.) records, and each event has an endTime field. After an event ends, I'd like to send out 2-3 emails for each past event.

Right now, I run an hourly cron job to find all events that has ended in the past hour, so it looks something like:

  • at 2:01pm: find all events ending between 1-2pm, send emails
  • at 3:01pm: find all events ending between 2-3pm, send emails
  • at 4:01pm: find all events ending between 3-4pm, send emails
  • at 5:01pm: ...

However, say when the 3:01pm job fails for some reason (Heroku crashes my rest api, email service provider goes down etc.), the events ending between 2-3pm won't get emails.

At the moment, my db records are not marked as notified if the emails were sent successfully. Should I do that so I can change the cron script to "find all records before current time where notified=false" (which catches all previously unsent records)? Would you then set a flag for each type of email you send out successfully?

Or is there a cleverer way that avoids setting flags?

(It was hell coming up with the title and tags for this question — suggestions/edits welcome!)

4

2 回答 2

0

flag的问题notified在于它需要一个索引来使WHERE notified = FALSE1有效,但 TRUE 值保留在索引中,尽管再也没有在查询中使用过。

随着时间的推移,您将在索引中有一个小的 FALSE 部分(这很有用)和一个巨大的 TRUE 部分(这只是浪费空间)。如果您的 DBMS 支持它,请使用某种部分索引从索引中删除 TRUE:

或者,创建一个只有一行和一个字段的额外表: LAST_SENT 2,并在成功发送一堆通知时更新该字段。这当然会排除乱序发送通知,您需要小心处理部分失败,因为您不能只是跳过不成功的通知。


1将 FALSE 替换为适合您的数据库的任何内容。

2如果您的表使用自动递增的整数作为主键,请考虑将其用于 LAST_SENT 而不是时间戳,以避免时间戳可能不唯一的极端情况。

于 2013-06-12T10:41:44.940 回答
0
CREATE TABLE events_tbl
(
    e_id    NUMBER
,   e_date  DATE
,   e_info  VARCHAR2(4000)
);

INSERT INTO events_tbl VALUES (43, '2000-01-01 01:10:00', 'event1');
INSERT INTO events_tbl VALUES (44, '2000-01-01 01:15:00', 'event2');
INSERT INTO events_tbl VALUES (45, '2000-01-01 01:20:00', 'event3');
INSERT INTO events_tbl VALUES (46, '2000-01-01 01:25:00', 'event4');

INSERT INTO events_tbl VALUES (47, '2000-01-01 02:10:00', 'event5');
INSERT INTO events_tbl VALUES (48, '2000-01-01 02:15:00', 'event6');
INSERT INTO events_tbl VALUES (49, '2000-01-01 02:20:00', 'event7');
INSERT INTO events_tbl VALUES (50, '2000-01-01 02:25:00', 'event8');

/* table that holds information about sent events */
CREATE TABLE events_sent_tbl
(
    s_e_id NUMBER
,   s_date DATE
);

INSERT INTO events_sent_tbl VALUES (43, '2000-01-01 02:01:00');
INSERT INTO events_sent_tbl VALUES (44, '2000-01-01 02:02:00');

SELECT  *
FROM    events_tbl
WHERE   TO_NUMBER(TO_CHAR(e_date, 'MMDDHH24MiSS')) BETWEEN 0101010000 AND 0101015959
AND     NOT EXISTS
        (
            SELECT  1
            FROM    events_sent_tbl
            WHERE   e_id = s_e_id
        )
;
/*
45  2000-01-01 01:20:00 event3
46  2000-01-01 01:25:00 event4
*/

与:

  • 要发送的事件
  • 发送事件

...在收藏中。将 events_tbl 和 events_sent_tbl 读入集合。发送数据并更新集合中的信息。将它与 FORALL 一起转储到 events_sent_tbl 表中。

于 2013-06-12T11:26:53.540 回答