thiagoelg opened a new pull request, #7107:
URL: https://github.com/apache/incubator-kie/pull/7107

   **Thank you for submitting this pull request**
   
   **NOTE!:** Double-check the target branch for this PR.
   The default is `main`.
   
   **Ports** If a forward-port or a backport is needed, paste the forward port 
PR here
   
   * n/a
   
   **Issue**: _(please edit the GitHub Issues link if it exists)_
   
   * https://github.com/apache/incubator-kie/issues/7106
   
   **Referenced Pull Requests**: _(please edit the URLs of referenced pull 
requests if they exist)_
   
   * https://github.com/apache/incubator-kie-kogito-runtimes/pull/3870 (context 
only — see "Relationship to #3870" below)
   
   ---
   
   ## What this fixes
   
   `KogitoBeanProducer` produced the CDI `UnitOfWorkManager` bean by returning 
the JVM-wide static singleton 
`StaticUnitOfWorkManger.staticUnitOfWorkManager()`. That class comes from a 
dependency JAR, so Quarkus loads it with the base runtime ClassLoader, which a 
dev-mode live reload does not recreate. The manager — and the 
`BaseEventManager` inside it — therefore outlives the application it belongs to.
   
   Every restart, `AbstractProcessConfig` registers the new generation's 
`EventPublisher`s and `UnitOfWorkEventListener`s on that same manager, and both 
`addPublisher` and `register` are add-only. The publisher set grows by one per 
reload, and `publish()` then calls publishers belonging to applications that 
were shut down long ago. Those hold an `EntityManagerFactory` that was closed 
on their own shutdown, which surfaces as `IllegalStateException: 
EntityManagerFactory is closed`.
   
   Measured across five consecutive dev-mode generations — `Application` is 
correctly recreated each time, the manager never is, and the publisher count 
grows monotonically:
   
   | Start | `Application` | `UnitOfWorkManager` | `BaseEventManager` | 
Publishers |
   |---|---|---|---|---|
   | restart no:0 | `@2b15af5c` | `DefaultUnitOfWorkManager@135ba` | 
`@78f53ca9` | 1 |
   | restart no:1 | `@41d76578` | `DefaultUnitOfWorkManager@135ba` | 
`@78f53ca9` | 2 |
   | restart no:2 | `@266a08bf` | `DefaultUnitOfWorkManager@135ba` | 
`@78f53ca9` | 3 |
   | restart no:3 | `@6637bbb9` | `DefaultUnitOfWorkManager@135ba` | 
`@78f53ca9` | 4 |
   | restart no:4 | `@72a2ae1f` | `DefaultUnitOfWorkManager@135ba` | 
`@78f53ca9` | 5 |
   
   The fix scopes the producer to the application with `@Singleton` and returns 
a new `DefaultUnitOfWorkManager`.
   
   Reproducer (public dependencies only, plus the full analysis): 
https://github.com/thiagoelg/quarkus-dev-mode-emf-closed-repro
   
   ## Relationship to #3870 — this is not a revert
   
   This changes the line that dcaca447 ([`[Fix #3869] Using the same work and 
event 
manager`](https://github.com/apache/incubator-kie-kogito-runtimes/pull/3870)) 
introduced, so it needs saying explicitly.
   
   Before dcaca447 the producer was a bare `@Produces`, i.e. `@Dependent`, so 
**every injection point received its own manager** and only `ProcessConfig`'s 
carried the publishers. That is 
[#3869](https://github.com/apache/incubator-kie-kogito-runtimes/issues/3869): a 
path resolving the manager from any other injection point published into a 
manager nobody listened to.
   
   The defect in #3869 was the **missing scope**. dcaca447 obtained sharing 
through a JVM static; this PR obtains the same sharing through the container. 
dcaca447's invariant is preserved, its lifetime defect is not. `@Singleton` 
rather than `@ApplicationScoped` so injection points hold the instance 
directly, leaving the unit-of-work path free of a client proxy.
   
   This is also why dcaca447 only touched Quarkus: Spring `@Bean` methods are 
singleton-scoped by default, so Spring Boot never had #3869 and its producer 
already reads `new DefaultUnitOfWorkManager(new CollectingUnitOfWorkFactory())`.
   
   `LightProcessRuntimeServiceProvider` is deliberately left exactly as 
dcaca447 set it.
   
   ## Regression test for #3869
   
   PR #3870 shipped no test, so nothing in CI guarded against this. This PR 
adds one, in `kogito-addons-quarkus-data-index-jpa/integration-tests-process`: 
`timerResume` parks on an intermediate timer, so the instance is persisted and 
resumed by the job scheduler rather than the request thread, and the test 
asserts the data index observes the completion.
   
   It was proven to fail before it was used to pass:
   
   | Build | `UnitOfWorkManager` identities | Test |
   |---|---|---|
   | Pre-dcaca447 (reverse-applied) | config `@3c11533` (1 publisher), fresh 
lookup `@7fd0231` — a **different object** — static `@4c1a14df` (0 publishers) 
| **Fails** (`ConditionTimeoutException`, instance holds `ACTIVE`) |
   | `main` | all one object, 1 publisher | Passes |
   | This PR | config == fresh, 1 publisher | Passes |
   
   ## Validation
   
   - Dev-mode reproducer: unpatched fails from reload #2 and never recovers; 
patched gives 11/11 clean starts with zero `EntityManagerFactory is closed`.
   - Data index actually receives events (a fix that merely disconnected the 
publishers would also look clean): 5 instances started across 5 generations → 
exactly 5 indexed, all `COMPLETED`.
   - `kogito-quarkus-processes-integration-test` (10 tests), 
`integration-tests-quarkus-usertasks` (22 tests), 
`kogito-addons-quarkus-data-index-jpa/integration-tests-process` (4 tests) all 
pass.
   
   The user-task module matters most: `UserTaskConfig` shares the 
`UnitOfWorkManager` bean with `ProcessConfig`, so a wrong scope shows up there.
   
   ## Note on the second commit
   
   `[NO-ISSUE] chore: fix the jobs-service IT shared/ ignore rule...` is 
unrelated to #7106. The `.gitignore` rule for the generated 
`src/main/resources/shared` directories still pointed at 
`apps-integration-tests/...`, the pre-merge path, so it has matched nothing 
since `kogito-apps` was merged in, and a built working copy shows 24 generated 
files as untracked. Happy to split it into its own PR if preferred.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to