2015-11-18 1 views
1

Я хотел бы иметь агента, который действует как SMTP-сервер, который асинхронно ждет сообщений электронной почты, а также запросы служб для получения списка полученных электронных писем. Агент будет выглядеть примерно так:Могу ли я иметь асинхронный агент, который слушает и отвечает на 2 события?

let agent = Agent.Start(fun inbox ->  
    let rec loop emails = async { 
    let! email = ReceiveEmail() 
    let emails = email::emails 
    let! emailStatusRequest = inbox.Receive() 
    match emailStatusRequest with 
    | Get channel -> channel.Reply emails 
    return! loop emails } 
    loop []) 

Это будет ждать сообщения электронной почты, а затем ждать запроса статуса. Как мне отделить заказ, чтобы агент реагировал на то, какое событие происходит первым - событие, полученное по электронной почте, или запрос на получение сообщения электронной почты? Является ли агент идеальным инструментом для моделирования этого?

+1

I переместит часть 'ReceiveEmail' в свой собственный асинхронный цикл и отправит сообщения вашему агенту - очевидным способом является наличие некоторого' AgentCommand = Received of Message ' StatusRequest EmailStatusRequest | ... 'sum-type – Carsten

+0

Nice @Carsten. Если вы добавите свой комментарий в качестве ответа, я соглашусь с ним. У меня есть один агент для получения писем, а другой - для записи их. Я обертываю это типом, который только предоставляет метод для получения списка полученных сообщений электронной почты. Я всегда забываю, что агенты могут общаться с другими агентами ... – NickL

ответ

2

Я бы переместил часть ReceiveEmail в свою собственную асинхронную петлю и опубликовал ее сообщения вашему агенту.

что-то вроде этого (предупреждение: не тестировалось - лечить, как псевдо-код):

type AgentCommands = 
    | Received of Email 
    | StatusRequest of RequestParams 
    | ... 

let agent = Agent.Start(fun inbox ->  
    let rec loop emails = async { 
    let! cmd = inbox.Receive 
    match cmd with 
    | Received email -> 
     let emails = email::emails 
     return! loop emails 
    | StatusRequest emailStatusRequest -> 
     match emailStatusRequest with 
     | Get channel -> channel.Reply emails 
    return! loop emails } 
    loop []) 

let receiveLoop = async { 
     while true do 
     let! email = ReceiveEmail() 
     agent.Post (Received email) 
    } |> Async.Start 

, конечно, вы, вероятно, необходимо при поддержке CancellationToken ... вы получите его;)

+0

Я отправил свой [код здесь] (http://www.fssnip.net/tn) для всех, кто интересуется – NickL

Смежные вопросы