콘텐츠로 이동

Java Channel messaging 공개 인터페이스

인터페이스 목차 · Channel messaging

ChannelName은 process 안의 송신 경로를 선택한다. RouteMesh·ClientServer·fanout builder와 typed handler, client call의 정확한 payload type은 공통 계약의 역할 구분을 Java generic으로 투영한다. One-way operation은 비동기 submit()과 동기 blocking submit_sync()를 제공하고, request operation의 submit(...)은 terminal reply까지 기다리며 동기 submit_sync(...)도 제공한다. 동기 submit_sync 계열은 application thread 전용이며, handler turn·Spot turn·state lane 등 runtime 실행 문맥에서 부르면 InvalidOperation으로 즉시 실패한다 (Submit과 완료 §4 F2-a). framework 공개 종결자는 backpressure를 노출하지 않는다(F1).

submit_sync는 interface의 default 메서드다. 구현이 모든 call type에서 같다 — 문맥을 검사한 뒤 같은 비동기 종결자를 기다린다. call type마다 다시 사용하면 같은 규칙이 여러 곳에 흩어지고 새 call type이 빠뜨릴 수 있다. .NET도 default interface method로 같은 구조를 사용한다. Logical Multicast는 target별 제출 결과를 반환하거나 publish 전용 monitoring으로 집계하지 않는다. Remote Spot queue 제출과 remote·local handler 실행 또는 완료는 CompletionStage 완료 조건이 아니다.

RouteMesh·ClientServer Channel send/request, Node direct send/request와 classic fanout 구독 handler에 filter를 적용한다. Spot·Actor·Logical Multicast·STREAM handler에는 적용하지 않는다. Filter는 ZLinkHandlerFilterContext.dispatchKind()로 다섯 경로를 구분한다. RouteMesh와 Node direct context는 실제 MeshName을 제공한다. ClientServer와 classic fanout context의 MeshName은 비어 있다.

Handler dispatch마다 child scope를 하나 만든다. Handler와 filter는 이 scope에서 Framework가 한 번씩 만들며 같은 scoped dependency를 사용한다. Spring bean scope나 Application service 등록으로 이 수명을 바꿀 수 없다. Dispatch가 끝나면 Framework가 만든 instance와 child scope를 정리한다.

Filter의 next.invoke()는 최대 한 번 호출할 수 있다. 두 번째 호출은 IllegalStateException으로 거부하고 handler를 다시 실행하지 않는다. Request filter가 next를 호출하지 않으면 ZLinkFrameworkException의 REJECTED로 완료한다. Filter가 임의 값을 반환해도 업무 reply로 사용하지 않는다. next가 실행한 handler의 값만 reply가 된다.

Classic fanout은 일치한 handler마다 별도 scope와 filter chain을 만든다. 한 dispatch의 filter 중단이나 실패는 다른 handler dispatch의 실행을 취소하지 않는다.

public interface ZLinkMeshChannelBuilder {
 ZLinkMeshChannelClientBuilder client();
 ZLinkMeshChannelServerBuilder server();
}

public interface ZLinkMeshChannelClientBuilder {}

public interface ZLinkMeshChannelServerBuilder {
 ZLinkMeshChannelServerBuilder setWeight(int weight);
 ZLinkMeshChannelServerBuilder addHandlerGroup(String groupName);
 <THandler extends ZLinkSendHandler<TMessage>, TMessage>
 ZLinkMeshChannelServerBuilder addSendHandler(
 Class<THandler> handlerType, Class<TMessage> messageType);
 <THandler extends ZLinkRouteSendHandler<TMessage>, TMessage>
 ZLinkMeshChannelServerBuilder addRouteSendHandler(
 Class<THandler> handlerType, Class<TMessage> messageType);
 <THandler extends ZLinkRequestHandler<TRequest, TReply>, TRequest, TReply>
 ZLinkMeshChannelServerBuilder addRequestHandler(
 Class<THandler> handlerType,
 Class<TRequest> requestType,
 Class<TReply> replyType);
}

public interface ClientServerChannelBuilder {
 ZLinkClientServerChannelClientBuilder client();
 ZLinkClientServerChannelServerBuilder server();
}

public interface ZLinkClientServerChannelClientBuilder {
 ZLinkClientServerChannelClientBuilder connect(String endpoint);
}

public interface ZLinkClientServerChannelServerBuilder {
 ZLinkClientServerChannelServerBuilder listen();
 ZLinkClientServerChannelServerBuilder listen(int port);
 ZLinkClientServerChannelServerBuilder setBindHost(String host);
 ZLinkClientServerChannelServerBuilder setAdvertiseHost(String host);
 ZLinkClientServerChannelServerBuilder setWeight(int weight);
 ZLinkClientServerChannelServerBuilder addHandlerGroup(String groupName);
 <THandler extends ZLinkSendHandler<TMessage>, TMessage>
 ZLinkClientServerChannelServerBuilder addSendHandler(
 Class<THandler> handlerType, Class<TMessage> messageType);
 <THandler extends ZLinkRequestHandler<TRequest, TReply>, TRequest, TReply>
 ZLinkClientServerChannelServerBuilder addRequestHandler(
 Class<THandler> handlerType,
 Class<TRequest> requestType,
 Class<TReply> replyType);
}

public interface ZLinkClient {
 ZLinkSendCall sendToChannel(String channelName, Object message);
 ZLinkRequestCall requestToChannel(String channelName, Object request);
}

public interface ZLinkRouteClient {
 ZLinkSendCall sendToNode(
 String meshName, RoutingId target, Object message);
 ZLinkRequestCall requestToNode(
 String meshName, RoutingId target, Object request);
 ZLinkSendCall sendToChannel(String channelName, Object message);
 ZLinkRequestCall requestToChannel(String channelName, Object request);
 ZLinkSpotSendCall sendToSpot(String spotId, Object message);
 ZLinkSpotRequestCall requestToSpot(String spotId, Object request);
}

public interface ZLinkFanoutClient {
 ZLinkFanoutPublishCall publish(
 String channelName, String topic, Object event);
 ZLinkFanoutPublishCall publish(String channelName, Object event);
}

public enum ZLinkRequestFailureReason {
 TIMEOUT, CANCELLED, SHUTDOWN
}

public final class ZLinkRequestFailureException extends RuntimeException {
 public ZLinkRequestFailureException(
 ZLinkRequestFailureReason reason, String message);
 public ZLinkRequestFailureException(
 ZLinkRequestFailureReason reason, String message, Throwable cause);
 public ZLinkRequestFailureReason reason();
}

Channel 호출은 process-local ChannelName index만 사용한다. 호출자가 MeshName과 ChannelName을 함께 넘겨 물리 배선을 고르는 overload는 제공하지 않는다. sendToNode(String, RoutingId, Object)는 RID를 지정하므로 첫 인자를 MeshName으로 해석한다.

Java Spot direct call은 instanceSpot()을 제공한다. Cold activation은 Spot 주소 메시징이 정한다.

Java는 channelName(channelName)과 addClientServerChannel(channelName) builder를 제공한다. 역할 등록은 Channel topology와 ClientServer channel이 정한다.

RouteMesh Channel Server, ClientServer Server와 node-wide placement weight는 모두 int이며 범위는 0..10000, 기본값은 100이다. 범위 밖 값은 startup 설정과 runtime 변경에서 configuration error다. Weighted selection은 후보 weight 합계를 최소 64-bit 정수로 계산한다.

Local Server 후보와 선택은 ClientServer channel §4가 정한다.

ZLinkFanoutClient.publish(...)에 명시하거나 subscribe에 등록하는 topic이 Channel messaging §7이 금지한 값이면 ZLinkConfigurationException을 발생시킨다. Topic을 생략한 overload는 typed event의 packet name을 topic으로 사용하며 같은 규칙을 적용한다.

Framework는 public call 뒤에서 Java binding의 exported raw socket API만 사용한다. Core service object, private dispatch record와 native handle은 handler context, call result나 exception payload에 노출하지 않는다.

다음 예제에서 client는 구성이나 dependency injection으로 얻은 ZLinkClient다. ChannelName으로 요청을 시작하며, submit(...)이 반환한 stage는 terminal reply까지 기다린다.

CompletionStage<CheckoutReply> reply = client
 .requestToChannel("checkout", request) // checkout Server 후보 중 하나를 Framework가 선택한다.
 .timeout(Duration.ofSeconds(5)) // 이 request operation에 적용할 timeout을 지정한다.
 .submit(CheckoutReply.class); // reply type을 지정하고 terminal reply를 기다린다.

public member inventory

아래 선언은 이 category의 Java public type과 member를 고정한다.

public final class systems.zlink.framework.channels.ZLinkRequestFailureReason extends java.lang.Enum<systems.zlink.framework.channels.ZLinkRequestFailureReason> {
 public static final systems.zlink.framework.channels.ZLinkRequestFailureReason TIMEOUT;
 public static final systems.zlink.framework.channels.ZLinkRequestFailureReason CANCELLED;
 public static final systems.zlink.framework.channels.ZLinkRequestFailureReason SHUTDOWN;
 public static systems.zlink.framework.channels.ZLinkRequestFailureReason[] values();
 public static systems.zlink.framework.channels.ZLinkRequestFailureReason valueOf(java.lang.String);
}
public final class systems.zlink.framework.channels.ZLinkRequestFailureException extends java.lang.RuntimeException {
 public systems.zlink.framework.channels.ZLinkRequestFailureException(systems.zlink.framework.channels.ZLinkRequestFailureReason, java.lang.String);
 public systems.zlink.framework.channels.ZLinkRequestFailureException(systems.zlink.framework.channels.ZLinkRequestFailureReason, java.lang.String, java.lang.Throwable);
 public systems.zlink.framework.channels.ZLinkRequestFailureReason reason();
}
public interface systems.zlink.framework.configuration.ZLinkMeshChannelBuilder {
 public abstract systems.zlink.framework.configuration.ZLinkMeshChannelClientBuilder client();
 public abstract systems.zlink.framework.configuration.ZLinkMeshChannelServerBuilder server();
}
public interface systems.zlink.framework.configuration.ZLinkMeshChannelClientBuilder {
}
public interface systems.zlink.framework.configuration.ZLinkMeshChannelServerBuilder {
 public abstract systems.zlink.framework.configuration.ZLinkMeshChannelServerBuilder setWeight(int);
 public abstract systems.zlink.framework.configuration.ZLinkMeshChannelServerBuilder addHandlerGroup(java.lang.String);
 public abstract <THandler extends systems.zlink.framework.channels.ZLinkSendHandler<TMessage>, TMessage> systems.zlink.framework.configuration.ZLinkMeshChannelServerBuilder addSendHandler(java.lang.Class<THandler>, java.lang.Class<TMessage>);
 public abstract <THandler extends systems.zlink.framework.channels.ZLinkRouteSendHandler<TMessage>, TMessage> systems.zlink.framework.configuration.ZLinkMeshChannelServerBuilder addRouteSendHandler(java.lang.Class<THandler>, java.lang.Class<TMessage>);
 public abstract <THandler extends systems.zlink.framework.channels.ZLinkRequestHandler<TRequest, TReply>, TRequest, TReply> systems.zlink.framework.configuration.ZLinkMeshChannelServerBuilder addRequestHandler(java.lang.Class<THandler>, java.lang.Class<TRequest>, java.lang.Class<TReply>);
}
public interface systems.zlink.framework.configuration.ZLinkClientServerChannelClientBuilder {
 public abstract systems.zlink.framework.configuration.ZLinkClientServerChannelClientBuilder connect(java.lang.String);
}
public interface systems.zlink.framework.configuration.ClientServerChannelBuilder {
 public abstract systems.zlink.framework.configuration.ZLinkClientServerChannelClientBuilder client();
 public abstract systems.zlink.framework.configuration.ZLinkClientServerChannelServerBuilder server();
}
public interface systems.zlink.framework.configuration.ZLinkClientServerChannelServerBuilder {
 public abstract systems.zlink.framework.configuration.ZLinkClientServerChannelServerBuilder listen();
 public abstract systems.zlink.framework.configuration.ZLinkClientServerChannelServerBuilder listen(int);
 public abstract systems.zlink.framework.configuration.ZLinkClientServerChannelServerBuilder setBindHost(java.lang.String);
 public abstract systems.zlink.framework.configuration.ZLinkClientServerChannelServerBuilder setAdvertiseHost(java.lang.String);
 public abstract systems.zlink.framework.configuration.ZLinkClientServerChannelServerBuilder setWeight(int);
 public abstract systems.zlink.framework.configuration.ZLinkClientServerChannelServerBuilder addHandlerGroup(java.lang.String);
 public abstract <THandler extends systems.zlink.framework.channels.ZLinkSendHandler<TMessage>, TMessage> systems.zlink.framework.configuration.ZLinkClientServerChannelServerBuilder addSendHandler(java.lang.Class<THandler>, java.lang.Class<TMessage>);
 public abstract <THandler extends systems.zlink.framework.channels.ZLinkRequestHandler<TRequest, TReply>, TRequest, TReply> systems.zlink.framework.configuration.ZLinkClientServerChannelServerBuilder addRequestHandler(java.lang.Class<THandler>, java.lang.Class<TRequest>, java.lang.Class<TReply>);
}
public interface systems.zlink.framework.channels.ZLinkClient {
 public abstract systems.zlink.framework.channels.ZLinkSendCall sendToChannel(java.lang.String, java.lang.Object);
 public abstract systems.zlink.framework.channels.ZLinkRequestCall requestToChannel(java.lang.String, java.lang.Object);
}
public interface systems.zlink.framework.channels.ZLinkFanoutClient {
 public abstract systems.zlink.framework.channels.ZLinkFanoutPublishCall publish(java.lang.String, java.lang.String, java.lang.Object);
 public abstract systems.zlink.framework.channels.ZLinkFanoutPublishCall publish(java.lang.String, java.lang.Object);
}
public interface systems.zlink.framework.channels.ZLinkFanoutPublishCall {
 public abstract java.util.concurrent.CompletionStage<java.lang.Void> submit();
}
public interface systems.zlink.framework.channels.ZLinkMeshChannelRuntimeOptions {
 public abstract int weight();
 public abstract void weight(int);
}
public interface systems.zlink.framework.channels.ZLinkPublishCall {
 public default systems.zlink.framework.channels.ZLinkPublishCall metadata(java.lang.String, java.lang.String);
 public default systems.zlink.framework.channels.ZLinkPublishCall metadata(java.util.Map<java.lang.String, java.lang.String>);
 public abstract java.util.concurrent.CompletionStage<java.lang.Void> submit();
}
public interface systems.zlink.framework.channels.ZLinkPublishMessageContext extends systems.zlink.framework.ZLinkMessageContext {
 public abstract java.lang.String topic();
 public abstract java.util.Optional<java.lang.String> source();
}
public interface systems.zlink.framework.channels.ZLinkFanoutHandler<TMessage> {
 public abstract java.util.concurrent.CompletionStage<java.lang.Void> handle(TMessage, systems.zlink.framework.channels.ZLinkPublishMessageContext);
}
public interface systems.zlink.framework.channels.ZLinkRequestCall {
 public default systems.zlink.framework.channels.ZLinkRequestCall metadata(java.lang.String, java.lang.String);
 public default systems.zlink.framework.channels.ZLinkRequestCall metadata(java.util.Map<java.lang.String, java.lang.String>);
 public abstract systems.zlink.framework.channels.ZLinkRequestCall timeout(java.time.Duration);
 public abstract <TReply> java.util.concurrent.CompletionStage<TReply> submit(java.lang.Class<TReply>);
 public default <TReply> TReply submit_sync(java.lang.Class<TReply>);   // blocking; runtime 문맥에서 InvalidOperation
 public abstract <TReply> java.util.concurrent.CompletionStage<TReply> yield(java.lang.Class<TReply>);
}
public interface systems.zlink.framework.channels.ZLinkRequestHandler<TRequest, TReply> {
 public abstract java.util.concurrent.CompletionStage<TReply> handle(TRequest, systems.zlink.framework.ZLinkMessageContext);
}
public interface systems.zlink.framework.channels.ZLinkRouteClient {
 public abstract systems.zlink.framework.channels.ZLinkSendCall sendToChannel(java.lang.String, java.lang.Object);
 public abstract systems.zlink.framework.channels.ZLinkRequestCall requestToChannel(java.lang.String, java.lang.Object);
 public abstract systems.zlink.framework.channels.ZLinkSendCall sendToNode(java.lang.String, systems.zlink.contracts.core.RoutingId, java.lang.Object);
 public abstract systems.zlink.framework.spots.ZLinkSpotSendCall sendToSpot(java.lang.String, java.lang.Object);
 public abstract systems.zlink.framework.channels.ZLinkRequestCall requestToNode(java.lang.String, systems.zlink.contracts.core.RoutingId, java.lang.Object);
 public abstract systems.zlink.framework.spots.ZLinkSpotRequestCall requestToSpot(java.lang.String, java.lang.Object);
}
public interface systems.zlink.framework.channels.ZLinkRouteMeshRuntimeOptions {
 public abstract systems.zlink.framework.channels.ZLinkMeshChannelRuntimeOptions channel(java.lang.String, java.lang.String);
 public abstract systems.zlink.framework.channels.ZLinkMeshPlacementRuntimeOptions mesh(java.lang.String);
 public abstract systems.zlink.framework.channels.ZLinkMeshChannelRuntimeOptions channel(java.lang.String);
}
public interface systems.zlink.framework.channels.ZLinkMeshPlacementRuntimeOptions {
 public abstract int placementWeight();
 public abstract void setPlacementWeight(int);
}
public interface systems.zlink.framework.channels.ZLinkRouteMessageContext extends systems.zlink.framework.ZLinkMessageContext {
 public abstract systems.zlink.contracts.core.RoutingId sourceNodeRid();
}
public interface systems.zlink.framework.channels.ZLinkRouteRequestHandler<TRequest, TReply> {
 public abstract java.util.concurrent.CompletionStage<TReply> handle(TRequest, systems.zlink.framework.channels.ZLinkRouteMessageContext);
}
public interface systems.zlink.framework.channels.ZLinkRouteSendHandler<TMessage> {
 public abstract java.util.concurrent.CompletionStage<java.lang.Void> handle(TMessage, systems.zlink.framework.channels.ZLinkRouteMessageContext);
}
public interface systems.zlink.framework.channels.ZLinkSendCall {
 public default systems.zlink.framework.channels.ZLinkSendCall metadata(java.lang.String, java.lang.String);
 public default systems.zlink.framework.channels.ZLinkSendCall metadata(java.util.Map<java.lang.String, java.lang.String>);
 public abstract java.util.concurrent.CompletionStage<java.lang.Void> submit();
 public default void submit_sync();   // blocking; runtime 문맥에서 InvalidOperation
}
public interface systems.zlink.framework.channels.ZLinkSendHandler<TMessage> {
 public abstract java.util.concurrent.CompletionStage<java.lang.Void> handle(TMessage, systems.zlink.framework.ZLinkMessageContext);
}
public interface systems.zlink.framework.handlers.ZLinkHandlerGroup extends java.lang.annotation.Annotation {
 public abstract java.lang.String value();
}
public interface systems.zlink.framework.handlers.ZLinkHandlerGroups extends java.lang.annotation.Annotation {
 public abstract systems.zlink.framework.handlers.ZLinkHandlerGroup[] value();
}
public interface systems.zlink.framework.handlers.ZLinkPacket extends java.lang.annotation.Annotation {
 public abstract java.lang.String value();
}
public interface systems.zlink.framework.handlers.ZLinkPublish extends java.lang.annotation.Annotation {
 public abstract java.lang.String packetName();
}
public interface systems.zlink.framework.handlers.ZLinkRequest extends java.lang.annotation.Annotation {
 public abstract java.lang.String packetName();
}
public interface systems.zlink.framework.handlers.ZLinkSend extends java.lang.annotation.Annotation {
 public abstract java.lang.String packetName();
}
public interface systems.zlink.framework.handlers.ZLinkSpotActorRequest extends java.lang.annotation.Annotation {
 public abstract java.lang.String packetName();
}
public interface systems.zlink.framework.handlers.ZLinkSpotActorSend extends java.lang.annotation.Annotation {
 public abstract java.lang.String packetName();
}
public interface systems.zlink.framework.handlers.ZLinkSpotRequest extends java.lang.annotation.Annotation {
 public abstract java.lang.String packetName();
}
public interface systems.zlink.framework.handlers.ZLinkSpotSubscription extends java.lang.annotation.Annotation {
 public abstract java.lang.String spotNodeName();
 public abstract java.lang.String topic();
}
public interface systems.zlink.framework.handlers.ZLinkSpotTimer extends java.lang.annotation.Annotation {
 public abstract java.lang.String name();
 public abstract long periodMillis();
}
public interface systems.zlink.framework.handlers.ZLinkStreamPacket extends java.lang.annotation.Annotation {
}
public interface systems.zlink.framework.handlers.ZLinkStreamRaw extends java.lang.annotation.Annotation {
}

이 문서의 request builder에 선언된 yield(...)는 호출자가 SpotWide User Spot 또는 Instance Spot의 shared turn을 소유할 때만 유효하다. 다른 실행 문맥에서는 message를 제출하거나 turn을 반환하지 않고 INVALID_OPERATION으로 완료한다. submit(...)은 현재 turn을 유지하는 공통 Async 의미다.