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

ddl: refactor constraint [2/6] #24005

Merged
merged 8 commits into from
Apr 16, 2021
Merged

ddl: refactor constraint [2/6] #24005

merged 8 commits into from
Apr 16, 2021

Conversation

xhebox
Copy link
Contributor

@xhebox xhebox commented Apr 14, 2021

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

  1. LabelConstraint is renamed to Constraint.
  2. checkLabelConstraint to NewConstraint
  3. added CompatibleWith, which is used to detect invalid combination of constraint. It is not used in the PR, but in the next PR.
  4. Move all Constraint things to constraint.go, and a full cover test in contraint_test.go.

Check List

Tests

  • Unit test
  • Integration test

Release note

  • No release note

@xhebox xhebox requested a review from a team as a code owner April 14, 2021 06:16
@xhebox xhebox requested review from wshwsh12 and removed request for a team April 14, 2021 06:16
@ti-chi-bot ti-chi-bot added the size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. label Apr 14, 2021
@xhebox xhebox changed the title ddl: refactor constraint ddl: refactor constraint [2/6] Apr 14, 2021
@xhebox xhebox requested a review from a team April 14, 2021 07:28
Copy link
Contributor

@morgo morgo left a 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.

ddl/placement/constraint_test.go Outdated Show resolved Hide resolved
Comment on lines +53 to +59
name: "not tiflash",
input: "-engine = tiflash ",
label: Constraint{
Key: "engine",
Op: NotIn,
Values: []string{"tiflash"},
},
Copy link
Contributor

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.)

Copy link
Contributor Author

@xhebox xhebox Apr 14, 2021

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).

Copy link
Contributor

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",

Copy link
Contributor Author

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:

  1. 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.
  2. 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.

Copy link
Contributor Author

@xhebox xhebox Apr 15, 2021

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:

  1. 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.
  2. 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.

Copy link
Contributor

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.

go.sum Outdated Show resolved Hide resolved
@morgo
Copy link
Contributor

morgo commented Apr 15, 2021

/LGTM

@ti-chi-bot ti-chi-bot added the status/LGT1 Indicates that a PR has LGTM 1. label Apr 15, 2021
@xhebox
Copy link
Contributor Author

xhebox commented Apr 15, 2021

Able to review, but merge depends on #24004
/hold

@ti-chi-bot ti-chi-bot added the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label Apr 15, 2021
@xhebox
Copy link
Contributor Author

xhebox commented Apr 16, 2021

/unhold

@ti-chi-bot ti-chi-bot removed the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label Apr 16, 2021
xhebox and others added 4 commits April 16, 2021 13:23
Signed-off-by: xhe <xw897002528@gmail.com>
Co-authored-by: Morgan Tocker <tocker@gmail.com>
Signed-off-by: xhe <xw897002528@gmail.com>
Signed-off-by: xhe <xw897002528@gmail.com>
@xhebox
Copy link
Contributor Author

xhebox commented Apr 16, 2021

Rebased to the master, because the first PR is merged.

ddl/placement/constraint.go Outdated Show resolved Hide resolved
ddl/placement/constraint_test.go Outdated Show resolved Hide resolved
func (c *Constraint) String() string {
str, err := c.Restore()
if err != nil {
return err.Error()
Copy link
Contributor

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...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Does panic feel better?

Copy link
Contributor

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("")?

Copy link
Contributor Author

@xhebox xhebox Apr 16, 2021

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.

Copy link
Contributor

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. 🤔

Copy link
Contributor Author

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.

Copy link
Contributor

@tangenta tangenta Apr 16, 2021

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:)

Copy link
Contributor Author

@xhebox xhebox Apr 16, 2021

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.

Copy link
Contributor Author

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.

xhebox and others added 3 commits April 16, 2021 18:06
Co-authored-by: tangenta <tangenta@126.com>
Signed-off-by: xhe <xw897002528@gmail.com>
Signed-off-by: xhe <xw897002528@gmail.com>
@tangenta
Copy link
Contributor

/lgtm

@ti-chi-bot
Copy link
Member

[REVIEW NOTIFICATION]

This pull request has been approved by:

  • morgo
  • tangenta

To complete the pull request process, please ask the reviewers in the list to review by filling /cc @reviewer in the comment.
After your PR has acquired the required number of LGTMs, you can assign this pull request to the committer in the list by filling /assign @committer in the comment to help you merge this pull request.

The full list of commands accepted by this bot can be found here.

Reviewer can indicate their review by writing /lgtm in a comment.
Reviewer can cancel approval by writing /lgtm cancel in a comment.

@ti-chi-bot ti-chi-bot added status/LGT2 Indicates that a PR has LGTM 2. and removed status/LGT1 Indicates that a PR has LGTM 1. labels Apr 16, 2021
@tangenta
Copy link
Contributor

/merge

@ti-chi-bot
Copy link
Member

This pull request has been accepted and is ready to merge.

Commit hash: 3c8921f

@ti-chi-bot ti-chi-bot added the status/can-merge Indicates a PR has been approved by a committer. label Apr 16, 2021
@ti-chi-bot
Copy link
Member

@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.

@ti-chi-bot ti-chi-bot merged commit 3ec3729 into pingcap:master Apr 16, 2021
@xhebox xhebox deleted the master_2 branch April 20, 2021 01:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
component/expression sig/sql-infra SIG: SQL Infra size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. status/can-merge Indicates a PR has been approved by a committer. status/LGT2 Indicates that a PR has LGTM 2.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants