#include "ask.h" #include "actor_bootstrapped.h" #include "actorid.h" #include "event.h" #include "hfunc.h" namespace NActors { namespace { class TAskActor: public TActorBootstrapped { enum { Timeout = EventSpaceBegin(TEvents::ES_PRIVATE), }; // We can't use the standard timeout event because recipient may send us one. struct TTimeout: public TEventLocal { }; public: TAskActor( TMaybe expectedEventType, TActorId recipient, THolder event, TDuration timeout, const NThreading::TPromise>& promise) : ExpectedEventType_(expectedEventType) , Recipient_(recipient) , Event_(std::move(event)) , Timeout_(timeout) , Promise_(promise) { } public: void Bootstrap() { Send(Recipient_, std::move(Event_)); Become(&TAskActor::Waiting); if (Timeout_ != TDuration::Max()) { Schedule(Timeout_, new TTimeout); } } STATEFN(Waiting) { if (ev->GetTypeRewrite() == TTimeout::EventType) { Promise_.SetException(std::make_exception_ptr(yexception() << "ask timeout")); } else if (!ExpectedEventType_ || ev->GetTypeRewrite() == ExpectedEventType_) { Promise_.SetValue(ev->ReleaseBase()); } else { Promise_.SetException(std::make_exception_ptr(yexception() << "received unexpected response " << ev->GetBase()->ToString())); } PassAway(); } public: TMaybe ExpectedEventType_; TActorId Recipient_; THolder Event_; TDuration Timeout_; NThreading::TPromise> Promise_; }; } THolder MakeAskActor( TMaybe expectedEventType, TActorId recipient, THolder event, TDuration timeout, const NThreading::TPromise>& promise) { return MakeHolder(expectedEventType, std::move(recipient), std::move(event), timeout, promise); } }