-
Notifications
You must be signed in to change notification settings - Fork 0
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
Proposal for new interfaces assign strategy #1
base: master
Are you sure you want to change the base?
Conversation
interface AddOperation extends Operation { | ||
String targetNode(); | ||
String collection(); | ||
String slice(); |
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.
Let's use "shard" everywhere, there's already too much confusion between slice and shard.
interface MoveOperation extends AddOperation { | ||
|
||
String fromNode(); | ||
String replicaName(); |
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.
What is the replicaName? there's also a lot of confusion around this currently. Is it the core name? or coreNode name? Let's clarify it and use consistently.
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.
coreNodeName
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 coreNodeName global per cluster, or just the collection? should we use core name instead, which is unique?
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.
coreNodeName
is the global name. That's unique for a given collection
*/ | ||
interface MoveOperation extends AddOperation { | ||
|
||
String fromNode(); |
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 have an optional toNode if the requestor knows exactly where it wants to put the replica.
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 must go into the hints
/**Generic method invocation endpoint for v2 APIs | ||
* | ||
*/ | ||
String endPoint(); |
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.
What's the end point here? /c/collections? Do we have any others? maybe it should be a default method.
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, mostly . But there are other sub paths that support collection admin ops as well
/** | ||
* This operation adds a replica to a given collection/shard | ||
*/ | ||
interface AddOperation extends Operation { |
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 interface here? I would expect a concrete class that implements interface methods.
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.
Make the impl opaque
/** The payload. This will be serialized to JSON and will be psosted to SOlr | ||
* | ||
*/ | ||
MapWriter payload(); |
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.
Maybe this should be an abstract class, or at least provide a default implementation of this method to write out the common payload elements.
Operation extends MapWriter
would make sense too.
/** | ||
* The implementation class can be stored in clusterprops.json as follows | ||
* { | ||
* assign-strategy : { |
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 should be possible to load and use multiple named strategies. I can imagine a common default strategy that uses Policy framework for some collections, and an override in collection config to use another strategy for other collections where Policy doesn't work 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.
I would strongly recommend against that. A violation for one strategy may not be same for another
/** | ||
* get a list of operations that can be performed for the intents. | ||
* | ||
* There should be a one-to-one mapping between intent and operation |
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.
Then we need a NO_OP too. We also need to somehow report that the Intent could not be satisfied, maybe an INVALID op?
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.
Yes, I thought of that . Forgot to add
/** | ||
* Moves a replica | ||
*/ | ||
MOVE(CollectionParams.CollectionAction.MOVEREPLICA); |
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.
DELETEREPLICA too, for scenarios when you dynamically scale down.
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.
Yes.
void init(SolrCloudManager cloudManager); | ||
|
||
/** | ||
* get a list of operations that can be performed for the intents. |
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.
"can" or "will"? This is an important difference in semantics, because if you know you will perform these ops then you should make reservations for the positions. "Can" is much weaker, it doesn't lock out the slots for other concurrent computations.
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 do not know if the invoker "will" execute these operations.
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.
In other words, the assumption that this method is using the current cluster state that was provided to it and itself it does not make any reservations.
(Just clarifying ... I think that's ok, we could provide it a cluster view that already includes other operations in progress).
My main concern with the proposal is that the plugin code now depends on It's going to either be hard or painful to change code (Autoscaling or other related to cluster state etc) when contributions are not living in the same repository or might not be accessible to us at all and can't be refactored at the same time. |
Rough example of what I mean when I suggest to separate what the new assignment plugins can touch vs existing code.
Just committed to this branch what the beginning of what I'm thinking of would look like... |
|
||
int getCountReplicas(); | ||
long getTotalSizeBytes(); | ||
long getFreeSizeBytes(); |
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 need much more information that that here - sysprops, JVM and OS metrics, etc.
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.
Agreed.
|
||
interface AssignerCollectionState { | ||
String getCollectionName(); | ||
Iterator<String> getSliceNames(); |
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.
Please, let's not do this again ... :) Let's just use "shard" everywhere, it's already bad as it is.
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 fine with that. Shall we aim to get rid of Slice in general in Solr code?
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 would be great but it's another issue. I already filed Jira for removing ReplicaInfo, we have Replica that serves exactly the same role.
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.
No sure which is better. The shard is a an abused term. Solr code is littered with both
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.
Whichever we use, lets just use one consistently. Shard is abused? it always refers to a partition of the collection. Adding Slice was a mistake IMHO, but that was done early on when the terminology was still in flux. Nowadays in my experience people commonly use "shard" not "slice".
long getFreeSizeBytes(); | ||
} | ||
|
||
interface AssignerReplicaInfo { |
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.
Similarly, we need much more info here, too - things like replica state and replica metrics - stuff like physical size, number of docs, recent use, etc etc.
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.
Yes @sigram we actually need to make a comprehensive list of data needed to compute operations
String getCollectionName(); | ||
Iterator<String> getSliceNames(); | ||
|
||
Iterator<AssignerReplicaInfo> getSliceReplicasInfo(String sliceName); |
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 understand the desire to hide as much as possible how these are constructed, but we will frequently need things like size()
, so maybe better to use Collection
here and in similar places.
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.
My motivation to provide Iterator was for cases when it's likely we don't need the whole set/collection (lazy building). Maybe there aren't such cases.
interface AssignementRequest { | ||
} | ||
|
||
interface AddReplicaAssignmentRequest { |
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.
These probably can be concrete classes.
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 requests should not, no reason to expose an implementation to the plugin.
Maybe the decisions could be concrete classes that the plugin would instantiate though.
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.
interfaces are in general better
Replica.Type getType(); | ||
} | ||
|
||
interface AssignmentDecision { |
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 not pass in the original AssignmentRequest here? this will be needed for logging, tracking and debugging anyway.
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 was not assuming a one to one correspondance between assignement requests and decisions. The calling code (Solr calling the plugin) knows what it just passed in the call to computeAssignements() when it gets the list of AssignmentDecision back.
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.
Even if it's not always a 1:1 correspondence, in cases when it is it would be good to know what was the reason for this decision.
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 it possible that a request may not have a corresponding decision
?
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.
Or the other way around: a request having multiple decisions? Like create collection could result in multiple replica creations. Just making this up as I write, but it doesn't sound impossible.
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 see a problem in either case - we should be able to tie any decisions on the output to a particular intent on the input. In 1 -> N case each Decision would simply refer to the same Intent. In 1 -> null we have a NO_OP Decision. Is N -> M even realistic? I don't think so at the moment.
} | ||
|
||
interface AddReplicaAssignmentDecision extends AssignmentDecision { | ||
String getNodeName(); |
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 other properties could come from the AssignmentRequest referenced here.
Yes. @murblanc That I'm +1 for making a lighter |
I like your proposal. Why don't we make this formal and make a ticket ? |
@noblepaul give me a few more days please. I'd like to have a better global view of current Autoscaling to make sure this "stop gap" option (that's how I see my proposal) does go in the right longer term direction. |
No description provided.