Skip to content

Make field-generation race reproducible with deterministic interleaving test#1233

Draft
Copilot wants to merge 16 commits into
masterfrom
copilot/add-parallel-execution-option
Draft

Make field-generation race reproducible with deterministic interleaving test#1233
Copilot wants to merge 16 commits into
masterfrom
copilot/add-parallel-execution-option

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented May 20, 2026

Field class corruption from concurrent writes to the same output path was hard to reproduce because the existing test was probabilistic and often ended in a valid “last writer wins” file. This PR makes the race reproducible and detectable with deterministic write interleaving.

  • Deterministic race reproduction in codegenerator tests

    • Added a two-task race scenario that writes the same field class from different dictionaries with distinct generated content.
    • Introduced a coordinated test output stream that synchronizes both writers (barrier after open/truncate) and enforces a controlled interleaving pattern.
  • Minimal production seam for test-controlled output

    • Added a protected output-stream factory hook in MessageCodeGenerator so tests can inject controlled writer behavior without changing generation logic.
    • generateCodeFile(...) now delegates stream creation via createOutputStream(File).
  • Stronger corruption assertion

    • The deterministic test compares final output against both valid variants and asserts it is neither, proving mixed/corrupt output rather than normal overwrite behavior.
// MessageCodeGenerator
protected OutputStream createOutputStream(File outputFile) throws FileNotFoundException {
    return new BufferedOutputStream(new FileOutputStream(outputFile));
}

@chrjohn
Copy link
Copy Markdown
Member

chrjohn commented May 20, 2026

@copilot please add logging output how many parallel tasks are used

Copy link
Copy Markdown
Contributor Author

Copilot AI commented May 20, 2026

@copilot please add logging output how many parallel tasks are used

Implemented in commit fde52ce. MessageCodeGenerator.generate(List<Task>) now logs the parallel worker count and total task count when parallel execution is enabled.

Copilot AI requested a review from chrjohn May 20, 2026 18:24
@chrjohn
Copy link
Copy Markdown
Member

chrjohn commented May 21, 2026

@copilot make generator.parallelExecution true by default.

Copy link
Copy Markdown
Contributor Author

Copilot AI commented May 21, 2026

@copilot make generator.parallelExecution true by default.

Done in commit d9804f4. generator.parallelExecution is now true by default for multi-task generation; setting it to false forces sequential execution.

Copilot AI changed the title Enable optional parallel MessageCodeGenerator task execution with thread-safe state and task-scoped logging Enable parallel MessageCodeGenerator task execution by default with thread-safe state and task-scoped logging May 21, 2026
@chrjohn
Copy link
Copy Markdown
Member

chrjohn commented May 21, 2026

@copilot parallel execution might work when calling main() of the code generator. However, it does not work when using the GenerateMojo. So the mojo needs the information for all possible executions for the various fix versions at once. Currently there are several executions in quickfixj-messages/quickfixj-messages-all/pom.xml

Copy link
Copy Markdown
Contributor Author

Copilot AI commented May 21, 2026

@copilot parallel execution might work when calling main() of the code generator. However, it does not work when using the GenerateMojo. So the mojo needs the information for all possible executions f...

Implemented in commit 3703f5f. GenerateMojo now accepts a tasks list and invokes generator.generate(List<Task>), and quickfixj-messages-all/pom.xml was switched from multiple generate executions to one aggregated execution containing all FIX-version tasks so parallel generation is applied across versions. No UI changes in this PR.

Copilot AI changed the title Enable parallel MessageCodeGenerator task execution by default with thread-safe state and task-scoped logging Enable parallel MessageCodeGenerator task execution by default, including GenerateMojo multi-version aggregation, with thread-safe state and task-scoped logging May 21, 2026
@chrjohn
Copy link
Copy Markdown
Member

chrjohn commented May 21, 2026

@copilot looking good so far.

  1. Please add a log entry when processing of one task starts and print the number of the task and the total number of tasks like ... "Started task for FIX44 (x / y)"
  2. and add a log entry when one task finishes and print the number of the task and the total number of tasks like ... "Finished task for FIX44 (x / y)"

Copy link
Copy Markdown
Contributor Author

Copilot AI commented May 21, 2026

@copilot looking good so far.

  1. Please add a log entry when processing of one task starts and print the number of the task and the total number of tasks like ... "Started task for FIX44 (x / y)"
    2....

Implemented in commit 1804050. Added per-task progress logs in MessageCodeGenerator.generate(List<Task>): Started task for <taskName> (x / y) before execution and Finished task for <taskName> (x / y) in a finally block after each task completes (sequential and parallel modes). No UI changes in this PR, so no screenshot applies.

@chrjohn
Copy link
Copy Markdown
Member

chrjohn commented May 21, 2026

@copilot the test ParallelExecutionOptionTest.testParallelExecutionIsEnabledByDefault is flaky. It expects that the tasks always finish in the same order.

Keep the assertions that verify:

  • parallel execution actually happened, and
  • the “parallel task execution enabled” log was emitted.
  • Remove the assertion that requires task-3 to be the last finished task.
  • add a weaker assertion that any finish log for all 4 tasks exists.

@chrjohn
Copy link
Copy Markdown
Member

chrjohn commented May 26, 2026

@copilot
ParallelFieldGenerationRaceTest: increase number of fields to 1000 and increase number of threads.

Copy link
Copy Markdown
Contributor Author

Copilot AI commented May 26, 2026

@copilot
ParallelFieldGenerationRaceTest: increase number of fields to 1000 and increase number of threads.

Implemented in commit 53358c4. ParallelFieldGenerationRaceTest now uses 1000 fields and increases parallel tasks from 8 to 16 to raise thread pressure. No UI changes were made, so no screenshot applies.

@chrjohn
Copy link
Copy Markdown
Member

chrjohn commented May 26, 2026

@copilot
ParallelFieldGenerationRaceTest: increase number of fields to 1000 and increase number of threads.

Implemented in commit 53358c4. ParallelFieldGenerationRaceTest now uses 1000 fields and increases parallel tasks from 8 to 16 to raise thread pressure. No UI changes were made, so no screenshot applies.

@copilot please change MessageCodeGenerator so that number of parallel threads can be optionally specified and use 16 parallel tasks in ParallelFieldGenerationRaceTest

Copy link
Copy Markdown
Contributor Author

Copilot AI commented May 26, 2026

@copilot
ParallelFieldGenerationRaceTest: increase number of fields to 1000 and increase number of threads.

...

Implemented in commit 9c8e038. MessageCodeGenerator now supports optional generator.parallelThreads to configure parallel worker count for multi-task generation, and ParallelFieldGenerationRaceTest explicitly uses 16 parallel threads/tasks via that option. No UI changes were made, so no screenshot applies.

Copilot AI changed the title Enable parallel MessageCodeGenerator task execution by default, including GenerateMojo multi-version aggregation, with thread-safe state and task-scoped logging Enable parallel MessageCodeGenerator task execution by default, including GenerateMojo multi-version aggregation, configurable parallel thread count, with thread-safe state and task-scoped logging May 26, 2026
@chrjohn
Copy link
Copy Markdown
Member

chrjohn commented May 26, 2026

@copilot
Please add -Xdiags:verbose to javac compiler options so that I can see a verbose description of compile errors.

Agent-Logs-Url: https://github.com/quickfix-j/quickfixj/sessions/5e22437f-c919-41cc-bd7b-3e321fd6465e

Co-authored-by: chrjohn <6644028+chrjohn@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented May 26, 2026

@copilot
Please add -Xdiags:verbose to javac compiler options so that I can see a verbose description of compile errors.

Implemented in commit 09795a5. I added -Xdiags:verbose to the parent maven-compiler-plugin configuration (compilerArgs), so javac emits verbose compile diagnostics across modules. No UI changes were made, so no screenshot applies.

Copilot AI changed the title Enable parallel MessageCodeGenerator task execution by default, including GenerateMojo multi-version aggregation, configurable parallel thread count, with thread-safe state and task-scoped logging Enable parallel MessageCodeGenerator task execution by default, including GenerateMojo multi-version aggregation, configurable parallel thread count, with thread-safe state, task-scoped logging, and verbose javac diagnostics May 26, 2026
@chrjohn
Copy link
Copy Markdown
Member

chrjohn commented May 27, 2026

@copilot please change the CI build script so that it parses the output on compilation error and does a simple "cat" on the reported file(s). E.g. the build output is like this:

Error:  COMPILATION ERROR : 
[INFO] -------------------------------------------------------------
Error:  /home/runner/work/quickfixj/quickfixj/quickfixj-messages/quickfixj-messages-all/target/generated-sources/quickfix/field/Rule80A.java:[61,1] class, interface, or enum expected
Error:  /home/runner/work/quickfixj/quickfixj/quickfixj-messages/quickfixj-messages-all/target/generated-sources/quickfix/field/Rule80A.java:[63,4] class, interface, or enum expected

Then do a "cat" on the reported files into the build log.

Copy link
Copy Markdown
Contributor Author

Copilot AI commented May 27, 2026

@copilot please change the CI build script so that it parses the output on compilation error and does a simple "cat" on the reported file(s). E.g. the build output is like this:

...

Implemented in commit d08f2a6. I updated .github/workflows/maven.yml so both Linux/macOS and Windows CI steps capture Maven output, detect COMPILATION ERROR, extract reported *.java:[line,col] file paths, and print (cat/Get-Content) each referenced file into the build log before exiting with the original Maven status.

Copilot AI changed the title Enable parallel MessageCodeGenerator task execution by default, including GenerateMojo multi-version aggregation, configurable parallel thread count, with thread-safe state, task-scoped logging, and verbose javac diagnostics Enable parallel MessageCodeGenerator task execution by default, including GenerateMojo multi-version aggregation, configurable parallel thread count, with thread-safe state, task-scoped logging, verbose javac diagnostics, and CI compile-error source dumps May 27, 2026
Copilot AI changed the title Enable parallel MessageCodeGenerator task execution by default, including GenerateMojo multi-version aggregation, configurable parallel thread count, with thread-safe state, task-scoped logging, verbose javac diagnostics, and CI compile-error source dumps Make field-generation race reproducible with deterministic interleaving test May 29, 2026
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.

2 participants