06. Stream session¶
이 category는 STREAM session 코드 안에서 쓰는 진입점(packet_stream_session_t, stream_t,
session_actor_manager_t, session_actor_t)과 Actor 코드 안에서 bound session에 쓰는 진입점
(bound_session_t)을 다룬다. 정확한 signature는
STREAM session exact interface와
Actor exact interface가 소유한다.
Session 콜백 구현 (packet_stream_session_t)¶
이 STREAM session이 받을 lifecycle·packet 이벤트를 처리한다. C++에는 assembly reflection이
없으므로 .NET처럼 packet type별 handler class를 등록하지 않는다 — register_session<TSession>()
(topology-discovery category)로 등록한 TSession이 직접 override하는 virtual member다.
class game_session_t : public zlink::framework::packet_stream_session_t {
public:
zlink::framework::task_t<void> on_connected(
zlink::framework::stream_t &stream) override;
zlink::framework::task_t<void> on_disconnected(
zlink::framework::stream_t &stream) override;
zlink::framework::task_t<void> on_error(
zlink::framework::stream_t &stream,
const zlink::framework::stream_error_t &error) override;
zlink::framework::task_t<void> on_packet(
zlink::framework::stream_t &stream,
const zlink::framework::session_message_context_t &context,
const zlink::framework::message_t &payload) override;
};
옵션. on_packet(...)의 context.packet_name으로 어떤 packet인지 구분한다 — 별도 registry
호출 없이 override 하나가 이 session이 받는 모든 packet을 처리한다.
완료 결과. 네 callback 모두 task_t<void>를 반환한다. on_connected/on_disconnected는
연결·해제마다 한 번, on_error는 transport 오류마다, on_packet은 Framework 내부 recv loop가
header framing과 queue admission을 끝낸 뒤 packet마다 호출한다. Handshake 실패는 session이
만들어지기 전이므로 on_error가 아니라 runtime monitoring에만 기록된다.
선택 기준. stream-session topology를 쓰는 모든 host가 구현한다. context.can_reply가
true인 packet에만 reply_packet으로 응답할 수 있다.
write_packet (stream_t)¶
연결된 client에 one-way message를 보낸다.
co_await stream
.write_packet(zlink::framework::message_t::from(server_tick_t{tick_number}))
.submit();
옵션. stream_send_call_t가 제공하는 modifier는 다음과 같다.
| Modifier | 기본값 | 의미 |
|---|---|---|
.metadata(key, value) |
없음 | client에 전달할 key-value |
.packet_name(name) |
payload 타입의 packet_name |
이 packet의 이름을 명시적으로 지정 |
.compress() |
비압축 | 등록된 stream compression codec으로 payload를 압축 |
.timeout(value) |
STREAM socket send timeout | 이 send의 admission 대기를 더 짧게 제한 |
.submit() |
필수 terminal | source-local admission까지만 기다린다 |
완료 결과. messaging-execution category의 one-way 완료 kind와 같다 — socket send timeout까지
기다린 뒤 없으면 deadline_exceeded, connection 단절은 unavailable인 framework_exception_t로
완료한다. 호출별 timeout은 socket timeout을 연장하지 않으며 둘 중 먼저 도달하는 deadline을 사용한다.
값은 millisecond 올림 뒤 1..INT_MAX여야 하고 deadline 뒤 late admission이나 replay는 없다. Reply에는
이 modifier를 적용하지 않는다.
선택 기준. Client가 보낸 request가 아닌, server가 먼저 보내는 push 메시지에 쓴다. Client의
request에 답할 때는 reply_packet을 쓴다.
reply_packet (stream_t)¶
현재 처리 중인 request packet에 응답한다.
co_await stream
.reply_packet(zlink::framework::message_t::from(get_player_state_result_t{state}))
.submit();
옵션. stream_write_call_t가 제공하는 modifier는 다음과 같다.
| Modifier | 기본값 | 의미 |
|---|---|---|
.metadata(key, value) |
없음 | client에 전달할 key-value |
.compress() |
비압축 | 등록된 stream compression codec으로 payload를 압축 |
.submit() |
필수 terminal | source-local admission까지만 기다린다 |
완료 결과. 이 request의 one-shot reply token을 원자적으로 claim한 뒤 전송한다. 같은 token으로
만든 두 번째 reply_packet 호출은 claim에 실패해 transport를 시도하지 않고 exceptional
completion으로 끝난다. Caller의 request timeout은 wire로 전달되지 않으므로 이 reply의 admission
deadline은 STREAM socket send timeout만 사용한다. Timeout 뒤에는 late reply를 보내지 않는다.
선택 기준. session_message_context_t::can_reply가 true인 packet(request)에만 쓴다. Client가
보낸 것이 아닌 새 메시지를 보내려면 write_packet을 쓴다.
bind / bind_or_get (session_actor_manager_t)¶
이 STREAM session에 Actor를 묶어 Actor 쪽에서 이 연결로 push할 수 있게 한다. stream_t::actors()로
호출한다.
zlink::framework::session_actor_t bound =
co_await stream.actors().bind_or_get(actor_ref).submit<zlink::framework::session_actor_t>();
옵션. 이 호출에는 modifier가 없다 — actor_ref_t만 받는다. 반환하는 request_call_t<session_actor_t>는
messaging-execution category의 request call과 같은 .timeout(...)/terminal 모양을 쓴다.
완료 결과. bind는 매번 새 binding을 만든다. bind_or_get은 이미 bound된 같은 incarnation이
있으면 그것을 반환한다. Binding은 actor_id + object_generation의 exact incarnation 하나로
고정된다. Mapping이 없으면 not_found, generation이 다르면 invalid_operation, pre-commit seal
중이면 unavailable이다. Bind retry가 deadline 안에 완료되지 않으면 deadline_exceeded로 끝난다.
find(actor_id)로 이미 bound된 handle을 동기 조회할 수 있고,
bound()는 현재 session에 bound된 전체 목록을 반환한다.
선택 기준. Actor가 이 client 연결로 직접 push해야 할 때 bind한다. Relocation이 일어나도
session_actor_t::ref()가 current location snapshot으로 갱신되므로 application이 다시 bind할
필요는 없다.
relay / notify_disconnected (session_actor_t)¶
Bind로 얻은 session_actor_t를 통해 이 Actor 쪽에서 client로 payload를 전달하거나 연결 단절을
통지한다.
옵션. 두 호출 모두 modifier가 없다 — payload(relay)만 받는다. relay는
session_message_context_t를 함께 받는 overload도 있다.
완료 결과. relay는 source-local admission을 수락하면 정상 완료하는 one-way task_t<void>
operation이다. notify_disconnected는 connection이 유지된 상태에서 논리적 단절을 알리는
notification이며 callback terminal까지 기다린다. Physical disconnect는 Framework가 자동으로
현재 binding 전체에 통지하므로 이 호출이 그 대체 경로는 아니다. Exact binding callback은 최대 한 번
실행하고 terminal 뒤 tombstone을 남긴다. Rebind는 새 binding을 먼저 등록하며 이전 callback failure가 새
binding을 제거하거나 이전 binding을 복원하지 않는다. 같은 generation의 relocation route 갱신은 rebind가
아니므로 disconnect callback을 실행하지 않는다.
선택 기준. Actor 쪽 코드에서 특정 bound client에 직접 전달할 때 쓴다. Request에 대한 응답은
Session 쪽 reply_packet이 처리한다.
send (bound_session_t, Actor 코드 안)¶
Actor에서 자신에게 bind된 client로 one-way message를 보낸다. actor_context_t::bound_session()이
반환하는 bound_session_t로 호출한다.
옵션. bound_session_send_call_t가 제공하는 .metadata(...)와 필수 terminal .submit()이
있다.
완료 결과. messaging-execution category의 one-way 완료 kind와 같다. 이 표면은 client를 향한 새 request operation을 제공하지 않는다 — client request에 대한 reply는 Actor request handler의 반환값으로 처리한다.
선택 기준. Actor 코드 쪽에서 bound client로 push할 때 쓴다. Session 쪽에서 직접 보내려면 위
write_packet 항목을 쓴다. 연결을 끊으려면 bound_session_t::disconnect()를 쓴다.
close (연결 종료)¶
Session이나 raw transport handle을 닫는다. stream_t::close()가 제공한다.
옵션. 이 호출에는 modifier가 없다.
완료 결과. 연결을 닫는다. 이미 닫힌 연결에 다시 호출해도 이 문서가 정의하는 별도 예외 계약은 없다 — 정확한 재호출 의미는 exact interface를 확인한다.
선택 기준. Application이 자발적으로 이 STREAM 연결을 끊어야 할 때 쓴다. Actor 쪽에서 bound
client 연결을 끊으려면 bound_session_t::disconnect()를 쓴다.
disconnect (Actor 코드 안, bound session)¶
Actor에서 자신에게 bind된 client 연결을 끊는다. bound_session_t::disconnect()로 호출한다.
옵션. 이 호출에는 modifier가 없다.
완료 결과. Bound session과의 연결을 끊는다.
선택 기준. Actor 쪽 코드에서 특정 client 연결을 더 유지할 필요가 없을 때 쓴다. Session 쪽에서
직접 끊으려면 close 항목을 쓴다.
전체 근거는 STREAM session exact interface와 Actor exact interface를 참고한다.