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

[core] Unify ActorRef type #2275

Merged
merged 9 commits into from
Jun 7, 2021
Merged

[core] Unify ActorRef type #2275

merged 9 commits into from
Jun 7, 2021

Conversation

davidkpiano
Copy link
Member

This PR unifies the ActorRef type to contain all methods previously only present on the SpawnedActorRef type. This was found to be redundant in #2271, so now the types are as follows:

  • ActorRef contains all methods (required)
  • BaseActorRef only requires send; all other methods are optional. This should seldom be used.
  • SpawnedActorRef is now an alias to ActorRef; it is deprecated and will be removed in v5.

@changeset-bot
Copy link

changeset-bot bot commented Jun 3, 2021

🦋 Changeset detected

Latest commit: 219e80b

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
xstate Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@davidkpiano davidkpiano requested a review from Andarist June 3, 2021 02:49
packages/core/src/types.ts Outdated Show resolved Hide resolved
packages/core/src/types.ts Outdated Show resolved Hide resolved
@VanTanev
Copy link
Contributor

VanTanev commented Jun 3, 2021

What is the guidance about actorRef.id? Is it supposed to be globally-unique, or machine unique, or...?

It seems to be somewhat XState specific, rather than actor-specific.

@VanTanev
Copy link
Contributor

VanTanev commented Jun 3, 2021

The toActorRef() functon seems to not infer well:

type TEvent = { type: 'one' } | { type: 'two' }

type TActor = BaseActorRef<TEvent>
const baseActor: TActor = null!

// Argument of type 'TActor' is not assignable to parameter of type 'BaseActorRef<EventObject, any>'.
//  Type 'EventObject' is not assignable to type 'TEvent'.
//    Type 'EventObject' is not assignable to type '{ type: "two"; }'.
//      Types of property 'type' are incompatible.
//        Type 'string' is not assignable to type '"two"'.(2345)
const a = toActorRef(baseActor)

packages/core/src/types.ts Outdated Show resolved Hide resolved
extends ActorRef<TEvent, TEmitted> {
export interface ActorRef<TEvent extends EventObject, TEmitted = any>
extends Subscribable<TEmitted> {
send: Sender<TEvent>;
id: string;
getSnapshot: () => TEmitted | undefined;
stop?: () => void;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

q for v5: should we kill .stop on ActorRefs? should such direct call only be allowed for parents? being able to stop an arbitrary actor when the ref gets shared seems to be dangerous

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should be able to stop an actor from any other actor that has a ref to it. This matches the behavior in Akka; I don't see how this can be dangerous (obviously, it's the responsibility of the developer to stop it properly): https://alvinalexander.com/scala/how-to-stop-akka-actors-in-scala-gracefulstop-poisonpill/ Okay maybe not

Copy link
Member

@Andarist Andarist Jun 6, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMHO there are two dangers here:

  1. it's an imperative/eager call, we should prefer pure actions
  2. that actor may live both in contexts of different actors and also in internal structures of its parent, especially for the latter we can't just shift the responsibility of handling that to the user as they don't control that at all

According to the Akka docs we can find this:

Classic actors can be stopped with the stop method of ActorContext or ActorSystem. [...] There is also a stop method in the ActorContext but it can only be used for stopping direct child actors and not any arbitrary actor.

and this:

Typically the context is used for stopping the actor itself or child actors and the system for stopping top level actors

So it seems to me that stopping the arbitrary actor might not be a recommended pattern in Akka, even if possible.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right, but let's discuss in a separate PR, as this might be a breaking change.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@davidkpiano
Copy link
Member Author

What is the guidance about actorRef.id? Is it supposed to be globally-unique, or machine unique, or...?

It seems to be somewhat XState specific, rather than actor-specific.

Right; we can probably rename this to name (as it is in v5)

@davidkpiano
Copy link
Member Author

davidkpiano commented Jun 5, 2021

The toActorRef() functon seems to not infer well:

type TEvent = { type: 'one' } | { type: 'two' }

type TActor = BaseActorRef<TEvent>
const baseActor: TActor = null!

// Argument of type 'TActor' is not assignable to parameter of type 'BaseActorRef<EventObject, any>'.
//  Type 'EventObject' is not assignable to type 'TEvent'.
//    Type 'EventObject' is not assignable to type '{ type: "two"; }'.
//      Types of property 'type' are incompatible.
//        Type 'string' is not assignable to type '"two"'.(2345)
const a = toActorRef(baseActor)

Fixed in 15c6e7d (I believe)

Copy link
Member

@Andarist Andarist left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change affects public interfaces from the types perspective so adding some changeset about this would still be a good thing to do so people get aware of the change if it affects them anyhow

@davidkpiano davidkpiano added this to Committed in Next Jun 7, 2021
@davidkpiano davidkpiano removed this from Committed in Next Jun 7, 2021
@davidkpiano davidkpiano merged commit ae48a5d into main Jun 7, 2021
@github-actions github-actions bot mentioned this pull request Jun 7, 2021
@Andarist Andarist deleted the davidkpiano/2271 branch June 7, 2021 11:09
@github-actions github-actions bot mentioned this pull request Jun 7, 2021
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

Successfully merging this pull request may close these issues.

None yet

3 participants