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

[NOID] Fixes #2283: Utilize KernelTransaction.setStatusDetails() in 4.4 #3383

Open
wants to merge 8 commits into
base: 4.4
Choose a base branch
from

Conversation

vga91
Copy link
Collaborator

@vga91 vga91 commented Dec 22, 2022

Related to #3097 (which fails because created from a fork)

Fixes #2283

Added KernelTransaction.setStatusDetails(..) every 1000 rows.

I don't added @Context public KernelTransaction kernelTx due to #2265 (comment).

I used final KernelTransaction ktx = ((InternalTransaction) tx).kernelTransaction(); instead.

@conker84
Copy link
Contributor

@AzuObs can you please take a look on it?

@AzuObs
Copy link
Contributor

AzuObs commented Jan 20, 2023

Hello 👋

I'm very sorry that I've not been quick to review this. It's definitely on my TO DO list. The main reason is that I've been fairly strict about prioritising security issues reported to us privately, and about the triggers work.

I will try to review this soon, but please let me know if it's urgent in any way and I will review sooner.

Copy link
Contributor

@AzuObs AzuObs left a comment

Choose a reason for hiding this comment

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

Generally speaking I think the approach should work, and should add value to the lives of our users. So, kudos on the great start 😁

As usual I cannot let you get away scot-free. I left a few small nitpicks.

checkStatusDetails(db, query, params, null);
}
public static void checkStatusDetails(GraphDatabaseService db, String query, Map<String, Object> params, String startQuery) {
String finalStartQuery = startQuery == null ? query : startQuery;
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this meant to be String final startQuery = ...?

String finalStartQuery = startQuery == null ? query : startQuery;

ExecutorService executor = Executors.newSingleThreadExecutor();
final Future<String> future = executor.submit(() -> db.executeTransactionally(query, params, Result::resultAsString));
Copy link
Contributor

Choose a reason for hiding this comment

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

I think the problem you will find here is that these tests will be flaky. Because the query starts executing right away, and could complete before the assertEventually on the next line begins, which means the assertEventually waits for something which never happens.

At least I believe that's how it works, but I'd be happy to be proven wrong.

What might be worth exploring is kicking off the assertEventually before we execute the query. If you'd like to explore this, then I think it might require some further thinking because currently assertEventually is blocking whereas we'd like the query to overlap.

final Future<String> future = executor.submit(() -> db.executeTransactionally(query, params, Result::resultAsString));

assertEventually(() -> TestUtil.<String>singleResultFirstColumn(db,
"SHOW TRANSACTIONS YIELD statusDetails, currentQuery where currentQuery STARTS WITH $startQuery RETURN statusDetails",
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
"SHOW TRANSACTIONS YIELD statusDetails, currentQuery where currentQuery STARTS WITH $startQuery RETURN statusDetails",
"SHOW TRANSACTIONS YIELD statusDetails, currentQuery WHERE currentQuery STARTS WITH $startQuery RETURN statusDetails",

assertEventually(() -> TestUtil.<String>singleResultFirstColumn(db,
"SHOW TRANSACTIONS YIELD statusDetails, currentQuery where currentQuery STARTS WITH $startQuery RETURN statusDetails",
Map.of("startQuery", finalStartQuery)),
StringUtils::isNotEmpty,
Copy link
Contributor

Choose a reason for hiding this comment

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

StringUtils::isNotEmpty only checks that there is a statusDetails which is not empty. Would it be worth adding a more meaningful check?

@@ -25,6 +25,13 @@
* @since 23.02.16
*/
public class FormatUtils {

public static <T> String asListed(Map<String, T> map) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
public static <T> String asListed(Map<String, T> map) {
public static <T> String asHyphenSeparatedList(Map<String, T> map) {

"asList" would also be fine if you prefer that 👍 "asListed" is however a bit ambiguous because it can also mean "as advertised".

Comment on lines 30 to 33
return map.entrySet()
.stream()
.map(e -> "- " + e.getKey() + ": " + e.getValue())
.collect(Collectors.joining("\n"));
Copy link
Contributor

Choose a reason for hiding this comment

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

We could consider making this into a comma separated list as that is slightly more standard. Completely up to you, though.

acceptBatch();
}

public void updateStatus(boolean updateCurrent) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
public void updateStatus(boolean updateCurrent) {
private void updateStatus(boolean updateCurrent) {

Comment on lines 128 to 133
public void updateStatus(boolean updateCurrent) {
final Map<String, Object> statusMap = JsonUtil.convertToMap(this.progressInfo);
if (updateCurrent) {
setKernelStatusMap(tx, true, statusMap);
}
setKernelStatusMap(tx, progressInfo.nodes + progressInfo.relationships + progressInfo.properties, statusMap);
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this function is a little bit confusing, because it's not obvious at first why we have an if statement on L131 if we end up always calling setKernelStatus on L133.

I would instead recommend creating two separate functions:

  • updateStatus
  • updateStatusPeriodically

Then, from the "update" function we can call updateStatus. And from the "nextRow" function we can call updateStatusPeriodically.

@@ -245,6 +247,10 @@ private void handleNode(Deque<Map<String, Object>> stack, Node node, boolean sim
}

if (!elementMap.isEmpty()) {
final int counter = stack.size();
final Map<String, Object> statusMap = map("curr. element", counter);
Copy link
Contributor

Choose a reason for hiding this comment

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

Should this map also be "map(records:, counter)" for consistency? Or is an element not the same thing as a record in this context?

@@ -103,6 +104,8 @@ public Stream<RundownResult> commit(@Name("statement") String statement, @Name(v
return 0L;
}
}), commitErrors, failedCommits, 0L);
setKernelStatusMap(tx, true,
Map.of("successes", batches.get() - failedBatches.get(), "errors", failedBatches.get()));
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
Map.of("successes", batches.get() - failedBatches.get(), "errors", failedBatches.get()));
Map.of("committed", batches.get() - failedBatches.get(), "failed", failedBatches.get()));

This seems more in line with our existing documentation https://neo4j.com/docs/apoc/current/overview/apoc.periodic/apoc.periodic.iterate/

Copy link
Contributor

Choose a reason for hiding this comment

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

Same comment for the other instances of this happening in this file.

@AzuObs AzuObs removed their assignment Jun 30, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants