-
Notifications
You must be signed in to change notification settings - Fork 3.6k
Add entity id to sharding props (#24053) #24058
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
Add entity id to sharding props (#24053) #24058
Conversation
Can one of the repo owners verify this patch? |
OK TO TEST |
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.
Nice! Added some comments.
*/ | ||
def start( | ||
typeName: String, | ||
propsGen: ShardRegion.PropsGenerator, |
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 like it that it is called Factory in Java and Generator in Scala, could we just skip the function type alias instead, and call the param propsFactory here as well?
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.
Sorry, I saw the differences between the MessageExtractor and the Scala function types and didn't realize that was because there's 2 functions in that interface. I'll change it.
*/ | ||
trait PropsFactory { | ||
def props(entityId: String): Props | ||
} |
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.
Add the @FunctionalInterface annotation perhaps?
Test FAILed. |
Fails binary compatibility check, all changes are in places that shouldn't hurt though and can be filtered, the filter statements are in the failed build log and should go in a |
Fixes #24053 |
@johanandren
Followed by a stack trace. Can you point me to the right place? |
https://jenkins.akka.io:8498/job/pr-validator-per-commit-jenkins/10840/consoleFull |
586ccf8
to
839f04a
Compare
Test FAILed. |
839f04a
to
2f0c703
Compare
Test FAILed. |
2f0c703
to
62b610d
Compare
Test PASSed. |
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 it deserves a small section explaining how to get the entity Id, be it via the path name trick or via the new method, then it's good to go :-)
@@ -33,7 +32,7 @@ import scala.util.control.NonFatal | |||
import akka.actor.Status | |||
import akka.cluster.ClusterSettings | |||
import akka.cluster.ClusterSettings.DataCenter | |||
import akka.stream.{ Inlet, Outlet } | |||
import akka.cluster.sharding.ShardRegion.PropsFactory |
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.
good name
@@ -0,0 +1,2 @@ | |||
# 24058 - Add ClusterSharding.start overloads | |||
ProblemFilters.exclude[IncompatibleMethTypeProblem]("akka.cluster.sharding.ShardRegion.props") |
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.
good
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.
looking good, but a few small things
* from entity id. | ||
*/ | ||
@FunctionalInterface | ||
trait PropsFactory { |
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 do we need this instead of using java.util.function.Function
?
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.
@patriknw In the first commit (before @johanandren's comments) I had this interface for Java and a type alias for Scala, to keep in line with the other params (ExtractEntityId, MessageExtractor, etc.). I also think having a specific type for it makes it clearer what it's for. But it isn't necessary, I can change it if you'd like.
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 it makes it clearer for such a simple function, it's another level of indirection to look at to understand what the parameter is about
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 agree, I just didn't think that second step away from the original code :)
*/ | ||
def start( | ||
typeName: String, | ||
propsFactory: String ⇒ Props, |
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.
The name propsFactory
is a bit vague. Props of what? I think it should still be entityProps
, or entityPropsFactory
@@ -39,13 +39,14 @@ object ClusterShardingSpec { | |||
case object Stop | |||
final case class CounterChanged(delta: Int) | |||
|
|||
class Counter extends PersistentActor { | |||
def counterPropsFactory: String ⇒ Props = id ⇒ Props(new Counter(id)) |
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.
is this showing up in documentation? I think the idiom should be to define it in the companion object, as we recommend for ordinary Props also. And I don't think there is a need to define the function there.
object Counter {
val ShardingTypeName = "Counter"
def props(id: String): Props = Props(new Counter(id))
}
and when registering it:
ClusterSharding(system).start(Counter.ShardingTypeName, Counter.props, ...
or in docs perhaps better to spell it out:
ClusterSharding(system).start(Counter.ShardingTypeName, entityId => Counter.props(entityId), ...
|
||
//#supervisor | ||
class CounterSupervisor extends Actor { | ||
val counter = context.actorOf(Props[Counter], "theCounter") | ||
val counter = context.actorOf(Props(new Counter("theCounter")), "theCounter") |
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.
Props should be defined in companion object according to our recommendations, e.g. avoid mistakes of closing over non thread safe things such as sender()
|
||
* Using the `propsFactory` parameter to `ClusterSharding.start`. The entity ID will be passed to the factory as a | ||
parameter, which can then be used in the creation of the actor (like the above example). | ||
* Using the actor's name (`self.path.name`). The actor's name will be the utf-8 URL-enconded entity ID. |
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.
with this new api added I see no value in describing the alternative of using the self.path.name
Test PASSed. |
20ba758
to
ffa7cf7
Compare
Test PASSed. |
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.
additional nitpicks about the doc examples
@@ -6,6 +6,7 @@ package akka.cluster.sharding | |||
import java.net.URLEncoder | |||
import java.util.Optional | |||
import java.util.concurrent.ConcurrentHashMap | |||
import java.util.function.Function |
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 is a bit scary since we are used to that Function
is the Scala function.
we often rename that:
import java.util.function.{ Function => JFunction}
ActorRef startedCounterRegion = ClusterSharding.get(system).start("Counter", | ||
Props.create(Counter.class), settings, messageExtractor); | ||
ActorRef startedCounterRegion = ClusterSharding.get(system).start(Counter.ShardingTypeName, | ||
Counter.propsFactory, settings, messageExtractor); |
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 it's easer to read (understand) the docs by putting the function inline here
entityId -> Counter.props(entityId)
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.
Actually, what about Counter::props
for this?
(Should've seen that from the start, guess it's been a while since I wrote actual code in Java...)
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.
that should work, but for the same reason I argued about using explicit entityId parameter in the scala examples we should do that here also
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.
Alright, in that case this build should cover it (once it's done building)
|
||
private final ActorRef counter = getContext().actorOf( | ||
Props.create(Counter.class), "theCounter"); | ||
Counter.propsFactory.apply("theCounter"), "theCounter"); |
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 would be weird, entities would get the id "theCounter"
The CounterSupervisor
should also get its id from the factory parameter and pass that to Counter.props(entityId)
here.
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.
and similar in the scala example
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.
That seemed odd to me too, but that's the way it was originally (self.path.name
was "theCounter") so I didn't want to break anything. I'll change it.
@@ -58,6 +58,10 @@ Scala | |||
Java | |||
: @@snip [ClusterShardingTest.java]($code$/java/jdocs/sharding/ClusterShardingTest.java) { #counter-start } | |||
|
|||
In some cases, the actor may need to know the `entityId` associated with it. This can be achieved using the `propsFactory` |
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.
propsFactory was renamed
import ShardRegion.Passivate | ||
|
||
context.setReceiveTimeout(120.seconds) | ||
|
||
// self.path.name is the entity identifier (utf-8 URL-encoded) | ||
override def persistenceId: String = "Counter-" + self.path.name | ||
override def persistenceId: String = "Counter-" + id |
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.
s"${Counter.ShardingTypeName}-$id"
@Override | ||
public String persistenceId() { | ||
return "Counter-" + getSelf().path().name(); | ||
return "Counter-" + entityId; |
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.
ShardingTypeName + "-" + entityId
ffa7cf7
to
a8e5f48
Compare
Test PASSed. |
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.
LGTM
Refs #24053 |
thanks @talpr , it will be included in upcoming Akka 2.5.8 |
* Revert "fix entityPropsFactory id param, akka#21809" This reverts commit cd7eae2. * Revert "Merge pull request akka#24058 from talpr/talpr-24053-add-entity-id-to-sharding-props" This reverts commit 8417e70, reversing changes made to 22e85f8.
Add overloads for
ClusterSharding.start
that take function from entity id to props.I modified the tests that were included in the docs to use the id from props as well, let me know if you want me to revert that part...