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

[Issue 513] Correct apparent logic error in batchContainer's hasSpace() method #678

Merged
merged 7 commits into from
Dec 22, 2021

Conversation

bschofield
Copy link
Contributor

@bschofield bschofield commented Dec 2, 2021

Fixes issue #513.

This issue was previously partially addressed by @zzzming in PR #528.

Motivation

Following PR #528, the logic for the hasSpace() function, which is used to determine whether a batch container has enough space for a new message, reads:

func (bc *keyBasedBatchContainer) hasSpace(payload []byte) bool {
	msgSize := uint32(len(payload))
	return bc.numMessages+1 < bc.maxMessages || (bc.buffer.ReadableBytes()+msgSize) < uint32(bc.maxBatchSize)
}

Currently, then, the batch container will be considered to have space (be non-full) until both the max-messages and the max-size limits are hit.

I think that is incorrect. Nearby in the code, the batch container is considered to be full if either of the conditions are hit:

// IsFull check if the size in the current batch exceeds the maximum size allowed by the batch
func (bc *batchContainer) IsFull() bool {
	return bc.numMessages >= bc.maxMessages || bc.buffer.ReadableBytes() > uint32(bc.maxBatchSize)
}

Because the logical rule is !(A || B) = (!A) && (!B), the || in hasSpace() should be an &&.

Modifications

Change the || in hasSpace() to an &&, so that the container will be considered full if either limit is hit.

Verifying this change

This change is a trivial rework / code cleanup without any test coverage.

Added TestMaxBatchSize().

Documentation

  • Does this pull request introduce a new feature? no

@bschofield
Copy link
Contributor Author

The tests now seem to be failing on TestNacksTracker(). Is that a consequence of this change, or an unrelated issue?

@cckellogg
Copy link
Contributor

cckellogg commented Dec 2, 2021

The tests now seem to be failing on TestNacksTracker(). Is that a consequence of this change, or an unrelated issue?

It's probably unrelated since the tests passed for the other go versions. The concerning part is there may be a flaky TestNacksTracker() test now?

I started a retest

@bschofield
Copy link
Contributor Author

bschofield commented Dec 3, 2021

The concerning part is there may be a flaky TestNacksTracker() test now?

I would guess that it's probably this part of newNackMockedConsumer():

// since the client ticks at an interval of delay / 3
// wait another interval to ensure we get all messages
time.Sleep(testNackDelay + 101*time.Millisecond)

Since the sleep above happens inside a new goroutine, and (*negativeAcksTracker).track() also runs inside a new goroutine, it's probably possible in rare cases for the goroutine scheduling to interfere with the intended sequence of actions. Also the documentation says that time.Ticker is allowed to drop ticks, which I suppose could be happening.

@bschofield
Copy link
Contributor Author

bschofield commented Dec 3, 2021

I added TestMaxBatchSize() to producer_test.go, based on TestMaxMessageSize().

From the results of that test, it looks like the < in the size test should actually be <=, to accommodate the case where the new payload fits exactly in the container.

@bschofield bschofield changed the title Correct apparent logic error in batchContainer's hasSpace() method [Issue 513] Correct apparent logic error in batchContainer's hasSpace() method Dec 7, 2021
@zzzming
Copy link
Contributor

zzzming commented Dec 10, 2021

We should use this

bc.numMessages+1 <= bc.maxMessages 

Because this will accommodate an individual message when batch is disabled. Currently this configuration fails at [unable to add message to batch]

pulsar.ProducerOptions{
		Topic:               topicName,
		DisableBatching:     true,
		BatchingMaxMessages: 1,
		BatchingMaxSize:     1,
	})

@bschofield
Copy link
Contributor Author

Made the additional tweak as suggested by @zzzming, also cleaned up IsFull() (which is not actually used anywhere as far as I can see).

Copy link
Member

@wolfstudy wolfstudy left a comment

Choose a reason for hiding this comment

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

LGTM +1

@wolfstudy wolfstudy merged commit 2bbfb8e into apache:master Dec 22, 2021
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.

None yet

4 participants