1

I created the following test code - .Net core 2.1 console application. It prints the following message only

TestActor received message MyTask ("Test1","Test1") from [akka://MySystem/user/Scheduler#1426101451]

But the message Ok 0 cannot be received by the actor scheduler?

open System
open Akka.FSharp
open Akka

type MyTask = MyTask of item1: string * item2: string 

let system = System.create "MySystem" <| Configuration.load ()

let scheduler (actors: Actor.IActorRef) (mailbox: Actor<Result<int, string>>) =
    let rec loop (list: int list list) = actor {
        let! m = mailbox.Receive ()
        let sender = mailbox.Sender ()
        let akkaName = mailbox.Self.Path.Name
        printfn "%s received message %A from %A" akkaName m sender
        return! loop []
    }
    actors <! MyTask("Test1", "Test1")
    loop []

let processor (mailbox: Actor<MyTask>) =
    let rec loop () = actor {
        let! m = mailbox.Receive ()
        let sender = mailbox.Sender ()
        let akkaName = mailbox.Self.Path.Name
        printfn "%s received message %A from %A" akkaName m sender
        sender <! Ok 0 // scheduler cannot receive this message?
        return! loop ()
    }
    loop ()

[<EntryPoint>]
let main argv =
    let actor = spawn system "TestActor" processor
    spawn system "Scheduler" (scheduler actor) |> ignore
    system.WhenTerminated.Wait()
    0

Update:

It works after I changed the parameter from (mailbox: Actor<Result<int, string>>) to (mailbox: Actor<_>)?

Jeffrey Chung
  • 19,319
  • 8
  • 34
  • 54
ca9163d9
  • 27,283
  • 64
  • 210
  • 413

1 Answers1

1

The scheduler isn't the sender of the MyTask message to which the processor is replying, because you are doing the tell (<!) from outside the actor computation. That means it's basically being sent with no sender. You can use the Tell method on IActorRef to send with an explicit sender, since you want to send it from outside the context of your actor computation:

actors.Tell(MyTask("Test1", "Test1"), mailbox.Self)

EDIT

Another issue is that the mailbox parameter to the scheduler is typed as Actor<Result<int, string>>, but since Ok 0 will be inferred as Result<int,obj> in your context, it won't match the actor type signature, and the message will be ignored. When defining an actor with a specific message type, any messages of a different type will be ignored.

Aaron M. Eshbach
  • 6,380
  • 12
  • 22
  • I tried it with `mailbox.Self` but it still not working. However, it works after I changed the parameter from `(mailbox: Actor>) ` to `(mailbox: Actor<_>) `? – ca9163d9 Oct 03 '18 at 15:00
  • Oh, right. Your actor type was also restricting the messages that could be received by that actor. `Ok 0` was probably inferred as `Result` or `Result`, and therefore not being received even with the correct sender. If you changed the code sending the message to explicitly type `Ok 0` as `Result`, your original actor type definition would probably work. – Aaron M. Eshbach Oct 03 '18 at 15:04
  • BTW, I found there is no need to use `actors.Tell(MyTask("Test1", "Test1"), mailbox.Self)`. `sender <! Ok 0` works fine. My real code is still not working even after I change the type parameter to `Actor<_>`. Still investigating. – ca9163d9 Oct 03 '18 at 15:17