요약

  • RFC 3343은terminate처리와 그에 대한 응답 전송 이후에는 서비스가 더 이상 갱신을 보내지 않는다고 약속하면서도, 이미 전송 중이던 이전의 presence 또는 watcher 갱신은 여전히 도착할 수 있다고 경고했습니다.
  • 따라서 코드 250 취소 응답은 서비스 측 차단의 증거일 뿐 큐 배수(drainage)가 아니었습니다. 트랜잭션 상관, 메시지 연령, 현재 구독 세대, 소비자 처리는 각각 별개의 증거로 남았습니다.

취소는 흔히 시간 위에 그은 선으로 상상됩니다. 선 앞의 모든 것은 해당 작업에 속하고, 선 뒤의 것은 그렇지 않다는 식입니다. RFC 3343은 보다 물리적인 경계를 그렸습니다. 서비스는 terminate 요청을 처리한 뒤 새 작업을 생성·전송하는 것을 멈출 수 있지만, 그보다 먼저 방출된 작업은 여전히 릴레이 메시 안에 남아 있을 수 있었습니다. 이 응답이 표시하는 것은 소스가 이후에 무엇을 할지이며, 하류의 모든 통로가 이미 끝낸 일이 아니었습니다.

이 구분은 익숙한 경합 상황을 증거 문제로 바꿉니다. 늦게 도착한 갱신을 받은 소비자는 취소가 거짓이라고 판단해서는 안 됩니다. 동시에 그 갱신이 현재 구독을 대표한다고 가정해서도 안 됩니다. 두 기록은 모두 진본이면서 전달 사슬의 서로 다른 시점을 가리킬 수 있습니다.

세 가지 지속 연산으로 구성된 서비스

APEX presence 서비스는 관리 도메인 안의 잘 알려진 엔드포인트apex=presence에 위치했습니다. 애플리케이션은 presence 항목을 게시하거나, 게시자의 presence를 구독하거나, 해당 게시자를 구독 중인 엔드포인트 목록을 감시할 수 있었습니다.

구독은 즉시 현재 presence 항목을 반환했습니다. 지속 시간이 0이 아니면 항목이 바뀔 때마다 새 게시 연산을 만들어 내다가 결국 terminate로 끝났습니다. 지속 시간이 0인 구독은 일회성 폴링으로 동작했습니다. watch는 먼저 코드 250을 받은 뒤 현재 구독자마다 하나의 notify를 받고, 이후 구독이 시작되거나 끝날 때 알림을 받았습니다.

이들은 격리된 요청-응답 쌍이 아니라 장기 연산이었습니다. presence 서비스는 presence 항목과 진행 중인 연산을 모두 영속화해야 했습니다. 서비스가 발원한 publish와 notify 메시지는 그 원인이 된 구독 또는 watch의 트랜잭션 식별자를 담았습니다. 이 식별자는 계보를 보이게 했지만, 나중에 도착하는 모든 메시지를 현재로 만들지는 않았습니다.

terminate가 실제로 약속한 것

subscribe 또는 watch 연산은 소비자나 서비스 어느 쪽이든 끝낼 수 있었습니다. 소비자는 트랜잭션 식별자와 함께terminate를 보냈습니다. 그 식별자가 해당 발원자의 진행 중인 연산을 가리키지 않으면 서비스는 오류 550을 반환했습니다. 그렇지 않으면 서비스는 연산을 제거하고 코드 250으로 응답했습니다.

그런 다음 사양은 곤란한 부분을 직접 밝힙니다. 종료 이후 발원자는 추가로 presence 또는 watcher 갱신을 받을 수 있으며, 서비스는 terminate를 처리하고 응답을 보낸 뒤에는 더 이상 갱신을 보내지 않지만 이전 갱신은 전송 중일 수 있다는 것입니다.

따라서 응답이 담는 것은 범위가 정해진 사실입니다. 활성 연산이 서비스에서 끝났고 서비스의 이후 전송 동작이 바뀌었다는 것입니다. 그것은 모든 릴레이 버퍼, 연결, 스케줄러 또는 소비자 입력 큐가 비었다고 말하지 않습니다. 이미 메시에 넘겨진 publish나 notify를 철회하지도 않습니다.

현대 시스템은 때로 이보다 강한 성질을 드레인 배리어(drain barrier)라고 부릅니다. 드레인 배리어는 경계 이전의 모든 작업이 도착했거나, 정의된 규칙에 따라 폐기되었거나, 회계적으로 처리되었다는 증거를 요구합니다. RFC 3343의 terminate 응답은 그런 배리어가 아니었습니다. 문서는 그 간극을 숨기는 대신 보존했습니다.

상관은 유효성보다 오래 남는다

늦게 도착한 갱신은 여전히 이전 트랜잭션 식별자를 담고 있었습니다. 그 덕분에 수신 애플리케이션은 어느 이미 끝난 연산이 그 갱신을 만들었는지 말할 수 있었습니다. 상관은 유용하지만, 내용을 적용하라는 명령은 아니었습니다.

소비자는 연산 세대 또는 묘비(tombstone) 같은 별도의 상태가 필요합니다. 즉 종료 경계와 늦은 메시지 정책을 기록하는 상태입니다. 소비자는 그 갱신을 폐기하거나, 감사용으로 보관하거나, presence 타임스탬프를 더 새 스냅숏과 비교하거나, 조정(reconciliation) 전까지 격리할 수 있습니다. 절대 하지 말아야 할 것은 일치하는 식별자를 구독이 현재 활성화되어 있다는 증거로 대하는 일입니다.

같은 발원자와 주제에 대해 새 구독이 이전 구독을 대체할 때도 같은 분리가 나타납니다. RFC 3343은 계속 진행하기 전에 이전 연산을 암묵적으로 종료했습니다. 논리적 관계의 재사용이 이전 세대의 전송 중 메시지를 지우지는 않았습니다. 세대를 인식하는 대장이 없으면, 이전 연산에서 온 갱신이 새 연산의 첫 갱신으로 오인될 수 있습니다.

presence는 접속 상태가 아니었다

모든 관리 도메인은 엔드포인트가 릴레이 메시에 접속되어 있는지와 무관하게 각 엔드포인트의 presence 항목을 유지했습니다. 각 항목은 게시자,lastUpdate, 게시자 정보, 하나 이상의 튜플을 가졌습니다. 튜플은 목적지 URI,availableUntil시각, 선택적 정보와 기능을 식별했습니다.

따라서 항목의 존재가 살아 있는 접속을 증명하지는 못했습니다.availableUntil주장은 데이터 모델 안에서 해당 실체가 메시지를 수신할 수 있는 최신 시각을 서술했을 뿐, 관측된 전달 결과가 아니었습니다. 종료 후 늦게 도착한 갱신은 저장된 항목의 충실한 복사본이면서도 소비자의 현재 판단에는 운영적으로 낡은 것일 수 있었습니다.

게시는 자신만의 동시성 경계를 사용했습니다. 제공된 presencelastUpdate는 저장된 값과 의미론적으로 일치해야 했고, 그렇지 않으면 서비스가 코드 555를 반환했습니다. 성공 시 서비스는 항목을 갱신하고 새 서비스 시각을 설정한 뒤 250으로 응답했습니다. 이는 서비스에서의 변경을 보호했습니다. 그러나 모든 구독자가 그 변경을 언제 받았는지는 증명하지 않았습니다.

사생활과 역사적 범위

RFC 3343은 2003년 4월에 Experimental로 발표되었고 현재는 Historic입니다. RFC Editor 기록이 현재 상태를 나열하고, 오류 수정 검색이 현재 정정 기록을 제공합니다. 2012년 7월 29일자 IETF 이력에 따르면, IETF가 아는 한 RFC 3340~3343의 구현은 배포된 바 없으며 APEX 기능은 RFC 6120과 6121 하에서 널리 배포된 XMPP가 제공했습니다.

그러한 단서가 붙은 기록은 종료 경합이 채택되지 않은 원인이라고 말하지 않습니다. 구현, 큐 측정 또는 사건도 제시하지 않습니다. RFC의 보안 절은 별도로, 타임스탬프의 오프셋이 위치를 드러낼 수 있어 위치 정보가 민감한 경우-00:00으로 변환할 수 있다고 언급했습니다. 유효한 presence 기록조차 자신의 전달 역학 밖에서 공개에 따른 결과를 지니고 있었습니다.

실질적으로 물려받을 것은 더 좁습니다. 갱신 생성, 전송으로의 인계, 종료 처리, 소스 측 차단, 릴레이 배수, 소비자 도착, 소비자 행동에 대해 별개의 응답을 유지하십시오. 처음 네 개만 존재한다면 다섯째를 만들어 내지 마십시오. 취소는 진실일 수 있으면서 그 과거는 여전히 다가오고 있을 수 있습니다.

출처