Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unexpected behaviour actorOf2 #101

Open
kleidemos opened this issue Apr 24, 2018 · 2 comments
Open

Unexpected behaviour actorOf2 #101

kleidemos opened this issue Apr 24, 2018 · 2 comments

Comments

@kleidemos
Copy link

I needed to create an actor that will set the task in the scheduler before launch. I used actor {} but then I rewrote it with actorOf2. After that I found its behavior very strange.

actorOf2 didn't perform calculations until receiving any message. But in my case. the actor had to recieve messages only from the Scheduler. It is deadlock.

"Minimal, Complete, and Verifiable example":

open Akkling

let system = System.create "my-system" <| Configuration.defaultConfig()

let builder () =
    props <| fun context ->
        let rec loop () = actor {
            let! message = context.Receive()
            message |> printfn "Message : %i"
            return! loop ()
        }
        printfn "builder"
        // In my case: context.Schedule ...
        loop ()

let typedActorOf2 () =
    actorOf2 <| fun cotnext ->
        let rec loop message =
            message |> printfn "Message : %i"
            loop |> become
        printfn "typed actorOf2"
        // In my case: context.Schedule ...
        loop
    |> props

let untypedActorOf2 () : Props<obj> =
    actorOf2 <| fun context ->
        let rec loop (message : obj) =
            message
            |> tryUnbox
            |> Option.iter (printfn "Message : %i")
            loop |> become
        printfn "untyped actorOf2"
        // In my case: context.Schedule ...
        loop
    |> props

If we try to run the following code, we will see that typedActorOf2 () |> spawnAnonymous system doesn't work (typed actorOf2).

builder () |> spawnAnonymous system
typedActorOf2 () |> spawnAnonymous system
untypedActorOf2 () |> spawnAnonymous system
()
> 
builder
untyped actorOf2
val it : unit = ()

But if we try to send message after creating, it will work.

builder () |> spawnAnonymous system                   <! 1
typedActorOf2 () |> spawnAnonymous system             <! 1
untypedActorOf2 () |> spawnAnonymous system |> retype <! 1
()
> 
builder
Message : 1
typed actorOf2
Message : 1
untyped actorOf2
Message : 1
val it : unit = ()

actorOf doesn't have such problems. I want to note that I needed to use context in my challenge.

I suppose boxed actor works because of sending PreStart.

I don't know if this a bug, but I think typed and untyped actors should work the same way regardless of 'Message.


RUS (little more info)

@kleidemos
Copy link
Author

I explored the source code. The following function works as I want:

let actorOf2' (fn : Actor<'Message> -> 'Message -> #Effect<'Message>) (mailbox : Actor<'Message>) : Effect<'Message> =
    let rec loop() =
        actor {
            let _fn = fn mailbox
            let! msg = mailbox.Receive()
            return _fn msg
        }
    loop()

@Horusiath
Copy link
Owner

I've added test, that confirms your problem. I'll modify actorOf2 for the next release.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants