-
Notifications
You must be signed in to change notification settings - Fork 5.8k
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
ddl: refactor constraint [2/6] #24005
Conversation
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, minor nits.
name: "not tiflash", | ||
input: "-engine = tiflash ", | ||
label: Constraint{ | ||
Key: "engine", | ||
Op: NotIn, | ||
Values: []string{"tiflash"}, | ||
}, |
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.
Should it have some tests where the case of tiflash
is upper? The code lowers it for comparison, but does not save it in values as lower as it parses it (making it compatible with previous code). But I'm wondering if it should lower when saving in values so the string is effectively normalized (space removed, consistent case 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.
I think there is one test for it, the typo one pointed out by you.
{
name: "disallow tiflash",
input: "+engine=Tiflash",
err: ErrUnsupportedConstraint,
},
But I'm wondering if it should lower when saving in values so the string is effectively normalized.
There should not be any normalization during comparison. I mean, I only do lowering for TiFlash, and it is a special case. It seems that we have no official doc, or spec for upper/lower cases of engine labels, so i added lower checking for a more relax check(so that tiflash will be banned even if it is TiFlash, Tiflash, or whatever).
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 is a bit of a strange behavior if the token TiFlash is case insensitive, but other tokens are stored in original case?
I think tokens are always case insensitive in MySQL, but in either case you decide (or don't decide), I think it makes sense to capture the current expected behavior in tests:
input: "+ZONE=BJ",
input: "+Zone=Bj",
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 thing is it is not a token, but a string. The syntax is like CONSTRIANTS="+zone=bj"
. Here we use this string a "pattern matcher", which will match constraints added by user, or the software itself. PD and TiDB both have a matcher: TiDB will match on the constraints cache, PD will match on the persisted constraints.
So, there are other two concerns:
zone,bj
kv pair is added by a user. But possibly not by a SQL of TiDB, e.g. tidb-operator could add such label. They won't normalize the label.- PD match case insensitively. It is also strange that TiDB is insensitive, but PD is sensitive.
For TiFlash
, it is just, I don't know, if the value is always TiFlash
. I mean, there is no spec for that. And this label is absolutely added by TiKV,TiFlash,TiDB. User should not add engine=xxx
label. It will break the system.
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 thing is it is not a token, but a string. The syntax is like ALTER TABLE ALTER PARTITION ADD PLACEMENT POLICY ... CONSTRIANTS="+zone=bj,..." ...
. I've proposed to parse the string by parser, but rejected by djshow832. It indeed makes the work easier, because this string may contain comma.
Here we use this string a "pattern matcher", which will match constraints added by user, or the software itself. PD and TiDB both have a matcher: TiDB will match on the constraints cache, PD will match on the persisted constraints.
So, there are other two concerns:
zone,bj
kv pair is added by a user. But possibly not by a SQL of TiDB, e.g. tidb-operator could add such label. They won't normalize the label.- PD match case sensitively. It is also strange that TiDB is insensitive, but PD is sensitive.
For TiFlash
, it is just, I don't know, if the value is always TiFlash
. I mean, there is no spec for that. And this label is absolutely added by TiKV,TiFlash,TiDB. User should not add engine=xxx
label. It will break the system.
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.
OK. It seems complicated enough maybe we can't solve it in this PR. LGTM.
/LGTM |
Able to review, but merge depends on #24004 |
/unhold |
Signed-off-by: xhe <xw897002528@gmail.com>
Signed-off-by: xhe <xw897002528@gmail.com>
Rebased to the master, because the first PR is merged. |
ddl/placement/constraint.go
Outdated
func (c *Constraint) String() string { | ||
str, err := c.Restore() | ||
if err != nil { | ||
return err.Error() |
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 String()
returning error message seems to be strange...
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.
Does panic feel better?
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.
How about log it and return empty(""
)?
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 is too silent... The only way to construct invalid constraint is by manual construction, bypassing the new method and all other checks. So far, only tests and json.Unmarshal
does not use the new method(after the merge of all refactor PRs). Unmarshal
takes data from the data persisted on PD, which are constructed through SQL and the new method. So it is safe, too.
User just should not go here. And devs should not rely on manual manipulation if there is a set of working public APIs.
EDIT: It seems taht only tests are using String()
for debugging purpose.
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.
If it is not used in the normal case, we should not provide it. 🤔
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.
But to use json.Marshal
convert the struct to string, there must be one stringer implementation.
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.
Ok... Anyway, Golang cannot prohibit the developers from initializing a struct with manual construction. Panic can be dangerous in a production environment. I still prefer logging it and return an empty string:)
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 can prevent that by wrapping another internal package and private fields... Manual construction will be blocked unless you are in the placement package. E.g.:
import "mypackage/internal"
type MyStruct struct {
internalFields internal.MyRealStruct
}
But that seems an overkill for me. It also changes the structure of json. So it can not be marshaled easily.
Anyway, Golang cannot prohibit the developers from initializing a struct with manual construction.
In fact, one of my point for refactor is to prevent developers from manual/raw operations. I hope they can follow the contract before going deep into the package.
Panic can be dangerous in a production environment
The upper service should recover()
the error, if there is a 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.
Anyway, I removed the stringer interface.
Co-authored-by: tangenta <tangenta@126.com>
Signed-off-by: xhe <xw897002528@gmail.com>
Signed-off-by: xhe <xw897002528@gmail.com>
/lgtm |
[REVIEW NOTIFICATION] This pull request has been approved by:
To complete the pull request process, please ask the reviewers in the list to review by filling The full list of commands accepted by this bot can be found here. Reviewer can indicate their review by writing |
/merge |
This pull request has been accepted and is ready to merge. Commit hash: 3c8921f
|
@xhebox: Your PR was out of date, I have automatically updated it for you. At the same time I will also trigger all tests for you: /run-all-tests If the CI test fails, you just re-trigger the test that failed and the bot will merge the PR for you after the CI passes. Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the ti-community-infra/tichi repository. |
What problem does this PR solve?
Problem Summary: Separate from #22415, 2/6 patch from the large PR.
Able to review, but merge depends on #24004
LabelConstraint
is renamed toConstraint
.checkLabelConstraint
toNewConstraint
CompatibleWith
, which is used to detect invalid combination of constraint. It is not used in the PR, but in the next PR.Constraint
things toconstraint.go
, and a full cover test incontraint_test.go
.Check List
Tests
Release note