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

Added support for UnrestrictedStash #6325

Merged
merged 1 commit into from
Jan 18, 2023

Conversation

ismaelhamed
Copy link
Member

@ismaelhamed ismaelhamed commented Jan 4, 2023

Currently, once you've marked your actor with any of the Stash interfaces (IWithUnboundedStash or IWithBoundedStash) there's no way to change it afterward via configuration (it is a design-time operation that requires recompiling).

But there are two traits that allow users to do that in the JVM:

  • A default Stash trait (IWithStash in this PR) which allows using any Deque-based mailbox (i.e., bounded or unbounded) via configuration. By default, it uses an UnboundedDeque mailbox, so it is akin to the current IWithUnboundedStash if you don't specify a custom mailbox type.

  • UnrestrictedStash trait, which does not enforce any mailbox type. The proper mailbox must be configured
    manually.

Checklist

[Obsolete("Bounded stashing is not yet implemented. Unbounded stashing will be used instead [0.7.0]")]
public interface IWithBoundedStash : IActorStash, IRequiresMessageQueue<IBoundedDequeBasedMessageQueueSemantics>
[Obsolete("Use `IWithStash` with a configured BoundedDeque-based mailbox instead.")]
public interface IWithBoundedStash : IWithUnrestrictedStash, IRequiresMessageQueue<IBoundedDequeBasedMessageQueueSemantics>
Copy link
Member Author

@ismaelhamed ismaelhamed Jan 4, 2023

Choose a reason for hiding this comment

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

We can remove this type since typically you'd want to change the mailbox or stash capacity with a bounded deque, which cannot be done programmatically (AFAIK)

Copy link
Member

Choose a reason for hiding this comment

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

Let's remove this type in v1.5 in a separate PR - I'd like to backport this as-is to v1.4 first.

}

if (actorType.Implements<IWithUnrestrictedStash>())
return new UnrestrictedStashImpl(context);

throw new ArgumentException($"Actor {actorType} implements an unrecognized subclass of {typeof(IActorStash)} - cannot instantiate", nameof(actorType));
}
Copy link
Member Author

Choose a reason for hiding this comment

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

BoundedStashImpl, UnboundedStashImpl and UnrestrictedStashImpl are all empty implementations, so we could get away with a single type (i.e., StashSupportImpl) like in the JVM.

@Aaronontheweb
Copy link
Member

UnrestrictedStash trait, which does not enforce any mailbox type. The proper mailbox must be configured
manually.

So in practice, how does this work? The user has to manually specify a mailbox type in addition to specifying the stash type?

@ismaelhamed
Copy link
Member Author

ismaelhamed commented Jan 5, 2023

UnrestrictedStash trait, which does not enforce any mailbox type. The proper mailbox must be configured
manually.

So in practice, how does this work? The user has to manually specify a mailbox type in addition to specifying the stash type?

Correct. By using IWithUnrestrictedStash you're opting out from the framework enforcing any mailbox type, but you must specify one (there's no default mailbox in this case).

@ismaelhamed ismaelhamed force-pushed the unrestricted-stash branch 2 times, most recently from 971318e to 57d9f60 Compare January 5, 2023 08:00
@ismaelhamed
Copy link
Member Author

Updated the documentation.

As an addendum to my previous comment, you now have two main stash interfaces to work with:

  • IWithStash, which is "unrestricted" since it allows both bounded and unbounded deque-based mailboxes. Defaults to unbounded if not specified otherwise.
  • IWithUnboundedStash, if you want to enforce that your actor can only work with an unbounded stash.

The UnrestrictedStash type is there to solve the single inheritance problem in JAVA, which I've respected for the sake of maintaining a compatible API. But since a Stash's mailbox MUST be deque-based anyway, using IWithStash or IWithUnrestrictedStash is basically the same (except that in the latter you must always specify a mailbox).

@ismaelhamed
Copy link
Member Author

@Aaronontheweb could we backport this and #6323 to v1.4?

@ismaelhamed
Copy link
Member Author

Unrelated tests failing

@Aaronontheweb
Copy link
Member

I put it on my planner to review this today - will do @ismaelhamed

@Aaronontheweb
Copy link
Member

@Aaronontheweb could we backport this and #6323 to v1.4?

yep, I don't see why not provided that there's nothing high risk in the PR

Copy link
Member

@Aaronontheweb Aaronontheweb left a comment

Choose a reason for hiding this comment

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

LGTM


Here is an example of the `IWithUnboundedStash` interface in action:
> [!NOTE]
> The interface `IWithStash` implements the marker interface `IRequiresMessageQueue<IDequeBasedMessageQueueSemantics>` which requests the system to automatically choose a deque-based mailbox implementation for the actor (defaults to an unbounded deque mailbox). If you want more control over the mailbox, see the documentation on mailboxes: [Mailboxes](xref:mailboxes).
Copy link
Member

Choose a reason for hiding this comment

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

LGTM

The result of this is that when an actor is restarted, any stashed messages will be delivered to the new incarnation of the actor. This is usually the desired behavior.

> [!NOTE]
> If you want to enforce that your actor can only work with an unbounded stash, then you should use the `IWithUnboundedStash` interface instead.
Copy link
Member

Choose a reason for hiding this comment

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

LGTM

public interface IWithTimers
{
Akka.Actor.ITimerScheduler Timers { get; set; }
}
public interface IWithUnboundedStash : Akka.Actor.IActorStash, Akka.Dispatch.IRequiresMessageQueue<Akka.Dispatch.IUnboundedDequeBasedMessageQueueSemantics> { }
public interface IWithUnboundedStash : Akka.Actor.IActorStash, Akka.Actor.IWithUnrestrictedStash, Akka.Dispatch.IRequiresMessageQueue<Akka.Dispatch.IUnboundedDequeBasedMessageQueueSemantics> { }
Copy link
Member

Choose a reason for hiding this comment

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

This is extend-only, so it's safe.

@@ -272,7 +272,7 @@ namespace Akka.Persistence.Sql.Common.Journal
public long Offset { get; }
public Akka.Actor.IActorRef ReplyTo { get; }
}
public abstract class SqlJournal : Akka.Persistence.Journal.AsyncWriteJournal, Akka.Actor.IActorStash, Akka.Actor.IWithUnboundedStash, Akka.Dispatch.IRequiresMessageQueue<Akka.Dispatch.IUnboundedDequeBasedMessageQueueSemantics>
public abstract class SqlJournal : Akka.Persistence.Journal.AsyncWriteJournal, Akka.Actor.IActorStash, Akka.Actor.IWithUnboundedStash, Akka.Actor.IWithUnrestrictedStash, Akka.Dispatch.IRequiresMessageQueue<Akka.Dispatch.IUnboundedDequeBasedMessageQueueSemantics>
Copy link
Member

Choose a reason for hiding this comment

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

This makes me think that we might have to update all of the Akka.Persistence plugins, since the journal currently uses an unbounded stash. I don't think that should be important unless there's something on the normal IWithUnrestrictedStash interface that could cause a MissingMethodException but it looks to me like there isn't any. Just wanted to make note of this in case I'm wrong.

Copy link
Member Author

Choose a reason for hiding this comment

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

Not really because the journal is still implementing IWithUnboundedStash which is more constrained. So, the mailbox is going to be selected based on it and not IWithUnrestrictedStash.

[Obsolete("Bounded stashing is not yet implemented. Unbounded stashing will be used instead [0.7.0]")]
public interface IWithBoundedStash : IActorStash, IRequiresMessageQueue<IBoundedDequeBasedMessageQueueSemantics>
[Obsolete("Use `IWithStash` with a configured BoundedDeque-based mailbox instead.")]
public interface IWithBoundedStash : IWithUnrestrictedStash, IRequiresMessageQueue<IBoundedDequeBasedMessageQueueSemantics>
Copy link
Member

Choose a reason for hiding this comment

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

Let's remove this type in v1.5 in a separate PR - I'd like to backport this as-is to v1.4 first.

@Aaronontheweb Aaronontheweb merged commit 7b1090d into akkadotnet:dev Jan 18, 2023
ismaelhamed added a commit to ismaelhamed/akka.net that referenced this pull request Jan 21, 2023
Aaronontheweb added a commit that referenced this pull request Jan 24, 2023
)

* Read stash capacity from actor's mailbox or dispatcher configuration (#6323)

* Added support for `UnrestrictedStash` (#6325)

* Add API for UntypedActorWithStash types (#6327)

Co-authored-by: Aaron Stannard <aaron@petabridge.com>

Co-authored-by: Aaron Stannard <aaron@petabridge.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
No open projects
Development

Successfully merging this pull request may close these issues.

2 participants