You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 5 Next »

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?");

  • No labels