-
Notifications
You must be signed in to change notification settings - Fork 1k
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
Akka Fsm Update #2559
Akka Fsm Update #2559
Conversation
src/core/Akka/Actor/FSM.cs
Outdated
/// <param name="nextStateName">State designator for the next state</param> | ||
/// <param name="stateData">Data for next state</param> | ||
/// <returns>State transition descriptor</returns> | ||
[Obsolete("GoTo method is osboleted. Use GoTo(TState nextStateName) [1.2.0]")] | ||
public State<TState, TData> GoTo(TState nextStateName, TData stateData) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method is not present in the Scala API
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think I've even seen this method get used. It's always been GoTo().WithState
AFAIK
@@ -1059,7 +1059,7 @@ public State ForMax(TimeSpan timeout) | |||
/// <summary> | |||
/// TBD | |||
/// </summary> | |||
public List<object> Replies | |||
public IReadOnlyCollection<object> Replies |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should prefer ReadOnly*
and Immutable
collections in the public API. But this change could break compatibility
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It shouldn't really affect how end-users are consuming it that much, unless they were modifying the collection themselves which would have been "illegal" anyway. Guess this falls into the gray area of "is fixing a bug in the public API really a breaking change?" I'm fine with it.
[Fact] | ||
public void FSM_must_notify_unhandled_messages() | ||
{ | ||
// EventFilter |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
EventFilter chaining is not working as expected
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm assuming that's unrelated to this PR, and IIRC it's an area where we have some known bugs still anyway.
src/core/Akka/Actor/FSM.cs
Outdated
public class Shutdown : Reason { } | ||
public sealed class Shutdown : Reason | ||
{ | ||
private Shutdown() { } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This one could break compatibility. Probably I should keep a public constructor with ObsoletedAttribute
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as previous. Go ahead and add that back.
src/core/Akka/Actor/FSM.cs
Outdated
public class Normal : Reason { } | ||
public sealed class Normal : Reason | ||
{ | ||
private Normal() { } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This one could break compatibility. Probably I should keep a public constructor with ObsoletedAttribute
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I would do that.
if(_debugLog != null) | ||
send = () => | ||
{ | ||
_debugLog.Debug("{0}Timer '{1}' went off. Sending {2} -> {3}",_ref.IsCancellationRequested ? "Cancelled " : "", name, message, actor); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why this debugging was implemented? It is not present in the scala API
} | ||
|
||
/// <summary> | ||
/// TBD | ||
/// </summary> | ||
public void Cancel() | ||
{ | ||
if (!_ref.IsCancellationRequested) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IsCancellationRequested
is always false
src/core/Akka/Actor/FSM.cs
Outdated
public class StateTimeout { } | ||
public sealed class StateTimeout | ||
{ | ||
private StateTimeout() { } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This one could break compatibility. Probably I should keep a public constructor with ObsoletedAttribute
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as previous. Go ahead and add that back.
Why we have implemented |
f98f770
to
294354b
Compare
Should I implement this one? |
When we are |
Why we need |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some minor changes requested, but otherwise it looks good.
@@ -768,52 +769,55 @@ namespace Akka.Actor | |||
public abstract class FSMBase : Akka.Actor.ActorBase | |||
{ | |||
protected FSMBase() { } | |||
public class CurrentState<TS> | |||
public sealed class CurrentState<TS> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sealing all of this off seems good to me.
@@ -846,14 +846,14 @@ namespace Akka.Persistence.Fsm | |||
public void WhenUnhandled(Akka.Persistence.Fsm.PersistentFSMBase<TState, TData, TEvent>.StateFunction stateFunction) { } | |||
public class State<TState, TData, TEvent> : Akka.Actor.FSMBase.State<TState, TData> | |||
{ | |||
public State(TState stateName, TData stateData, System.Nullable<System.TimeSpan> timeout = null, Akka.Actor.FSMBase.Reason stopReason = null, System.Collections.Generic.List<object> replies = null, Akka.Util.ILinearSeq<TEvent> domainEvents = null, System.Action<TData> afterTransitionDo = null) { } | |||
public State(TState stateName, TData stateData, System.Nullable<System.TimeSpan> timeout = null, Akka.Actor.FSMBase.Reason stopReason = null, System.Collections.Generic.IReadOnlyCollection<object> replies = null, Akka.Util.ILinearSeq<TEvent> domainEvents = null, System.Action<TData> afterTransitionDo = null) { } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Like this change too. We should have been using read-only collections from the start here.
@@ -1059,7 +1059,7 @@ public State ForMax(TimeSpan timeout) | |||
/// <summary> | |||
/// TBD | |||
/// </summary> | |||
public List<object> Replies | |||
public IReadOnlyCollection<object> Replies |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It shouldn't really affect how end-users are consuming it that much, unless they were modifying the collection themselves which would have been "illegal" anyway. Guess this falls into the gray area of "is fixing a bug in the public API really a breaking change?" I'm fine with it.
[Fact] | ||
public void FSM_must_notify_unhandled_messages() | ||
{ | ||
// EventFilter |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm assuming that's unrelated to this PR, and IIRC it's an area where we have some known bugs still anyway.
src/core/Akka/Actor/FSM.cs
Outdated
public class Normal : Reason { } | ||
public sealed class Normal : Reason | ||
{ | ||
private Normal() { } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I would do that.
src/core/Akka/Actor/FSM.cs
Outdated
/// <param name="nextStateName">State designator for the next state</param> | ||
/// <param name="stateData">Data for next state</param> | ||
/// <returns>State transition descriptor</returns> | ||
[Obsolete("GoTo method is osboleted. Use GoTo(TState nextStateName) [1.2.0]")] | ||
public State<TState, TData> GoTo(TState nextStateName, TData stateData) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think I've even seen this method get used. It's always been GoTo().WithState
AFAIK
if(_timers.ContainsKey(name)) | ||
if (DebugEvent) | ||
{ | ||
_log.Debug($"setting {(repeat ? "repeating" : "")} timer {name}/{timeout}: {msg}"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Liking the C#6 API here... makes it way easier to read.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hold my beer. I'm planning to do C# 7 refactoring :)
src/core/Akka/Actor/FSM.cs
Outdated
_stateTimeouts.Add(state, timeout); | ||
else | ||
_stateTimeouts[state] = timeout; | ||
_stateTimeouts.AddOrSet(state, timeout); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Change this to
stateTimeouts[state] = timeout
AddOrSet is something stupid I added to the codebase that we should deprecate and remove at some point. It's an unnecessary abstraction.
}) | ||
.With<InternalActivateFsmLogging>(_=> { DebugEvent = true; }) | ||
.Default(msg => | ||
ProcessMsg(StateTimeout.Instance, "state timeout"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Way easier to read (the main FSM handling routine) and will have fewer allocations also. Nice job.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should avoid of PatternMatch class
src/core/Akka/Actor/FSM.cs
Outdated
replies.Reverse(); | ||
foreach (var r in replies) { Sender.Tell(r); } | ||
if (!_currentState.StateName.Equals(upcomingState.StateName)) | ||
nextState.Replies.Reverse().ForEach(r => Sender.Tell(r)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Much cleaner.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I should get it back. List.Reverse has better performance than IEnumerable.Reverse
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
instead of reversing the list and then iterating, why not do both like
for (int i = nextState.Replies.Count - 1; i >= 0; i--)
{
Sender.Tell(nextState.Replies[i]);
}
2159c5d
to
a2bd36f
Compare
a2bd36f
to
77a5330
Compare
@@ -854,7 +854,7 @@ namespace Akka.Persistence.Fsm | |||
public System.Action<TData> AfterTransitionHandler { get; } | |||
public Akka.Util.ILinearSeq<TEvent> DomainEvents { get; } | |||
public bool Notifies { get; set; } | |||
public System.Collections.Generic.IReadOnlyCollection<object> Replies { get; } | |||
public System.Collections.Generic.IReadOnlyList<object> Replies { get; } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why the switch to IReadOnlyList ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because I've implemented this code :)
for (int i = nextState.Replies.Count - 1; i >= 0; i--)
{
Sender.Tell(nextState.Replies[i]);
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
@alexvaluyskiy on the |
FSMActor_must_unlock_the_lock
testFSMActor_must_log_events_and_transitions_if_asked_to_do_so
testFSMActor_must_fill_rolling_event_log_and_hand_it_out
test