Dark Mode

Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Actor model on top of cats? #2627

Answered by armanbilge
yatesco asked this question in Q&A
Actor model on top of cats? #2627
Dec 4, 2021 * 6 comments * 10 replies
Answered by armanbilge Return to top
Discussion options

yatesco
Dec 4, 2021

Hi there - I might be missing something (seriously - I am frantically catching up), but an Actor model on top of Cats Effects seems like a no-brainer to me, but there doesn't seem to be one.

How do you manage long running, independant, but identifiable processes? A process per session on a web server for example, or a process per long running async something or other.

I'd assume Fiber, but:

  • why doesn't this already exist - I must be missing something
  • I didn't think Fibers were uniquely identifable - do I need to maintain a map of id->fiber myself?

As I say, this Q is firstly "why is an actor model on top of cats a bad idea" and maybe secondly "what do people do instead" :-)

You must be logged in to vote

I arrived to CE3 from Akka world, so I also had a hard time wrapping my head around this one at first :) still do sometimes!

How do you manage long running, independant, but identifiable processes? A process per session on a web server for example, or a process per long running async something or other.

Yes, fibers are indeed the answer. They are lightweight and generally awesome!

why doesn't this already exist - I must be missing something

It is fairly straightforward to make an "actor" using fs2's Channel API.

trait Channel[F[_], A] {
def send(a: A): F[Either[Channel.Closed, Unit]]
def stream: Stream[F, A]
}

https://github.com/typelevel/fs2/blob/main/core/shared/src/main/scala/f...

View full answer

Replies: 6 comments 10 replies

Comment options

armanbilge
Dec 5, 2021
Maintainer Sponsor

I arrived to CE3 from Akka world, so I also had a hard time wrapping my head around this one at first :) still do sometimes!

How do you manage long running, independant, but identifiable processes? A process per session on a web server for example, or a process per long running async something or other.

Yes, fibers are indeed the answer. They are lightweight and generally awesome!

why doesn't this already exist - I must be missing something

It is fairly straightforward to make an "actor" using fs2's Channel API.

trait Channel[F[_], A] {
def send(a: A): F[Either[Channel.Closed, Unit]]
def stream: Stream[F, A]
}

https://github.com/typelevel/fs2/blob/main/core/shared/src/main/scala/fs2/concurrent/Channel.scala

The send method should be pretty familiar :) to implement the "actor logic", you consume messages A from the stream and do something with them, e.g. fold over some internal "actor state". Then you can run that stream as a Fiber, and voila you have an "actor" :)

I didn't think Fibers were uniquely identifable - do I need to maintain a map of id->fiber myself?

Fibers are ultimately just objects and you can work with them as such, although there are many higher level APIs that are much more friendly.

As for why this pattern is not so popular, I think it just doesn't lend itself well to the FP paradigm :) consider the example of web server, for example. http4s models this concept as a function Request[F] => F[Response[F]] which of course can be run concurrently as a Fiber. The problem with Actors is that they do not fit this pattern very well: sending a message to an actor is a side effect F[Unit] (see the signature of send in Channel), and that actor will itself have to use side-effects to complete handling of the message. So in general it is more difficult to reason about a program whose logic is implemented with side effects (even if they are suspended in an F e.g. IO), rather than a Input => F[Output].

Anyway just my 2 cents, maybe someone smarter can give us both some real insight on the matter

You must be logged in to vote
5 replies
Comment options

yatesco Dec 5, 2021
Author

Thanks! That was really helpful.

Unfortunately I do want exactly the actor model. Essentially I want a "persistent object" that represents each user so it can progress a user's long running status.

I could of course turn it into a messages/event paradigm, or have a single state/map which represents all user's state.

I'm read this as "the actor paradigm is about maintaining state and being side effectful, both of which have different solutions in a strict FP environment" :-)

Comment options

armanbilge Dec 5, 2021
Maintainer Sponsor

the actor paradigm is about maintaining state and being side effectful, both of which have different solutions in a strict FP environment

this is a fantastic summary.

Essentially I want a "persistent object" that represents each user so it can progress a user's long running status.

Following from the above, FWIW I'm sure there is some pattern that can get you where you need. E.g. the Kleisli/Reader monad: https://typelevel.org/cats/datatypes/kleisli.html#other-uses, which lets you easily pass around a environment/context across your computation.

Comment options

SystemFw Jan 8, 2022
Collaborator

have a single state/map which represents all user's state.

You can have an abstraction over this with Ref (and soon, MapRef), and that would be the idiomatic way to do it. It's pretty easy to implement a simple, non distributed version of Akka in cats-effect (ultimately a local actor is a Queue plus some state in Ref, which are both there), but a lot of state machines can be built directly without needing this extra queue.

This talk should be a good starting point: https://systemfw.org/talks.html#scala-italy-2019

Comment options

SystemFw Jan 8, 2022
Collaborator

Especially with the help of @ChristopherDavenport https://github.com/davenverse/mapref , which is soon coming to cats-effect but you can use as a library now

Comment options

yatesco Jan 8, 2022
Author

Thanks!

Answer selected by yatesco
Comment options

yatesco
Dec 5, 2021
Author

this was too on-point :-)

https://twitter.com/buitengebieden_/status/1467439671865229314

You must be logged in to vote
1 reply
Comment options

bblfish Jan 8, 2022

Sadly that Tweet has gone.

Comment options

bblfish
Jan 8, 2022

Perhaps you should talk to @alcestes on the topic of Actors and cats effects. I put together a Twitter thread earlier this year on some of his talks and pointers to his work https://twitter.com/bblfish/status/1358392715118010369

You must be logged in to vote
1 reply
Comment options

yatesco Jan 8, 2022
Author

Thanks!

Comment options

bblfish
Jan 8, 2022

It would be useful to put together a list of use cases where actors are very useful and cannot be so easily done without.
I'll start with the following ideas (could be wrong)

  • HTTP clients: so that connections to a domain go through the same TCP connection and are throttled for politeness, esp with http/{2,3} (when called by the same user). I guess browsers already do that work, but in Java its is not done by default - well in Java it was done because of the cost of threading.
  • For a read/write web only one actor should be writing to a file at a time - changing it's state, so one would want HTTP Requests to be sequentialised. That is what I do with my read/write web server.
You must be logged in to vote
2 replies
Comment options

SystemFw Jan 12, 2022
Collaborator

Thing is, all those things are easily done with cats-effect without actors, and in fact arguably more easily than with actors

Comment options

bblfish Feb 24, 2022

Do you have some reading on how one would do that?
I guess it would be using Ref and Deferred somehow, as mentioned above.

I would like to understand at what point the Actor concepts start becoming important.
I guess this is related to pi calculus too. If so it would be give me a reason to read up on that (finally).

This comment was marked as spam.

Comment options

Swoorup
Sep 1, 2022

If you are still looking for actors, I put together a small gists using CE3, Ref, Deferred, magic. https://gist.github.com/Swoorup/1ac9b69e0c0f1c0925d1397a94b0a762

You must be logged in to vote
1 reply
Comment options

yatesco Sep 5, 2022
Author

thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Category
Q&A
Labels
None yet
6 participants