At-Least-Once Delivery - 적어도 메시지를 한번 보내려는 메카니즘으로 PersistenceActor와 결합하여
목표를 달성할수 있습니다. 적어도 한번보내려는 메카니즘으로 인해 중복 메시지 발생에 유의하여 작성
해보겠습니다.
메시지설계
public class Msg { public Msg(long deliveryId, string message) { DeliveryId = deliveryId; Message = message; } public long DeliveryId { get; } public string Message { get; } } public class Confirm { public Confirm(long deliveryId) { DeliveryId = deliveryId; } public long DeliveryId { get; } } public interface IEvent { } public class MsgSent : IEvent { public MsgSent(string message) { Message = message; } public string Message { get; } } public class MsgConfirmed : IEvent { public MsgConfirmed(long deliveryId) { DeliveryId = deliveryId; } public long DeliveryId { get; } }
액터설계
public class ExampleDestinationAtLeastOnceDeliveryReceiveActor : ReceiveActor { private ILoggingAdapter log = Context.GetLogger(); protected int messageCnt = 0; public ExampleDestinationAtLeastOnceDeliveryReceiveActor() { Receive<Msg>(msg => { messageCnt++; //Test를 위해 일부러 메시지를 못받은척한다. if (messageCnt % 2 ==0) { log.Warning("Test for Drop Message"); return; } log.Debug("Yes I can"); Sender.Tell(new Confirm(msg.DeliveryId), Self); }); } } public class ExampleAtLeastOnceDeliveryReceiveActor : AtLeastOnceDeliveryReceiveActor { private readonly IActorRef _destionationActor = Context.ActorOf<ExampleDestinationAtLeastOnceDeliveryReceiveActor>(); private ILoggingAdapter log = Context.GetLogger(); public ExampleAtLeastOnceDeliveryReceiveActor() { Recover<MsgSent>(msgSent => Handler(msgSent)); Recover<MsgConfirmed>(msgConfirmed => Handler(msgConfirmed)); Command<string>(str => { log.Debug("received:" + str); Persist(new MsgSent(str), Handler); }); Command<Confirm>(confirm => { //메시지 받음을 확인하고, 해당 메시지를 더이상 안보낸다. log.Debug("received confirm:" + confirm.DeliveryId); Persist(new MsgConfirmed(confirm.DeliveryId), Handler); }); } private void Handler(MsgSent msgSent) { Deliver(_destionationActor.Path, l => new Msg(l, msgSent.Message)); } private void Handler(MsgConfirmed msgConfirmed) { ConfirmDelivery(msgConfirmed.DeliveryId); } public override string PersistenceId { get; } = "persistence-id"; }
TestCode
테스트 케이스
- 메시지 10개를 한꺼번에 보낸다.
- 받는 쪽에서 짝수번째 메시지를 못본채한다.( test 시나리오)
- 우선 홀수 메시지는 모두 전송됨을 확인
- 메시지 전송에 실패가난 짝수번째 메시지도 다시전송하여 결국 성공시킨다.(홀수번쨰 성공)
var actorInfo = Props.Create<ExampleAtLeastOnceDeliveryReceiveActor>(); var myactor = actorSystem.ActorOf(actorInfo, "myActor"); for(int i=0;i<10;i++) myactor.Tell("can you speak english?");