Repository navigation
Consumer 소유 스레드 기반 타이머 등록·취소 지원 - #65
Merged
Merged
Conversation
- Connection 기반 타이머 요구사항 및 구현 방향 정리 - 작업 문서에 작업 계획 링크 추가 - 요구사항 문서에 작업 계획 링크 추가 - 작업 기록 문서에 계획 작성 내용 추가
- RabbitMQ 연결 타이머 기능을 구현하고 관련 계약을 정의 - 타이머 샘플을 추가하여 예약 및 취소 기능을 시연 - 기존 Stream 샘플을 연결 타이머로 전환 - 문서 및 매뉴얼에 변경 사항 반영 - 관련 테스트를 추가하고 검증 결과 기록 - 관련 이슈: feature/62
Contributor
There was a problem hiding this comment.
🟡 Changes recommended
The returned handle exposes implementation details and the underlying connection through public fields, so those attributes should be private while retaining remove() as the supported operation.
1 open issue
What changed in this PR
This PR adds optional, connection-level one-shot timer registration and cancellation for RabbitMQ connections. Timers use Pika’s owner-thread event loop and return handles that delegate cancellation to the underlying connection.
Changes:
- Added
Timer,TimerCallback, andSetTimerprotocols with public exports. - Implemented RabbitMQ
Connection.set_timer()using Pika’scall_later()andremove_timeout(). - Added timer and Stream samples, unit/contract tests, documentation, and implementation records.
- 45 unit and regression tests pass; live RabbitMQ validation could not be completed because a broker connection was unavailable.
- Nit: In
src/Broker/Implements/RabbitMQ/Connection.py, the timer handle exposesconnectionandtimeoutpublicly despite the opaque-handle API. These should be private attributes.
| File | Summary |
|---|---|
tests/test_protocol_contracts.py |
Verifies timer protocol signatures, exports, runtime checks, and optional support. |
tests/rabbitmq/test_rabbitmq_timers.py |
Tests timer registration, cancellation, delegation, re-registration, samples, and integration behavior. |
src/Broker/Implements/RabbitMQ/Connection.py |
Implements Pika-backed timer registration and cancellation handles. Contains the noted public implementation-detail exposure. |
src/Broker/Implements/RabbitMQ/__init__.py |
Exposes RabbitMQ timer implementation symbols. |
src/Broker/Connection.py |
Defines Timer, TimerCallback, and optional SetTimer contracts. |
src/Broker/__init__.py |
Re-exports timer contracts from the Broker package. |
samples/Broker/RabbitMQ/Sample.Timer.py |
Demonstrates timer cancellation and repeated registration. |
samples/Broker/RabbitMQ/Sample.Stream.py |
Uses the connection timer instead of an external thread timer. |
issues/feature/62/tasks/1793778440735.md |
Records timer and Stream sample verification. |
issues/feature/62/tasks/1793778003070.md |
Records final verification and unavailable broker validation. |
issues/feature/62/tasks/1793777847993.md |
Records unit verification and documentation updates. |
issues/feature/62/tasks/1793777337621.md |
Records the Connection timer implementation plan. |
issues/feature/62/tasks/1793775771772.md |
Records delegation and lifecycle decisions. |
issues/feature/62/tasks/1793775544541.md |
Records the finalized timer registration signature. |
issues/feature/62/tasks/1793774701691.md |
Records the narrowed Connection-based scope. |
issues/feature/62/tasks/1793772101827.md |
Records the initial timer and Consumer contract analysis. |
issues/feature/62/TASKS.md |
Summarizes implementation status, verification results, and remaining integration checks. |
issues/feature/62/REQUIREMENTS.md |
Defines finalized timer contracts, behavior, scope, and exclusions. |
issues/feature/62/README.md |
Records the original issue, objectives, and implementation context. |
issues/feature/62/PLAN.md |
Documents the planned implementation and verification steps. |
issues/feature/62/implements/1793778339166.md |
Records the runnable timer sample and Stream sample update. |
issues/feature/62/implements/1793777682327.md |
Records timer contract and RabbitMQ implementation details. |
issues/feature/62/IMPLEMENTS.md |
Summarizes the completed implementation and validation limitations. |
issues/feature/62/CHANGELOG.md |
Documents the user-facing timer feature and its constraints. |
docs/README.md |
Adds connection timers to the Korean RabbitMQ documentation index. |
docs/README.en.md |
Adds connection timers to the English RabbitMQ documentation index. |
docs/RabbitMQ.md |
Documents the Korean timer API, examples, and usage constraints. |
docs/RabbitMQ.en.md |
Documents the English timer API, examples, and usage constraints. |
Review effort: Lite
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

변경 내용
원본 이슈: #62
README.md
Consumer 소유 스레드 기반 타이머 등록·취소 지원
이슈와 작업 상태
feature), 원본 이슈에 적용됨feature,rabbitmqyong5eon/DefStream, 작업 브랜치feature/62origin/master와 동일한 로컬master의f1bf897master작업 문서
이슈 원문
해결하려는 문제
RabbitMQ Consumer로 메시지를 소비하면서, 메시지가 없는 동안에도 연결 유지용 콜백 등을 일정 시간 뒤 실행할 필요가 있습니다.
현재
Consumer.call(callback)은 연결 소유 스레드로 콜백을 전달하지만 지연 타이머의 등록·취소 API는 제공하지 않습니다. 따라서 호출자가 Pika의BlockingConnection.call_later()·remove_timeout()에 직접 의존하거나 별도 스레드 타이머의 수명주기를 관리해야 합니다.threading.Timer에서 직접 출력·소비 중단을 처리하면 메시지 처리와 동시 실행될 수 있고, 타이머 스레드에서 발생한 예외도 소비 루프로 자동 전파되지 않습니다.Consumer.call()로 다시 전달할 수는 있지만 타이머 생성·재등록·취소·소비 종료 후 실행 방지는 호출자가 계속 관리해야 합니다.제안하는 해결 방법
DefStream의 소비자 API를 통해 소비자 소유 스레드에서 실행되는 타이머를 등록·취소할 수 있게 지원해 주세요. 우선 현재 사용 사례인 RabbitMQ Consumer를 대상으로 합니다.
구체적인 메서드 이름과 핸들 타입은 구현 시 기존 인터페이스와 대조해 결정하면 됩니다. 예를 들어 지연 콜백 등록과 해당 핸들 취소 형태를 고려할 수 있으며, 이 예시를 확정 API로 지정하는 것은 아닙니다.
확인 기준
Consumer.call()동작을 유지합니다.고려한 대안
threading.Timer와Consumer.call()조합: 실행 스레드 전달은 가능하지만 별도 스레드·타이머 수명주기를 호출자가 관리해야 합니다.추가 정보
연결 유지용 출력은 사용 예시일 뿐이며 DefStream이 HTTP·SSE 프로토콜이나 해당 출력 내용을 구현해 달라는 요청은 아닙니다. 우선 타이머 등록·취소와 소비자 수명주기 통합만 지원하면 됩니다.
원문
REQUIREMENTS.md
Connection 기반 선택적 타이머 요구사항
목적과 범위
원본 이슈와 작업 정보를 기준으로, 연결 구현체가 제공하는 타이머를 공통 계약으로 이용한다. 이번 범위는 Connection을 이용하는
SetTimer,Timer,TimerCallback과 이를 지원하는 RabbitMQ 연결 구현, 직접 관련된 테스트·문서로 한정한다.Consumer의 인터페이스·구현과 Worker·Ping·Executor 등 다른 구성 요소는 변경하지 않는다. 앞서 논의한 리팩터링은 후속 작업으로 분리한다.
이번 문서는 확정 요구사항을 담는다. 구현 순서와 검증 방법은 작업 계획, 실제 결과와 남은 검증은 구현 종합에 구분하여 기록한다.
분석 근거와 현재 동작
GetExchange,GetQueue,GetStream,GetConsumer등 선택적 기능의 프로토콜을 구분한다. 타이머도 모든 연결에 강제하지 않고 같은 방식으로 분리한다.call_later와remove_timeout으로 내부 확인용 타이머를 관리한다. 소비 루프의finally에서 해당 타이머를 취소한다.원문과 대화에서 변경한 사항
SetTimer프로토콜로 제공하기로 확정했다.SetTimer,Timer,TimerCallback으로 확정했다.complete,fail,call제거와close추상 메서드 선언은 이번 요구사항에서 철회했다. 기존 선언·구현·호출 흐름을 그대로 유지한다.확정 요구사항
R1. 선택적 타이머 등록
SetTimer프로토콜을 정의한다. 기본Connection과 Consumer에는 타이머 등록을 필수 계약으로 추가하지 않는다.Timer핸들을 반환한다. 타이머의 구현 방식은 각 연결 구현체에 맡긴다.R2. 타이머 핸들과 콜백
Timer는 내부 구현을 숨기는 반환 핸들의 프로토콜이며, 공개 기능은remove() -> None으로 한정한다.remove는 아직 실행되지 않은 예약을 취소한다. 실행 중인 콜백을 강제로 중단하는 기능은 포함하지 않는다.TimerCallback은 인자 없이 실행되며 반환값이 없는__call__() -> None계약이다.등록과 반환 타입의 계약은 다음과 같다. 아래 코드는 공개 계약의 명세이며, 실제 선언은 연결 계약 모듈에 있다.
set_timer이며, 인자 순서는cb,seconds이다.cb=,seconds=키워드 인자로 전달할 수 있다.seconds의 타입은int, 단위는 초이며 반환 타입은Timer이다.Timer,SetTimer에는@runtime_checkable을 적용하고, 각각remove,set_timer에@abstractmethod를 적용한다.TimerCallback에는 이 두 데코레이터를 추가하지 않는다.R3. 기반 구현의 동작 이용
R4. 기존 코드와의 경계
complete,fail,call,close,run등 인터페이스와 구현은 변경하지 않는다.R5. 사용 문서
계약 확정 결과
set_timer(self, cb: TimerCallback, seconds: int) -> Timer로 확정했다.인수 기준과 검증 범위
위 항목은 인수 기준이다. 실제 검증 결과와 실행하지 못한 항목은 작업 종합에 기록하며, 실제 RabbitMQ 검증은 서버 연결 불가로 남아 있다.
제외 범위
complete·fail·call제거 및close추상 메서드 선언원문
CHANGELOG.md
연결 타이머 등록과 취소
추가된 기능
RabbitMQ 연결에서
set_timer(cb, seconds)로 일회성 콜백을 예약하고,반환된
Timer의remove()로 취소할 수 있습니다.호출자는 Pika 연결이나 내부 타이머 ID를 직접 다루지 않아도 됩니다.
SetTimer는 연결의 선택적 기능이며,Timer,TimerCallback과 함께DefStream.Broker및DefStream.Broker.Connection에서 import할 수 있습니다.반복 실행은 콜백에서 다음 타이머를 등록하는 방식으로 구성합니다.
실행 가능한 타이머 샘플에서
취소와 재등록을 확인할 수 있습니다. 기존 Stream 샘플의 소비 중단도
외부 스레드 타이머 대신 연결 타이머를 사용합니다.
사용 조건
자세한 사용법은 RabbitMQ 연결 타이머 안내를 참고하세요.
원문
IMPLEMENTS.md
연결 타이머 구현 결과
구현 내용
Timer,TimerCallback,SetTimer를 추가하고 Broker 공개 진입점에서도 노출했다.Timer,SetTimer의 런타임 검사·추상 메서드 선언과set_timer(cb: TimerCallback, seconds: int) -> Timer시그니처를 확정 명세대로 구현했다.SetTimer를 명시적으로 상속한다. 기존 연결 확인 후 즉시call_later(seconds, cb)로 일회성 예약을 등록하므로 지연 시간은 등록 시점부터 계산된다.Timer는 등록 당시 실제 연결과 불투명 핸들만 보관한다.remove()는 해당 연결의remove_timeout에 직접 위임하여 상위 연결 객체가 재연결되어도 취소 대상이 바뀌지 않는다.set_timer(consumer.stop, 1)로 교체했다.유지한 범위
Consumer·Worker·Ping·Pool·Executor·Event·Redis 구현과 연결·소비 종료 처리는 변경하지 않았다. 기본 Connection 계약에 타이머를 강제하지 않으며, 별도 이슈 #63·#64의 리팩터링을 포함하지 않았다.
검증과 제한
샘플 검증 추가 후 단위·회귀 45개가 통과했으며 실제 브로커 테스트 4개는 기본 실행에서 건너뛰었다. 별도 유휴 실행 테스트는 로컬 RabbitMQ 연결 실패로 동작 검증까지 진행하지 못했다. 타입·구문 진단과 사용 예제 검증 결과는 작업 종합에 구분하여 기록했다.
구현은 반영했지만 유휴 실행·실제 소유 스레드·취소·재등록·콜백 예외의 실제 브로커 인수 확인은 남아 있다.
구현 기록
원문
변경 유형
검증
TASKS.md
요구사항 분석 결과
요구사항 명세의 범위를 Connection 기반
SetTimer,Timer,TimerCallback과 RabbitMQ 연결 지원 및 직접 관련된 테스트·문서로 한정했다.앞서 명세한 Consumer의 메서드 제거·close 추상 메서드 선언은 이번 범위에서 철회했다. Consumer·Worker·Ping·Pool·Executor·Event는 변경하지 않으며, 리팩터링은 후속 작업으로 분리한다. 타이머 수명주기는 호출자와 기반 구현이 관리하며, 별도 추적·자동 정리 계층이나 소비 종료 연동은 추가하지 않는다.
등록 API는
set_timer(self, cb: TimerCallback, seconds: int) -> Timer로 확정했으며,Timer·SetTimer의 런타임 검사 및 추상 메서드 선언도 명세했다.지연 시간은 등록 시점부터 계산한다. 스레드 제약과 중복 취소·종료된 연결·음수·0초 등의 동작은 기반 API를 따른다. 이를 공통화하기 위한 추가 동기화·입력 검증·상태 관리는 요구하지 않는다.
작업 계획에 따라 계약·RabbitMQ 구현과 테스트·한국어 및 영어 매뉴얼을 반영했다. 제품 구현의 상세 결과는 구현 종합에 기록했다.
선택된 개발 환경에서 샘플 검증 추가 후 관련 49개 테스트 중 45개가 통과했으며, opt-in 실제 RabbitMQ 테스트 4개는 기본 실행에서 건너뛰었다. 별도로 유휴 실행 통합 테스트를 시도했으나 연결 단계에서
AMQPConnectionError로 막혔다. 전체 인수 완료로 판단하지 않는다.작업 기록
검증
git diff --check를 확인했다. 변경 Python 파일 5개는 Python 3.9 문법 파싱도 통과했으며 실제 실행 환경은 Python 3.12.10이다.원문
확인 사항
Closes #62