Skip to content

MINOR: consolidate processor context for active/standby#8669

Merged
guozhangwang merged 15 commits intoapache:trunkfrom
ableegoldman:MINOR-consolidate-ProcessorContext-impls
May 18, 2020
Merged

MINOR: consolidate processor context for active/standby#8669
guozhangwang merged 15 commits intoapache:trunkfrom
ableegoldman:MINOR-consolidate-ProcessorContext-impls

Conversation

@ableegoldman
Copy link
Copy Markdown
Member

This is a prerequisite for KAFKA-9501 and will also be useful for KAFKA-9603

There should be no logical changes here: the main difference is the removal of StandbyContextImpl in preparation for contexts to transition between active and standby.

Also includes some minor cleanup, eg pulling the ReadOnly/ReadWrite decorators out into a separate file.

@ableegoldman
Copy link
Copy Markdown
Member Author

Call for review @cadonna @guozhangwang @vvcephei

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I felt these were just cluttering up this class so I moved them to a new file

@ableegoldman ableegoldman force-pushed the MINOR-consolidate-ProcessorContext-impls branch from 62d7079 to 751e8e8 Compare May 15, 2020 00:08
@ableegoldman ableegoldman force-pushed the MINOR-consolidate-ProcessorContext-impls branch from 751e8e8 to 2a506c4 Compare May 15, 2020 00:09
import org.apache.kafka.streams.state.WindowStoreIterator;
import org.apache.kafka.streams.state.internals.WrappedStateStore;

abstract class AbstractReadOnlyDecorator<T extends StateStore, K, V> extends WrappedStateStore<T, K, V> {
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

All of this (and the other new class below) was just copied over from ProcessorContextImpl. I changed the named to AbstractXXXDecorator since it's an abstract class but it's all otherwise unchanged

}

/**
* @throws UnsupportedOperationException if the current task type is standby
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

No logical changes here, just added a check for any methods that were previously overridden in the standby context to throw UnsupportedOperation

logChange(key, value, context.timestamp());
}

void logChange(final K key,
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

This class was the root cause of the processor context issue blocking the active <--> standby task conversion. I was taking pieces out of it bit by bit and by the end it seemed pointless to have at all

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

SGTM.

void log(final Bytes key,
final byte[] value) {
changeLogger.logChange(key, value);
context.logChange(name(), key, value, context.timestamp());
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

We now just delegate to the context to figure out how/what to log

Copy link
Copy Markdown
Contributor

@vvcephei vvcephei left a comment

Choose a reason for hiding this comment

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

Thanks for this, @ableegoldman !

I had a few comments; once they're addressed, I'll be +1 to merge this.

Thanks,
-John

Comment on lines +234 to +237
@Override
public TaskType taskType() {
return stateManager.taskType();
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looks like this doesn't need to be defaulted here. If the logic doesn't apply to all the implementing classes, it's better not to define it in the abstract class.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Ah, actually it does. I should remove the override from the ProcessorContextImpl instead

Comment on lines +31 to +33
BytesSerializer BYTES_KEY_SERIALIZER = new BytesSerializer();
ByteArraySerializer BYTE_ARRAY_VALUE_SERIALIZER = new ByteArraySerializer();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

It doesn't seem like these need to be defined here, since they're only used outside of this interface.

They actually only have two, independent, usages, and it doesn't seem that important to de-duplicate the instances. Can we just copy them to separate constants in the classes that need them?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Yeah, this was part of a larger refactoring that I walked back. That sounds like a reasonable request 👍

EasyMock.reset(context);
EasyMock.expect(context.timestamp()).andStubReturn(0L);
context.logChange(store.name(), key1, value, 0L);
context.logChange(store.name(), key2, value, 0L);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

We don't need expectLastCall() on these (and everywhere else)?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

The expectLastCall is redundant if you're not chaining it with something else (like expectLastCall().times(2))

I verified this just to be sure by removing the invocation of context.logChange in this class and it did indeed fail

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Ok, thanks!

Comment thread streams/src/test/java/org/apache/kafka/test/MockInternalProcessorContext.java Outdated
private final List<CapturedForward> capturedForwards = new LinkedList<>();
private boolean committed = false;


Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Not sure about this change ;)

@vvcephei
Copy link
Copy Markdown
Contributor

test this please

@vvcephei
Copy link
Copy Markdown
Contributor

Test this please

1 similar comment
@vvcephei
Copy link
Copy Markdown
Contributor

Test this please

@ableegoldman
Copy link
Copy Markdown
Member Author

All builds failed due to some mysterious

11:59:42 FATAL: command execution failed
11:59:42 java.io.EOFException
11:59:42 	at java.io.ObjectInputStream$PeekInputStream.readFully(ObjectInputStream.java:2681)
11:59:42 	at java.io.ObjectInputStream$BlockDataInputStream.readShort(ObjectInputStream.java:3156)
11:59:42 	at java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:862)
11:59:42 	at java.io.ObjectInputStream.<init>(ObjectInputStream.java:358)
11:59:42 	at hudson.remoting.ObjectInputStreamEx.<init>(ObjectInputStreamEx.java:49)
11:59:42 	at hudson.remoting.Command.readFrom(Command.java:140)
11:59:42 	at hudson.remoting.Command.readFrom(Command.java:126)
11:59:42 	at hudson.remoting.AbstractSynchronousByteArrayCommandTransport.read(AbstractSynchronousByteArrayCommandTransport.java:36)
11:59:42 	at hudson.remoting.SynchronousCommandTransport$ReaderThread.run(SynchronousCommandTransport.java:63)
11:59:42 Caused: java.io.IOException: Unexpected termination of the channel

@guozhangwang
Copy link
Copy Markdown
Contributor

test this please

@ableegoldman
Copy link
Copy Markdown
Member Author

All builds failed on 14:16:00 ERROR: Error cloning remote repo 'origin' 😕

@guozhangwang
Copy link
Copy Markdown
Contributor

test this please

Copy link
Copy Markdown
Contributor

@guozhangwang guozhangwang left a comment

Choose a reason for hiding this comment

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

LGTM overall. I'd like to also ping @cadonna since he's reviewing another large PR that merges MockInternal- and InternalMock- ProcessorContext which would have some conflicts with this one.

final Bytes key,
final byte[] value,
final long timestamp) {
recordCollector().send(
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

When we merge the InternalMock with MockInternal would this be okay? cc @cadonna

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I assumed this would be fine since it's pretty much what happened before (ie users of the context would get the record collector and then call send) but I'd like to get this confirmed

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Both, MockInternalProcessorContext and InternalMockProcessorContext currently implement RecordCollector.Supplier (i.e., recordCollector()). Of course, once rebased the consolidated mock needs to implement taskType() and logChange().
See also my comment above regarding KEY_SERIALIZER and VALUE_SERIALIZER.
@guozhangwang did you have anything specific in mind that I did not cover here?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

No I do not, just wanting to make sure we do not have any major conflicts when rebasing the other.

logChange(key, value, context.timestamp());
}

void logChange(final K key,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

SGTM.

Copy link
Copy Markdown
Member

@cadonna cadonna left a comment

Choose a reason for hiding this comment

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

@ableegoldman Thank you for this! I am looking forward to use this in the fix for KAFKA-9603.

Here my feedback.

final Bytes key,
final byte[] value,
final long timestamp) {
throwUnsupportedOperationExceptionIfStandby("logChange");
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

req: Please unit test a processor context for a standby with the unsupported methods. That is, all code paths that involve a call to throwUnsupportedOperationExceptionIfStandby().

Comment on lines +57 to +58
import static org.apache.kafka.streams.processor.internals.ProcessorContextImpl.KEY_SERIALIZER;
import static org.apache.kafka.streams.processor.internals.ProcessorContextImpl.VALUE_SERIALIZER;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

prop: I think we should move those to InternalProcessorContext. IMO, it would be cleaner for a mock not to have a direct dependency to the class it mocks. The new consolidated mock for the internal processor context will not extend AbstractProcessorContext but only MockProcessorContext. Thus, the common ancestor will be InternalProcessorContext.
Sorry for bothering you because of those constants after that @vvcephei has already bothered you. :-)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Ack

final Bytes key,
final byte[] value,
final long timestamp) {
recordCollector().send(
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Both, MockInternalProcessorContext and InternalMockProcessorContext currently implement RecordCollector.Supplier (i.e., recordCollector()). Of course, once rebased the consolidated mock needs to implement taskType() and logChange().
See also my comment above regarding KEY_SERIALIZER and VALUE_SERIALIZER.
@guozhangwang did you have anything specific in mind that I did not cover here?

@guozhangwang
Copy link
Copy Markdown
Contributor

test this please

@guozhangwang
Copy link
Copy Markdown
Contributor

LGTM. Will merge after green builds.

@guozhangwang
Copy link
Copy Markdown
Contributor

test this please

1 similar comment
@guozhangwang
Copy link
Copy Markdown
Contributor

test this please

@ableegoldman
Copy link
Copy Markdown
Member Author

Failed due to flaky EosBetaUpgradeIntegrationTest.shouldUpgradeFromEosAlphaToEosBeta and ConnectorTopicsIntegrationTest.testGetActiveTopics

@guozhangwang guozhangwang merged commit 392e49b into apache:trunk May 18, 2020
@ableegoldman ableegoldman deleted the MINOR-consolidate-ProcessorContext-impls branch May 18, 2020 23:30
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