카우치베이스 6.6의 출시와 함께 이벤트 서비스의 기능이 크게 개선되었습니다.
취소 타이머() 함수를 사용하거나 기존 타이머와 동일한 참조 식별자를 가진 새 타이머를 생성하여 취소할 수 있는 새로운 이벤트 타이머가 도입되었습니다. 반복 타이머도 완벽하게 지원되며, 타이머 콜백을 사용하여 새로운 타이머를 생성함으로써 반복 로직을 쉽게 만들 수 있습니다. 타이머 스케줄링을 사용하면 성능에 부정적인 영향을 미치지 않고 며칠, 몇 주 또는 몇 년 후의 타이머를 만들 수 있습니다. OnDelete 핸들러는 이제 새로운 "options" 매개변수를 사용해 문서가 삭제되었는지 만료되었는지를 표시합니다. 이제 UI의 주요 이벤트 통계가 각 함수 수명 주기 제어와 함께 배치됩니다.
이러한 개선 사항을 통해 강력한 비즈니스 로직을 만드는 데 필요한 노력과 코드를 간소화할 수 있습니다.
전제 조건
이 문서에서는 주요 이벤트 최신 GA 릴리스, 즉 Couchbase 버전 6.6.0에 추가된 개선 사항과 각 항목에 대해 작동하는 기본 예제를 제공합니다. 그러나 이 문서에서 제공하는 이벤트 함수 중 어느 것도 이전 버전의 카우치베이스 서버에서 큰 변경이나 복잡한 작업 없이 "있는 그대로" 작동하지는 않는다는 점을 이해해 주시기 바랍니다..
카우치베이스 또는 이벤트 서비스에 익숙하지 않은 경우 시작하기와 이벤트 예시 중 하나를 구체적으로 참조하세요:
- 의 지침에 따라 작동하는 Couchbase 6.6.0 서버를 설정합니다. 여기서 시작하세요!
- 기본 이벤트 개념과 기본 이벤트 함수를 배포하는 방법을 모두 이해합니다. 문서 보관 예제.
이제 이벤트 타이머를 취소할 수 있습니다.
취소 타이머() 함수를 추가하거나 기존 타이머와 동일한 참조 식별자를 가진 새 이벤트 타이머를 생성하면 아직 실행되지 않은 활성 타이머를 취소할 수 있습니다. 이 기능 개선으로 강력한 비즈니스 로직을 만드는 데 필요한 코드가 간소화되었습니다.
개발자는 더 이상 필드와 로직을 추가하고, 실행 중인 타이머가 '오래되어' 새로운 타이머로 대체되지 않도록 추가 확인 작업을 수행하지 않아도 됩니다.
예시:
- 이벤트용 '소스' 버킷과 '메타데이터' 버킷을 만듭니다.
- 이 함수를 배포합니다(아래 코드).
- 를 사용하여 소스 버킷에 문서를 만듭니다:
1KEY user_scoreboard::1 and DATA {"type": "user_scoreboard", "id": 1} - 잠시 후 로그를 확인합니다.
- "user_scoreboard::1" 키를 사용하여 문서를 삭제합니다.
- 잠시 후 로그를 확인합니다.
- 이 기능을 배포 해제합니다.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
function UserInactivityCallback(context) { log('user was inactive for 10 minutes', context.docId); /* * take some actions ... */ } function OnUpdate(doc, meta) { if (doc.type != 'user_scoreboard') return; // Create a timestamp 600 seconds from now var tenMinutesFromNow = new Date(); // Get current time & add 600 sec. to it. tenMinutesFromNow.setSeconds(tenMinutesFromNow.getSeconds() + 600); // Every mutation to the user's scoreboard will result in a new Timer but // the old timers will be canceled as they have the same identifier, meta.id. createTimer(UserInactivityCallback, tenMinutesFromNow, meta.id, { "docId": meta.id }); } function OnDelete(meta, options) { if (!(meta.id.startsWith("user_scoreboard:"))) return; log('user scoreboard was deleted for', meta.id); // remove the timer as there is no related document anymore. cancelTimer(UserInactivityCallback,meta.id); /* * take some actions ... */ } |
이제 반복 이벤트 타이머가 완전히 지원됩니다.
반복 타이머가 완전히 지원됩니다. 즉, 타이머 콜백에 의해 호출되는 함수는 새로운 타이머를 안정적으로 생성할 수 있습니다. 이 업데이트를 통해 단일 이벤트 함수가 다른 타이머의 콜백 내에서 새 타이머를 생성하는 복잡한 반복 이벤트를 안정적으로 구현할 수 있습니다.
이전에는 반복되는 일련의 타이머(왼쪽 이미지)를 안정적으로 생성하기 위해 공동 함수가 필요했지만, 6.6 릴리스에서는 반복(또는 예약) 비즈니스 로직을 구현하는 데 필요한 코드가 간소화되었습니다(오른쪽 이미지).

예시:
- 이벤트용 '소스' 버킷과 '메타데이터' 버킷을 만듭니다.
- 함수 설정에서 읽기+쓰기 모드의 소스 버킷에 대한 버킷 별칭을 "src_bkt"로 설정합니다.
- 이 함수를 배포합니다(아래 코드).
- 를 사용하여 소스 버킷에 문서를 만듭니다:
1KEY recurring_timer::1 and DATA {"type": "recurring_timer", "id": 1, "active": true} - 잠시 후 로그를 확인합니다.
- 몇 분 후에 로그를 검사합니다.
- "recurring_timer::1" 키를 사용하여 문서를 변경하고 다음과 같이 "active" 필드를 false로 변경합니다:
-
1KEY recurring_timer::1 and DATA {"type": "recurring_timer", "id": 1, "active": false}
- 잠시 후 로그를 확인합니다.
- 이 기능을 배포 해제합니다.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
function CreateRecurringTimer(context) { log('From CreateRecurringTimer: creating timer', context.mode, context.id); // Create a timestamp 30 seconds from now var thirtySecFromNow = new Date(); // Get current time & add 30 sec. to it. thirtySecFromNow.setSeconds(thirtySecFromNow.getSeconds() + 30); // Create a document to use as out for our context createTimer(RecurringTimerCallback, thirtySecFromNow, context.id, context); } function RecurringTimerCallback(context) { log('From RecurringTimerCallback: timer fired', context); /* * do any sort of recurring work here, just update a date_stamp in a document * written back to the source bucket (but with the ID prefixed whit "cur_") */ src_bkt["cur_" + context.id] = { "last_update": new Date() }; // rearm the timer CreateRecurringTimer({ "id": context.id, "mode": "via_callback" }) } function OnUpdate(doc, meta) { // You would typically filter to mutations of interest if (doc.type !== 'recurring_timer') return; if (doc.active === false) { if (cancelTimer(RecurringTimerCallback, meta.id)) { log('From OnUpdate: canceled active Timer, doc.active', doc.active, meta.id); } else { log('From OnUpdate: no active Timer to cancel, doc.active', doc.active, meta.id); } } else { log('From OnUpdate: create/overwrite doc.active', doc.active, meta.id); CreateRecurringTimer({ "id": meta.id, "mode": "via_onupdate" }); } } |
타이머는 일/주/년 단위로 생성할 수 있습니다.
유휴 상태인 이벤트 시스템에 성능에 부정적인 영향을 미치지 않으면서 타이머를 하나 또는 백만 개까지 만들 수 있습니다. 이 기능은 장기적인 알림 및 고객 재참여 프로그램을 위한 사용 사례를 열어줍니다.
6.5.X 릴리스에서는 유휴 시스템에서 수천 개의 타이머를 생성하면(예: 1시간 이상) 메타데이터 버킷 작업 수가 증가하여 성능에 영향을 미치고 결국 주어진 이벤트 함수에 대한 돌연변이를 차단할 수 있었습니다.[1]
취소 타이머() 작업을 하거나 기존 타이머를 참조로 덮어쓰면 Eventing "메타데이터" 버킷에 임시 문서가 생성되며, 결국 이러한 문서는 삭제됩니다.[2]
예시:
많은 이벤트 타이머(이 경우 50,000개)를 생성하고 미래(96시간까지)로 예약한 다음 전체 세트를 취소(또는 모두 콜백 루틴을 실행하도록 허용)하는 데모를 시연합니다. 타이머 콜백).
- 이벤트용 '소스' 버킷과 '메타데이터' 버킷을 만듭니다.
- 이 함수를 배포합니다(아래 코드).
- 소스 버킷에 우리가 살펴볼 데이터만 있는 문서를 만듭니다.
1KEY spawn_50k_timers::1 - 1~2분 후에 로그를 확인합니다.
- "spawn_50k_timers::1" 키를 사용하여 문서를 삭제합니다.
- 1~2분 후에 로그를 확인합니다.
- 이 기능을 배포 해제합니다.
50만 이벤트 타이머가 생성되고 (취소되지 않고) 실행되는 것을 확인합니다:
- 기능 변경 지연 분을 1로 편집합니다(4일을 기다리지 않으려는 경우).
- 수정된 함수를 배포합니다(아래 코드).
- 소스 버킷에서 KEY만 볼 수 있으므로 아무 데이터로나 문서를 만듭니다.
1KEY spawn_50k_timers::1 - 2분 후에 로그를 검사합니다.
- "spawn_50k_timers::1" 키를 사용하여 문서를 삭제합니다.
- 1~2분 후에 로그를 확인합니다.
- 이 기능을 배포 해제합니다.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
function TimerCallback(context) { if (context.timer_num == 1 || context.timer_num == 50000) log('TimerCallback: fired timer #', context.timer_num); /* * take some actions ... */ } function OnUpdate(doc, meta) { if (meta.id != 'spawn_50k_timers::1') return; // Create a timestamp 96 hours from now (4 days) var delayMinutes = 60*96; var futureTime = new Date(); futureTime.setMinutes(futureTime.getMinutes() + delayMinutes); // make 50K timers for (var i=1; i<= 50000; i++) { var timer_id = "tmr_" + i; if (i == 1 || i == 50000) log('OnUpdate: create timer # ', i, timer_id); try { createTimer(TimerCallback, futureTime, timer_id, { "docId": meta.id, "timer_num": i}); } catch (e) { log('OnUpdate: create #', i, " error ", e); } } } function OnDelete(meta, options) { if (meta.id != 'spawn_50k_timers::1') return; /* * Remove the 50K timer as there is no related control document anymore. * * Note on a cancel or overwrite there will be documents which will be * cleaned up at a) initial firing schedule of the Timers, b) undeployment * of the function, or c) a lazy cleaning process by the Eventing Service. */ for (var i=1; i<= 50000; i++) { var timer_id = "tmr_" + i; if (i == 1 || i == 50000) log('OnDelete: clear timer # ', i, timer_id); try { cancelTimer(TimerCallback, timer_id); } catch (e) { log('OnDelete: clear timer #', i, " error ", e); } } } |
이제 이벤트 통계가 수명 주기 제어와 함께 배치됩니다.
이제 UI에서 4개의 주요 이벤트 통계가 각 함수 수명 주기 컨트롤과 함께 배치됩니다. 이러한 개선 사항으로 코딩 작업과 이벤트 함수를 진단하는 작업이 간소화되어 강력한 비즈니스 로직을 빠르게 만들 수 있습니다.
개발자나 관리자는 함수의 수명 주기 컨트롤에서 벗어나지 않고도 함수가 잘못 작동하는 것을 즉시 확인할 수 있습니다.
예시:
- 이벤트용 '소스' 버킷과 '메타데이터' 버킷을 만듭니다.
- 소스 버킷에 KEY와 DATA를 몇 개 문서화하세요.
- 수정된 함수(아래 코드)를 배포하면 변수 앞에 var를 넣는 것을 잊어버리는 구문 오류가 발생합니다.
|
1 2 3 4 5 |
function OnUpdate(doc, meta) { log('docId', meta.id); // this is an error missing 'var' a = 2; } |
- 이벤트 기능이 배포되면 개발자에게 문제가 발생했다는 즉각적인 피드백이 제공됩니다.

- 사용자는 피드백(예: '빨간색' 실패)에 응답하고 오류의 원인을 찾기 위해 함수를 검사할 수 있습니다.

- 이 이벤트 함수를 배포 해제합니다.
- 이 경우 오류를 수정하여 4줄을 만듭니다: "var a=2;".
- 이 이벤트 함수를 다시 배포합니다.
- 코드가 수정되면 개발자는 이제 성공 카운터가 증가함에 따라 올바른 동작과 진행 상황을 확인할 수 있습니다.

이제 온삭제 핸들러가 삭제 또는 만료를 표시합니다.
OnDelete 핸들러는 이제 새로운 매개변수 "옵션"을 통해 문서가 삭제되었는지 만료되었는지를 표시합니다. 자주 요청되는 이 기능을 통해 삭제 유형에 따라 다른 로직을 실행할 수 있습니다.
예시:
- 이벤트용 '소스' 버킷과 '메타데이터' 버킷을 만듭니다.
- 이 함수를 배포합니다(아래 코드).
- KEY만 보므로 소스 버킷에 DATA가 있는 문서를 만듭니다.
1KEY doc_to_delete::1 - 몇 초 후 로그 검사
- "doc_to_delete::1" 키를 사용하여 문서를 삭제합니다.
- 1분 후 로그 검사
- 이 기능 배포 취소
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
function OnDelete(meta, options) { if (options.expired) { log("doc expired:",meta.id); /* * take some action ... */ } else { log("doc deleted:",meta.id); /* * take some other action ... */ } } |
Couchbase Server 6.6 리소스 살펴보기
참조
- 카우치베이스 이벤트 문서:
https://docs.couchbase.com/server/current/eventing/eventing-overview.html - 카우치베이스 이벤트 예시:
https://docs.couchbase.com/server/current/eventing/eventing-examples.html - 카우치베이스 서버 6.6의 새로운 기능:
https://docs.couchbase.com/server/6.6/introduction/whats-new.html - 이벤트에 대한 카우치베이스 블로그:
https://www.couchbase.com/blog/tag/eventing/
6.6의 기능이 마음에 드셨는지, 앞으로 비즈니스에 어떤 도움이 될지 여러분의 의견을 듣고 싶습니다. 댓글을 통해 의견을 공유해 주세요. 포럼.
각주
[1] 심각도는 다음과 같은 요소에 따라 결정됩니다. a) 활성 타이머를 보유하고 있는 vBucket의 수입니다. 따라서 향후 타이머가 몇 개만 있는 경우 문제가 눈에 띄지 않거나 구체화되지 않을 수 있습니다. 그리고 b) 이벤트 타이머가 최근에 vBucket에서 실행되었는지 여부(기능별로 지정된 vBucket에 대한 문제를 해결합니다). 따라서 단기 타이머 활동이 많은 6.5 시스템에서는 타이머가 먼 미래로 예약되어 있어도 이 문제가 발생하지 않습니다. 6.6에서는 이 문제가 발생하지 않습니다.
[2] 취소 타이머() 연산이나 참조로 기존 타이머를 덮어쓰는 경우, Eventing "메타데이터" 버킷에 임시 문서가 생성되며, 이는 a) 취소된(또는 덮어쓴) 타이머의 초기 발동 일정 또는 b) 함수 배포 해제 시점에 정리됩니다. 이 동작은 예약된 시간에 실행되는 타이머와는 달리 타이머가 실행되는 즉시 관련된 모든 Eventing 메타데이터가 Eventing "메타데이터" 버킷에서 정리됩니다.