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

importccl: refactor out all business logic from the processor #41909

Merged
merged 1 commit into from
Oct 24, 2019

Conversation

spaskob
Copy link
Contributor

@spaskob spaskob commented Oct 24, 2019

This helps in being able to run an import standalone and makes it clear
that the distSql processor is only used for propagating error and status
messages to the controller.

Release note: none.

@spaskob spaskob requested review from dt and miretskiy October 24, 2019 18:00
@cockroach-teamcity
Copy link
Member

This change is Reviewable

Copy link
Contributor

@miretskiy miretskiy left a comment

Choose a reason for hiding this comment

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

Reviewable status: :shipit: complete! 0 of 0 LGTMs obtained (waiting on @dt, @miretskiy, and @spaskob)


pkg/ccl/importccl/import_processor.go, line 77 at r1 (raw file):

	// We don't have to worry about this go routine leaking because next we loop over progCh
	// which is closed only after the go routine returns.

I kinda think that "leaking" is a strong word... Did you mean that runImport() terminates early if the passed in context is cancelled, and so we don't need to use group.GoCtx for the cancellation propagation?


pkg/ccl/importccl/import_processor.go, line 102 at r1 (raw file):

Quoted 8 lines of code…
	if err != nil {
		cp.output.Push(nil, &execinfrapb.ProducerMetadata{Err: err})
		return
	}
	cp.output.Push(sqlbase.EncDatumRow{
		sqlbase.DatumToEncDatum(types.Bytes, tree.NewDBytes(tree.DBytes(countsBytes))),
		sqlbase.DatumToEncDatum(types.Bytes, tree.NewDBytes(tree.DBytes([]byte{}))),
	}, nil)

Not sure which one is more canonical go:
if countBytes, err := marhsal(); err == nil {
// send result
} else {
// send error.
}

This helps in being able to run an import standalone and makes it clear
that the distSql processor is only used for propagating error and status
messages to the controller.

Release note: none.
Copy link
Member

@dt dt left a comment

Choose a reason for hiding this comment

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

Reviewable status: :shipit: complete! 0 of 0 LGTMs obtained (waiting on @dt and @miretskiy)


pkg/ccl/importccl/import_processor.go, line 77 at r1 (raw file):

Previously, miretskiy (Yevgeniy Miretskiy) wrote…
	// We don't have to worry about this go routine leaking because next we loop over progCh
	// which is closed only after the go routine returns.

I kinda think that "leaking" is a strong word... Did you mean that runImport() terminates early if the passed in context is cancelled, and so we don't need to use group.GoCtx for the cancellation propagation?

"leaking a go routine" is a common problem where the function that started a goroutine returns while the goroutine it started is still running, and nothing is responsible for making sure that goroutine actually exists.

Using group.Go is one way we avoid this (since group.Wait() will block until they all exit) and using our bespoke stopper is another, and a naked go is often treated as suspect given how easy it is to get wrong. However, in-person, Spas and I looked at this particular callsite and decided there was no need for the one-goroutine-group, since it was clear the range would block the creating function until the defer fired, and the ctx closed over would cancel at exactly the same time either way, so in this case, it was clearer this way (but with a comment for those who have acquired the fear of the naked keyword).


pkg/ccl/importccl/import_processor.go, line 102 at r1 (raw file):

Previously, miretskiy (Yevgeniy Miretskiy) wrote…
	if err != nil {
		cp.output.Push(nil, &execinfrapb.ProducerMetadata{Err: err})
		return
	}
	cp.output.Push(sqlbase.EncDatumRow{
		sqlbase.DatumToEncDatum(types.Bytes, tree.NewDBytes(tree.DBytes(countsBytes))),
		sqlbase.DatumToEncDatum(types.Bytes, tree.NewDBytes(tree.DBytes([]byte{}))),
	}, nil)

Not sure which one is more canonical go:
if countBytes, err := marhsal(); err == nil {
// send result
} else {
// send error.
}

no, err != nil immediately after the error-returning call is the norm.

If you try to put the nil case in the else so you can use the if-scoped values (countBytes here), our linter will in fact tell you not to (since the first block has an early return) and instead do it the way it is in this diff now: binding the value and err outside the if, doing the err conditional early return, then using the bound result back at the original scope.

You can do it the way you wrote, putting the non-nil err in the else instead, if you really want to use the if binding to limit the scope of the countBytes, but that is not the norm, and runs a serious risk of people accustomed to the err != nil convention missing the subtle difference. (FWIW, I wish that linter didn't exist, and have been known to try your way, but have come around to ahearing to the convention instead)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants