2013-06-12 2 views
0

"이벤트"(회의, 생일 파티 등) 레코드의 db가 있으며 각 이벤트의 필드는 endTime입니다. 이벤트가 끝나면 과거 이벤트마다 2-3 개의 이메일을 보내고 싶습니다. 지금 각 db 레코드 타임 스탬프를 기반으로 알림 전자 메일 보내기

, 나는 지난 시간에 종료 된 모든 이벤트를 찾기 위해 매시간 cron 작업을 실행, 그래서 같은 같습니다

  • 2:01 오후를 : 모든 이벤트는 1-2pm 사이에 종료 찾기 3:01 pm에 이메일
  • 을 보내 : 오후 2시 -3시 사이에 끝나는 모든 이벤트를 찾을 수, 4:01 pm에 이메일
  • 을 보내 : 3-4pm 사이에 끝나는 모든 이벤트를 찾을 수, 5:01 pm에 이메일
  • 를 보냅니다. ..

그러나 오후 3시 01 분 작업이 실패한 경우 (Heroku가 내 휴식 API를 충돌시키고 이메일 서비스 제공 업체가 다운되는 경우 등) 오후 2시 사이에 종료되는 이벤트는 이메일을받지 못합니다.

이메일이 성공적으로 전송 된 경우 현재 db 레코드는 notified으로 표시되지 않습니다. 그렇게해야만 cron 스크립트를 "현재 시간 이전에 모든 레코드를 찾으십시오."(이전에 보내지 않은 레코드를 모두 잡는 곳인 notified=false)가 변경 될 수 있습니까? 그런 다음 성공적으로 보내는 전자 메일의 각 유형별로 플래그를 설정 하시겠습니까?

플래그를 설정하지 않는 더 깨끗한 방법이 있습니까?

는 (그것은 도대체이 질문에 대한 제목과 태그와 함께오고 - 제안/편집 환영!)

답변

0

notified 플래그 문제는 그냥 WHERE notified = FALSE1 효율적으로하기 위해 인덱스를 필요로한다는 것이다, 그러나 TRUE 값은 쿼리에서 결코 다시 사용되지 않더라도 인덱스에 남아 있습니다.

시간이 흐르면 ​​색인에 작은 부분 (유용함)과 거대한 부분 (공간을 낭비)이 생깁니다.

  • 오라클 doesn't index NULLs, 그래서 대신 TRUE를 사용하여 DBMS가 지원하는 경우, 인덱스에서 TRUE를 제거하기 위해 어떤 종류의 partial index를 사용합니다.
  • MS SQL Server에서 filtered index을 사용하십시오 (예 : CREATE INDEX ... WHERE notified = 0).
  • PostgreSQL에서 partial index을 사용하십시오. 알림 무리가 성공적으로 전송 될 때마다 해당 필드를 LAST_SENT 2 및 업데이트 :

는 다른 방법으로, 정확히 하나의 행과 하나 개의 필드로 별도의 테이블을 만듭니다. 이것은 물론 순서가 잘못된 알림을 보내는 것을 배제하며 실패한 알림을 건너 뛰지 않아도되므로 부분적으로 오류를 신중하게 처리해야합니다.

1


는 데이터베이스에 적합한 어떤와 FALSE 교체합니다.테이블이 기본 키로 자동 증가 정수를 사용하는 경우

2, 타임 스탬프가 고유하지 않을 수 있습니다 가장자리 사례를 방지하기 위해, 대신에 타임 스탬프의 LAST_SENT을 위해 그것을 사용하는 것이 좋습니다. 와

+0

이메일 유형별로 필드 (및 색인)를 추가하는 것이 좋은 방법인지 확실하지 않습니다. 그러나 제가 그렇게한다면 도움이 될 것입니다. – thatmarvin

+0

@thatmarvin 한 가지 대안은 전송 된 테이블과 보내지 않은 알림을위한 테이블 두 가지를 갖는 것입니다. 알림이 전송되면 한 테이블에서 다른 테이블로 이동하십시오. 분명히 두 테이블 모두에 걸쳐 있고 FK를 복제 할 수있는 키가 필요하다면 문제가 될 수 있지만, DBMS가 지원하는 경우 테이블을 분할하여 (논리적으로 하나의 테이블이므로) 완화 할 수 있습니다. –

+0

테이블이 여전히 작기 때문에 지금은 가능한 가장 간단한 솔루션을 원합니다. 실제로 MongoDB를 사용하고 있지만 postgresql으로 곧 전환 할 계획입니다 (따라서 오해의 소지가있는 태그). 내가 찾고있는 대답은 "그렇습니다, 당신은 확실히 이것을 할 깃발이 필요합니다"또는 "아니오, 깃발없이 할 수있는 다른 일이 있습니다"입니다. 네가 "예"라고 말하는 것처럼 들리네! – thatmarvin

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을 콜렉션으로 읽으십시오. 컬렉션에서 데이터를 보내고 정보를 업데이트하십시오. events_sent_tbl 테이블에 FORALL로 덤프합니다.