From a3b5fbdbdad8c4d48113d0771e4c4dc72296ea66 Mon Sep 17 00:00:00 2001 From: Gavin Bauman Date: Tue, 30 May 2023 15:20:40 -0400 Subject: [PATCH 1/3] init commit - wip --- ...e-actor-model-and-when-should-i-use-it.mdx | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 content/posts/2023-5-30-what-is-the-actor-model-and-when-should-i-use-it.mdx diff --git a/content/posts/2023-5-30-what-is-the-actor-model-and-when-should-i-use-it.mdx b/content/posts/2023-5-30-what-is-the-actor-model-and-when-should-i-use-it.mdx new file mode 100644 index 0000000..36330f3 --- /dev/null +++ b/content/posts/2023-5-30-what-is-the-actor-model-and-when-should-i-use-it.mdx @@ -0,0 +1,37 @@ +--- +title: What is the Actor Model and When Should I Use It? +description: "Defines the Actor Model, its use cases, discusses using it with statecharts" +tags: + - actor model + - modeling + - statechart + - tutorials + - state machine + - typescript + - blog +author: Gavin Bauman +publishedAt: 2023-5-30 +--- + +At Stately, the [Actor Model](https://en.wikipedia.org/wiki/Actor_model) is one of our favorite programming paradigms, and we think it's for good reason! The actor model allows developers to build reliable message-based systems by using _actors_ to communicate. This works extremely well with state machines and statecharts, which can also be modeled as actors and can communicate much in the same ways. Read on to learn what the actor model is, the problems it seeks to solve, and how you can use it in your projects to communicate reliably across different entities. + +## What is the actor model? + +The actor model has been around for quite a while, dating back to the 1970's. The fact that it's still around is a bit of a testament to its utility. When researching the actor model, it's very common to see the phrase "everything is an actor", as it is a core tenant in the actor model philosophy. This simply means that in a given system, the _actor_ is the core unit of execution. Every action that occurs in the system is driven by an actor. An actor can communicate with other actors with the use of messaging, and they can also interact with external systems. Specifically, an actor can perform the following basic tasks: + +- Actors can spawn other actors +- Actors can send messages to other actors +- Actors can respond to received messages +- Actors can manage their own internal state + +It may sound simple, but this framework allows for the development of highly scalable and concurrent systems. There are constraints though, the most important of which is that an actor _cannot_ modify the internal state of another actor directly. This can be done implicitly with messaging (i.e an actor updating its state in response to a message) but never directly. + +## How does Stately use the actor model? + +With XState, + +// example implementation + +// when should you use the actor model? + +// example implementation From d23626770b493b42b30efece76bf5ac2ac3d590c Mon Sep 17 00:00:00 2001 From: Gavin Bauman Date: Thu, 1 Jun 2023 02:30:44 -0400 Subject: [PATCH 2/3] first draft --- ...e-actor-model-and-when-should-i-use-it.mdx | 77 +++++++++++++++++-- 1 file changed, 69 insertions(+), 8 deletions(-) diff --git a/content/posts/2023-5-30-what-is-the-actor-model-and-when-should-i-use-it.mdx b/content/posts/2023-5-30-what-is-the-actor-model-and-when-should-i-use-it.mdx index 36330f3..5cd6cd3 100644 --- a/content/posts/2023-5-30-what-is-the-actor-model-and-when-should-i-use-it.mdx +++ b/content/posts/2023-5-30-what-is-the-actor-model-and-when-should-i-use-it.mdx @@ -17,21 +17,82 @@ At Stately, the [Actor Model](https://en.wikipedia.org/wiki/Actor_model) is one ## What is the actor model? -The actor model has been around for quite a while, dating back to the 1970's. The fact that it's still around is a bit of a testament to its utility. When researching the actor model, it's very common to see the phrase "everything is an actor", as it is a core tenant in the actor model philosophy. This simply means that in a given system, the _actor_ is the core unit of execution. Every action that occurs in the system is driven by an actor. An actor can communicate with other actors with the use of messaging, and they can also interact with external systems. Specifically, an actor can perform the following basic tasks: +The actor model has been around for quite a while, dating back to the 1970's. That it's used with frameworks like [Akka](https://akka.io/) and built natively into languages like Erlang(https://www.erlang.org/) are testaments to its utility. When researching the actor model, it's very common to see the phrase "everything is an actor", as it is a core tenant in the actor model philosophy. This simply means that in a given system, the _actor_ is the core unit of execution. Every action that occurs in the system is driven by an actor. An actor can communicate with other actors with the use of messaging, and they can also interact with external systems. Specifically, an actor can perform the following basic tasks: - Actors can spawn other actors - Actors can send messages to other actors -- Actors can respond to received messages - Actors can manage their own internal state -It may sound simple, but this framework allows for the development of highly scalable and concurrent systems. There are constraints though, the most important of which is that an actor _cannot_ modify the internal state of another actor directly. This can be done implicitly with messaging (i.e an actor updating its state in response to a message) but never directly. +It may sound simple, but this programming model allows for the development of highly scalable and concurrent systems. There are constraints though, the most important of which is that an actor _cannot_ modify the internal state of another actor directly. This can be done implicitly with messaging (i.e an actor updating its state in response to a message) but _never directly_. -## How does Stately use the actor model? +## When should I use it? -With XState, +The actor model is extremely useful for divvying work that can be processed in parallel. It's excellent for "fan-out/fan-in" scenarios where several functions need to be run at once and have their results combined before final processing. It also works well with building pub/sub systems, where several actors can be "workers", waiting for messages from the "publisher". Our last example, but certainly not the least, is in the case of systems that need to manage several similar entities, like a multiplayer game where every player is represented as an actor. A good rule of thumb is to at least consider the actor model whenever distribution and concurrency are core requirements. -// example implementation +## When not to use it -// when should you use the actor model? +As with any pattern, it's just as important to understand its weaknesses as it is to understand its strengths. Typically you may not want to use the actor pattern when order really matters. Order is usually not promised in the actor pattern, and if one of the actors fails, you'll have to deal with the concern of rolling back events. The actor model is often unnecessary when dealing with synchronous problems as well, and can add unnecessary overhead. Additionally, error handling can be tricky with actors. Erlang popularized the "let it crash" philosophy, but given the problem, it may not always be the most reasonable answer. -// example implementation +## How does Stately work with the actor model? + +With XState, we expose the ability to create instances of machines as actors! Looking at the example below, we can see that after defining our machine and its attributes, we only need to use `interpret()` to instantiate an actor (called `toggleActor`) and send it messages. + +```typescript +import { createMachine, interpret } from "xstate"; + +// State machine definition +const toggleMachine = createMachine({ + id: "toggle", + initial: "inactive", + states: { + inactive: { on: { TOGGLE: "active" } }, + active: { on: { TOGGLE: "inactive" } }, + }, +}); + +// Machine instance with internal state +const toggleActor = interpret(toggleMachine); +toggleActor.subscribe((state) => console.log(state.value)); +toggleActor.start(); +// => logs 'inactive' + +toggleActor.send({ type: "TOGGLE" }); +// => logs 'active' + +toggleActor.send({ type: "TOGGLE" }); +// => logs 'inactive' +``` + +This actor has its own state and context, and it can be updated whenever it receives events. Of course, in order for the internal state of an actor to be updated, the event must be a legal transition defined with the machine. + +### Spawning Actors + +XState can also be used to spawn other actors and communicate with each other: + +```typescript +import { createMachine, spawn } from "xstate"; +import { todoMachine } from "./todoMachine"; + +const todosMachine = createMachine({ + // ... + on: { + "NEW_TODO.ADD": { + actions: assign({ + todos: (context, event) => [ + ...context.todos, + { + todo: event.todo, + // add a new todoMachine actor with a unique name + ref: spawn(todoMachine, `todo-${event.id}`, { sync: true }), + }, + ], + }), + }, + // ... + }, +}); +``` + +With the use of `spawn()` and `assign()`, we create a new actor instance when provided the machine and a unique identifier. By their nature, actions are ["fire and forget" effects](https://xstate.js.org/docs/guides/actions.html#api), meaning they are actions that are executed with no expectation of receiving events back to the actor. This makes sense for creating a new actor, but we may still want the parent actor to have a reference to its child, so we save that in its context using `assign()`. `spawn()` is the function called that actually creates the new actor. `spawn()` also sports another useful feature in that it accepts an `options` object with an optional `sync` property. Setting this to `true` allows the parent actor to subscribe to the child's current state. The parent can access this state easily by calling `getSnapshot()` on the reference to the child. + +For more detailed examples around working with actors in XState, like callback or promised-based actor spawning, sending updates, and communicating between actors, [check out the guides in the XState documentation](https://xstate.js.org/docs/guides/actors.html). From eec46219f843bd3f8857266b23ac1ff0dac2b13f Mon Sep 17 00:00:00 2001 From: laurakalbag Date: Fri, 2 Jun 2023 14:18:10 +0100 Subject: [PATCH 3/3] =?UTF-8?q?Convert=20"/'=20straight=20quotes=20to=20?= =?UTF-8?q?=E2=80=9C/=E2=80=99=20curly=20quotes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...hat-is-the-actor-model-and-when-should-i-use-it.mdx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/content/posts/2023-5-30-what-is-the-actor-model-and-when-should-i-use-it.mdx b/content/posts/2023-5-30-what-is-the-actor-model-and-when-should-i-use-it.mdx index 5cd6cd3..40ce44e 100644 --- a/content/posts/2023-5-30-what-is-the-actor-model-and-when-should-i-use-it.mdx +++ b/content/posts/2023-5-30-what-is-the-actor-model-and-when-should-i-use-it.mdx @@ -13,11 +13,11 @@ author: Gavin Bauman publishedAt: 2023-5-30 --- -At Stately, the [Actor Model](https://en.wikipedia.org/wiki/Actor_model) is one of our favorite programming paradigms, and we think it's for good reason! The actor model allows developers to build reliable message-based systems by using _actors_ to communicate. This works extremely well with state machines and statecharts, which can also be modeled as actors and can communicate much in the same ways. Read on to learn what the actor model is, the problems it seeks to solve, and how you can use it in your projects to communicate reliably across different entities. +At Stately, the [Actor Model](https://en.wikipedia.org/wiki/Actor_model) is one of our favorite programming paradigms, and we think it’s for good reason! The actor model allows developers to build reliable message-based systems by using _actors_ to communicate. This works extremely well with state machines and statecharts, which can also be modeled as actors and can communicate much in the same ways. Read on to learn what the actor model is, the problems it seeks to solve, and how you can use it in your projects to communicate reliably across different entities. ## What is the actor model? -The actor model has been around for quite a while, dating back to the 1970's. That it's used with frameworks like [Akka](https://akka.io/) and built natively into languages like Erlang(https://www.erlang.org/) are testaments to its utility. When researching the actor model, it's very common to see the phrase "everything is an actor", as it is a core tenant in the actor model philosophy. This simply means that in a given system, the _actor_ is the core unit of execution. Every action that occurs in the system is driven by an actor. An actor can communicate with other actors with the use of messaging, and they can also interact with external systems. Specifically, an actor can perform the following basic tasks: +The actor model has been around for quite a while, dating back to the 1970’s. That it’s used with frameworks like [Akka](https://akka.io/) and built natively into languages like Erlang(https://www.erlang.org/) are testaments to its utility. When researching the actor model, it’s very common to see the phrase “everything is an actor”, as it is a core tenant in the actor model philosophy. This simply means that in a given system, the _actor_ is the core unit of execution. Every action that occurs in the system is driven by an actor. An actor can communicate with other actors with the use of messaging, and they can also interact with external systems. Specifically, an actor can perform the following basic tasks: - Actors can spawn other actors - Actors can send messages to other actors @@ -27,11 +27,11 @@ It may sound simple, but this programming model allows for the development of hi ## When should I use it? -The actor model is extremely useful for divvying work that can be processed in parallel. It's excellent for "fan-out/fan-in" scenarios where several functions need to be run at once and have their results combined before final processing. It also works well with building pub/sub systems, where several actors can be "workers", waiting for messages from the "publisher". Our last example, but certainly not the least, is in the case of systems that need to manage several similar entities, like a multiplayer game where every player is represented as an actor. A good rule of thumb is to at least consider the actor model whenever distribution and concurrency are core requirements. +The actor model is extremely useful for divvying work that can be processed in parallel. It’s excellent for “fan-out/fan-in” scenarios where several functions need to be run at once and have their results combined before final processing. It also works well with building pub/sub systems, where several actors can be “workers”, waiting for messages from the “publisher”. Our last example, but certainly not the least, is in the case of systems that need to manage several similar entities, like a multiplayer game where every player is represented as an actor. A good rule of thumb is to at least consider the actor model whenever distribution and concurrency are core requirements. ## When not to use it -As with any pattern, it's just as important to understand its weaknesses as it is to understand its strengths. Typically you may not want to use the actor pattern when order really matters. Order is usually not promised in the actor pattern, and if one of the actors fails, you'll have to deal with the concern of rolling back events. The actor model is often unnecessary when dealing with synchronous problems as well, and can add unnecessary overhead. Additionally, error handling can be tricky with actors. Erlang popularized the "let it crash" philosophy, but given the problem, it may not always be the most reasonable answer. +As with any pattern, it’s just as important to understand its weaknesses as it is to understand its strengths. Typically you may not want to use the actor pattern when order really matters. Order is usually not promised in the actor pattern, and if one of the actors fails, you’ll have to deal with the concern of rolling back events. The actor model is often unnecessary when dealing with synchronous problems as well, and can add unnecessary overhead. Additionally, error handling can be tricky with actors. Erlang popularized the “let it crash” philosophy, but given the problem, it may not always be the most reasonable answer. ## How does Stately work with the actor model? @@ -93,6 +93,6 @@ const todosMachine = createMachine({ }); ``` -With the use of `spawn()` and `assign()`, we create a new actor instance when provided the machine and a unique identifier. By their nature, actions are ["fire and forget" effects](https://xstate.js.org/docs/guides/actions.html#api), meaning they are actions that are executed with no expectation of receiving events back to the actor. This makes sense for creating a new actor, but we may still want the parent actor to have a reference to its child, so we save that in its context using `assign()`. `spawn()` is the function called that actually creates the new actor. `spawn()` also sports another useful feature in that it accepts an `options` object with an optional `sync` property. Setting this to `true` allows the parent actor to subscribe to the child's current state. The parent can access this state easily by calling `getSnapshot()` on the reference to the child. +With the use of `spawn()` and `assign()`, we create a new actor instance when provided the machine and a unique identifier. By their nature, actions are ["fire and forget" effects](https://xstate.js.org/docs/guides/actions.html#api), meaning they are actions that are executed with no expectation of receiving events back to the actor. This makes sense for creating a new actor, but we may still want the parent actor to have a reference to its child, so we save that in its context using `assign()`. `spawn()` is the function called that actually creates the new actor. `spawn()` also sports another useful feature in that it accepts an `options` object with an optional `sync` property. Setting this to `true` allows the parent actor to subscribe to the child’s current state. The parent can access this state easily by calling `getSnapshot()` on the reference to the child. For more detailed examples around working with actors in XState, like callback or promised-based actor spawning, sending updates, and communicating between actors, [check out the guides in the XState documentation](https://xstate.js.org/docs/guides/actors.html).