-
Notifications
You must be signed in to change notification settings - Fork 685
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
Wip/wan tx grouping module 1 #7083
base: develop
Are you sure you want to change the base?
Conversation
1407b2a
to
214dc76
Compare
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.
Inlined a few comments. Overall looks like a good direction! Here are some general comments and tips:
- Prefer interfaces over abstract methods.
- Standardize on one library instead of mixing them (such as AssertJ for assertions).
- Is there a better word than "txgrouping" for module name and packages?
- Declare variables and APIs with interfaces rather than implementations.
- Always look for an interface to use instead of an implementation (such as InternalCache instead of GemFireCacheImpl) in both tests and product code.
- Always minimize the scope of anything (class, method, variable, constant).
import static org.assertj.core.api.Assertions.assertThat; | ||
import static org.junit.Assert.assertEquals; | ||
import static org.junit.Assert.assertNotNull; |
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.
Please use AssertJ for all assertions. The assertEquals
can just use assertThat(a).isEqualTo(b)
and assertNotNull
becomes assertThat(a).isNotNull();
|
||
protected Properties createLocatorConfig(int systemId, int locatorPort, int remoteLocatorPort) { | ||
Properties config = new Properties(); | ||
config.setProperty(MCAST_PORT, "0"); |
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.
This is the default so you can delete the line with MCAST_PORT
if (regionSize != r.keySet().size()) { | ||
await().untilAsserted(() -> assertThat(r.keySet().size()).isEqualTo(regionSize)); | ||
} |
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 would delete the if-statement and just use the await. The if statement is redundant... the await will also immediately complete successfully if the if-statement is true.
await() | ||
.untilAsserted(() -> assertThat(regionQueue.size()).isEqualTo(expectedQueueSize)); | ||
} | ||
ArrayList<Integer> stats = new ArrayList<>(); |
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.
Remember to declare as the weakest interface you need:
List<Integer> stats = new ArrayList<>();
assertThat(creates).isEqualTo(gatewayReceiverStats.getCreateRequest()); | ||
} | ||
|
||
protected void doTxPutsWithRetryIfError(String regionName, final long putsPerTransaction, |
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 you should try to simplify any new method with this many calculations, for-loops, do-whiles and try-blocks. If you really need all of those blocks then try extracting the nested blocks to their own short little methods.
try { | ||
for (AsyncInvocation<?> asyncInvocation : asyncInvocations) { | ||
asyncInvocation.await(); | ||
} | ||
} catch (InterruptedException e) { | ||
fail("Interrupted"); | ||
} |
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.
Don't catch an exception and use fail
. Instead just add throws InterruptedException
to the test and delete the try-catch lines.
} finally { | ||
exp.remove(); | ||
exp1.remove(); | ||
} |
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.
IgnoredException
implements AutoCloseable
so you can use it in try-with-resources syntax. Using import-static and addIgnoredException(Class)
tidies it up nicely:
import static org.apache.geode.test.dunit.IgnoredException.addIgnoredException;
try (IgnoredException ie1 = addIgnoredException(RegionDestroyedException.class);
IgnoredException ie2 = addIgnoredException(ForceReattemptException.class)) {
// ...
}
+ statistics.getUnprocessedEventsRemovedByPrimary())).isEqualTo(eventsReceived); | ||
} | ||
|
||
private Boolean killPrimarySender(String senderId) { |
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 dunit testing framework originally required primitive wrappers, so I think you may have copied some of this from elsewhere. It's better to just use simple primitives for return types and parameters now, such as boolean
instead of Boolean
.
import org.apache.geode.internal.cache.wan.GatewaySenderException; | ||
import org.apache.geode.internal.cache.wan.MutableGatewaySenderAttributes; | ||
|
||
public abstract class CommonTxGroupingGatewaySenderFactory { |
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 you should make this an interface instead of an abstract class. The static
validator method would then become a default
implementation which would probably only ever be overridden by a test.
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.
What would be the benefit of using an interface over an abstract class here?
Given that it provides helper static methods I tend to think it is better to define it is a class but I have no strong argument in favor of it.
while (true) { | ||
for (Iterator<Map.Entry<TransactionId, Integer>> iter = | ||
incompleteTransactionIdsInBatch.entrySet().iterator(); iter.hasNext();) { | ||
Map.Entry<TransactionId, Integer> pendingTransaction = iter.next(); | ||
TransactionId transactionId = pendingTransaction.getKey(); | ||
int bucketId = pendingTransaction.getValue(); | ||
List<Object> events = | ||
peekEventsWithTransactionId(partitionedRegion, bucketId, transactionId); | ||
for (Object object : events) { |
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.
Try to extract any nested loops to their own smaller methods. It helps keep things better organized and more readable.
} | ||
|
||
@Override | ||
public synchronized void remove() throws CacheException { |
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.
At first glance it looks like a lot of the remove method content is reimplemented here. Is there a way break up the original with some extension points to deduce the duplication?
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.
See Nordix#17
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.
Nice!
@@ -256,7 +257,13 @@ public GatewaySenderFactory setEnforceThreadsConnectSameReceiver( | |||
|
|||
static void validate(final @NotNull InternalCache cache, | |||
final @NotNull GatewaySenderAttributesImpl attributes) { | |||
final int myDSId = cache.getDistributionManager().getDistributedSystemId(); | |||
int myDSId; | |||
if (cache instanceof CacheCreation) { |
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.
Maybe CacheCreation
should be fixed to behave like any other InternalCache
rather than making consumer know subtile differences in behavior.
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.
You mean to implement in CacheCreation
the getDistributionManager()
method as follows?
@Override
public DistributionManager getDistributionManager() {
return InternalDistributedSystem.getAnyInstance().getDistributionManager()
}
addIgnoredException("could not get remote locator"); | ||
|
||
String createCommandString = | ||
"create gateway-sender --id=sender1 --remote-distributed-system-id=1 --parallel --group-transaction-events=true"; |
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.
This doesn't seem modular yet. Is this testing deprecated --group-transaction-events
and work is pending to add at --type=TxGroupingParallelGatewaySender
?
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.
You can find an example of modularizing this in the first POC. Follow the new type
property on the create gateway-sender
command.
https://github.com/pivotal-jbarrett/geode/blob/wip/wan-spi/geode-gfsh/src/main/java/org/apache/geode/management/internal/cli/commands/CreateGatewaySenderCommand.java#L83
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.
Done. We'll have to see how we reflect this in the documentation as we will need documentation specific for the module.
@albertogpz Can you please rebase this from develop. There as a fixed added there to address issues with Gradle builds. |
@albertogpz we need to extract out the TX batching specific elements form the |
Thanks for your comments. |
1850646
to
ee9b459
Compare
@pivotal-jbarrett As I said in a previous e-mail, I do not think we can make these changes without breaking backward compatibility. The feature was production ready at 1.14 so we can expect that it is used by customers. Therefore, we cannot just ignore those changes when interworking with 1.14 servers. |
f238c66
to
d6d80b2
Compare
520d955
to
1ac52a6
Compare
this PR appears to be abandoned, can it be closed? |
1ac52a6
to
dd7f827
Compare
It is not abandoned. Still waiting for comments after review changes. I have rebased the branch to remove the conflicts with develop. |
7a03267
to
13ea059
Compare
13ea059
to
4ce6664
Compare
For all changes:
Is there a JIRA ticket associated with this PR? Is it referenced in the commit message?
Has your PR been rebased against the latest commit within the target branch (typically
develop
)?Is your initial contribution a single, squashed commit?
Does
gradlew build
run cleanly?Have you written or updated unit tests to verify your changes?
If adding new dependencies to the code, are these dependencies licensed in a way that is compatible for inclusion under ASF 2.0?