Page History
Info |
---|
At-Least-Once Delivery - 적어도 메시지를 한번 보내려는 메카니즘으로 PersistenceActor와 결합하여 목표를 달성할수 있습니다. 보낼려는 메시지가 유실될수 있는 가능성을 제거하며 적어도 한번보내려는 메카니즘으로 인해 중복 메시지 발생에 유의하여 작성 해보겠습니다. |
이것은 메시지를 무조건 한번만 보내야할때 유용합니다. 아주 착한 택배 서비스 시나리오를 가정해봅시다.
택배 아저씨는 택배를 대상에게 일반적으로 아주 빠르게 대부분 성공을 하며, 물건 분실을
방지하고자 꼭 수신인 실명을 확인을 합니다. 하지만 받을사람이 부재중이라고 가정해봅시다.
택배 아저씨는 자신의 해야할 남은 다른 일을 모두 하는동시에, 택배를 받는 사람이 나타날때까지보관하고 있다가 자신이 해야할 일을 하는동시에, 부재중을 체크하면서 보내려고 할것입니다.
결국 택배아저씨는 자신이 배달해야할 모든 택배를 모두 보내게 되며, 물건은 복제가 안되기때문에 중복없이
꼭 한번만 보내게 됩니다. 상대편이 결국 모두 보내게 될것입니다. 상대편이 선물을 받았나? 안받았나?
확인안하는 산타클로스 할아버지와는 다른 메카니즘입니다.
메시지설계
Code Block | ||||
---|---|---|---|---|
| ||||
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; } } |
...
Code Block | ||||
---|---|---|---|---|
| ||||
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";
} |
...