콘텐츠로 이동

한국어 | English

레퍼런스 목차

04. Eventing

이 category는 socket monitoring, 재사용 가능한 poller, standalone timer를 다룬다 — 각각 open_socket_monitor(...), create_poller(), create_timer()로 생성되며, 모두 package 최상위(Core category)에서 도달한다. 정확한 signature는 contracts/eventing/가 소유한다.


MonitorSocket

socket의 connection lifecycle event를 관찰하고 현재 상태를 읽는다.

monitor = open_socket_monitor(socket)
event = monitor.recv(flags=RecvFlags.DONT_WAIT)
if event is not None:
    print(event.event, event.remote_addr)
status = monitor.status()

Options.

Member 의미
status() 시점 스냅샷 MonitorStatus를 반환
close() monitor를 닫음
recv(*, flags=0) 다음 event를 가져옴; MonitorEvent 또는 DONT_WAIT가 설정되고 없으면 None 반환

Completion result. 모든 member는 동기다. sync·async context-manager 프로토콜을 둘 다 지원한다.

선택 기준. caller-driven pull loop에는 recv를 쓰고 시점 스냅샷에는 status()를 쓴다. Monitor 전달에는 등록형 callback이 없다.


MonitorStatus

MonitorSocket.status()가 반환하는, socket의 monitored 상태와 auto-high-water-mark telemetry 시점 스냅샷. 큰 keyword-only __init__을 가진 concrete class다(Protocol이 아님).

Options. 생성자가 모든 필드를 keyword-only 인자로 받는다. 여러 개는 향후 호환성을 위해 None 기본값을 받는다. 눈에 띄는 이름 중복: auto_hwm_applied_sndhwm_bytesauto_hwm_applied_sndhwm은 별개 생성자 파라미터지만, 짧은 이름이 생략되면 __init___bytes 값으로 fallback한다(_rcvhwm, _deferred_sndhwm, _deferred_rcvhwm도 같은 패턴) — instance를 읽는 caller는 두 attribute 이름 모두 같은 값을 가진 걸 본다.

그룹 Attribute
ABI identity abi_version, struct_size
Source/state source_kind, state_flags/detail_flags(비트마스크), is_ready()(계산 method)
Pending count snd_pending_msgs, rcv_pending_msgs
Auto-HWM 설정 auto_hwm_enabled, auto_hwm_profile/auto_hwm_role/auto_hwm_policy_class, auto_hwm_unit_budget_bytes/auto_hwm_socket_message_slots, auto_hwm_size_cap
Connection bucket auto_hwm_connection_bucket_enabled, auto_hwm_connection_bucket_count/_index/_hwm_4k, auto_hwm_connection_bucket_hysteresis_retained
Auto-HWM plan(byte) auto_hwm_effective_message_bytes, auto_hwm_planned_sndhwm_bytes/_rcvhwm_bytes, auto_hwm_applied_sndhwm_bytes/_rcvhwm_bytes(과 alias auto_hwm_applied_sndhwm/_rcvhwm), auto_hwm_effective_sndbuf/_rcvbuf
Auto-HWM recalc auto_hwm_last_recalc_ms, auto_hwm_last_recalc_reason, auto_hwm_send_blocked_ratio_ppm
Auto-HWM deferred shrink auto_hwm_deferred_sndhwm_bytes/_rcvhwm_bytes(과 alias), auto_hwm_deferred_sndhwm_valid/_rcvhwm_valid가 true일 때만 유효
In-flight/과금 snd_bytes_in_flight, rcv_bytes_in_flight, minimum_core_message_charge_bytes, oversize_message_admission_count, oversize_message_admission_max_bytes

Completion result. 해당 없음 — 순수 instance attribute에 더해 계산 method is_ready().

선택 기준. state_flags를 직접 디코딩하는 대신 is_ready()를 읽는다. socket의 실제 send/receive HWM이 설정한 CommonSocketOptions 값(Sockets category)과 다른 이유를 진단할 땐 connection-bucket과 auto-HWM-plan attribute를 쓴다.


MonitorEvent

monitor가 보고하는 socket connection-lifecycle event 하나. keyword-only __init__을 가진 concrete class다.

Options. 생성자 keyword 인자는 전부 필수이며 기본값이 없다; 각각 같은 이름의 순수 instance attribute가 된다.

Field 의미
event lifecycle event의 종류(MonitorEventMask 값)
value 에러 코드나 reconnect interval 같은 event별 값
routing_id event가 제공할 때만 존재하는 peer routing id
local_addr / remote_addr event에 결부된 local/remote 주소

Completion result. 해당 없음 — monitor가 전달하는 실질적으로 불변인 값(mutation을 막는 건 없지만 contract 어디도 그걸 요구하지 않는다).

선택 기준. lifecycle transition에 분기하려면 event (MonitorEventMask 값)를 읽는다. value는 event별 세부사항을 담는다(예: 에러 코드나 reconnect interval).


Poller

socket, file descriptor, timer를 하나의 재사용 가능한 wait로 multiplex한다.

poller = create_poller()
poller.add_socket(dealer, PollEventFlag.POLLIN, slot=1)
poller.add_timer(timer, slot=2)
events = create_poll_events(8)
ready = poller.wait(events, timeout_ms=1000)

Options.

Member 의미
add_socket(socket, events, slot) socket을 등록; slot은 대응하는 결과로 그대로 되돌아오는 caller token
add_fd(fd, events, slot) raw file descriptor를 등록, 같은 형태
add_timer(timer, slot) timer를 socket/fd와 함께 multiplex하도록 등록
modify_socket(socket, events) / modify_fd(fd, events) 이미 등록된 socket/fd의 감시 event를 교체
remove_socket(socket) / remove_fd(fd) / remove_timer(timer) source 등록을 해제
size() 현재 등록된 source 개수
wait(events, timeout_ms) timeout_ms까지 block하며 events를 그 자리에서 채움; 음수 timeout은 무기한 block
close() poller를 닫음

Completion result. 등록/제거 member는 동기다. waittimeout_ms까지 block하며, events를 그 자리에서 채우고 준비된 개수를 반환한다. sync·async context-manager 프로토콜을 둘 다 지원한다. Socket을 PollEventFlag.POLLCOMPLETION으로 등록했다면 owner가 wait()를 계속 호출해 binding이 native completion을 drain·settle하게 해야 한다. 두 역할이 필요하면 별도 execution context에서 blocking terminal을 수행한다.

선택 기준. 서비스 수명 전체에서 poller 하나를 쓴다. wait 호출마다 새로 만드는 대신 PollEvents buffer 하나를 재사용한다.


PollEvents / PollEvent

PollEventsPoller.wait(...)가 채우는 재사용 가능한 poll 결과 buffer로, create_poll_events(capacity)(Core category)로 생성된다 — java/node의 사전할당 결과 buffer와 같은 설계다. PollEvent@dataclass(frozen=True)로 필요 시 결과 하나를 materialize한다.

events = create_poll_events(16)
poller.wait(events, timeout_ms=500)
for i in range(events.ready_count):
    if events.has_event(i, PollEventFlag.POLLIN):
        ...

Options — PollEvents.

Member 의미
capacity property, create_poll_events(...)에 넘긴 고정 용량
ready_count property, 마지막 wait 이후 몇 개 slot이 준비된 event를 담고 있는지
source_kind(index) 해당 index의 준비된 source 종류
slot(index) 그 source 등록 시 넘긴 caller token
revents(index) 해당 index의 raw poll-event bitmask
fd(index) 해당 index의 file descriptor, FD kind source에서만 채워짐
has_event(index, event) revents(index)에 대한 편의 bit-test
event(index) 해당 index의 PollEvent를 materialize

Options — PollEvent(frozen dataclass).

Field 의미
source_kind source가 socket·file descriptor·timer 중 무엇인지
slot 등록 시 제공한 caller token
revents raw poll-event bitmask
fd file descriptor, source가 FD kind가 아니면 기본값 0

Completion result. 모든 PollEvents accessor는 동기다. PollEvent는 불변이다(frozen=True).

선택 기준. revents(index)를 손으로 bit-test하는 대신 has_event(index, flag)를 선호한다. caller가 진짜로 materialize된 PollEvent가 필요할 때만 event(index)를 쓴다 — 개별 accessor를 순회하면 hot polling loop에서 그 할당을 피할 수 있다.


Timer

interval마다 fire하며 poll하거나 await할 수 있는 timer.

timer = create_timer()
timer.start(interval_ns=1_000_000_000, repeat_count=0)
count = timer.recv()

Options.

Member 의미
start(interval_ns: int, repeat_count: int) interval_ns마다 fire를 시작; interval이 나노초 단위다, rust의 Timer::start와 일치하고 지금까지 다룬 다른 모든 언어가 쓰는 밀리초/Duration 기반 start와 다르다; repeat_count == 0은 무제한
stop() fire를 멈춤; start로 재시작 가능
recv() Optional[int] 반환 — 누적 fire count, 대기 중인 게 없으면 None
close() timer를 닫음

Completion result. 모든 member는 동기다. sync·async context-manager 프로토콜을 둘 다 지원한다.

선택 기준. 만료를 pull하려면 recv를, socket과 함께 하나의 wait에서 multiplex하려면 Poller.add_timer로 등록한다. Timer 전달에는 등록형 callback이 없다.


Eventing enum

Enum 사용처
MonitorEventMask(IntFlag) MonitorEvent.event CONNECTED, CONNECT_DELAYED, CONNECT_RETRIED, LISTENING, BIND_FAILED, ACCEPTED, ACCEPT_FAILED, CLOSED, CLOSE_FAILED, DISCONNECTED, MONITOR_STOPPED, HANDSHAKE_FAILED_NO_DETAIL, CONNECTION_READY, HANDSHAKE_FAILED_PROTOCOL, HANDSHAKE_FAILED_AUTH, PEER_WEIGHT_CHANGED, ALL
PollEventFlag(IntFlag) Poller.add_socket/modify_socket/add_fd/modify_fd, PollEvents.has_event(...) POLLIN, POLLOUT, POLLERR, POLLPRI, POLLITEMS_DFLT(16, readiness flag가 아니다 — legacy 기본 용량 상수, 다른 값들과 종류가 다름), POLLCOMPLETION(binding runtime worker용으로 예약됨; 자신의 doc comment에 따르면 application 코드는 대개 POLLIN/POLLOUT을 쓴다)
PollSourceKind(IntEnum) PollEvent.source_kind SOCKET, FD, TIMER

선택 기준. MonitorEventMask/PollEventFlag는 Python IntFlag이므로, 값을 결합할 땐 비트 | 연산자를 직접 쓴다 (MonitorEventMask.CONNECTED | MonitorEventMask.DISCONNECTED) — varargs나 EnumSet이 필요한 언어와 다르다.


contracts/eventing/Python 바인딩 스펙에서 전체 근거를 확인한다.