You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@grails.apache.org by "jdaugherty (via GitHub)" <gi...@apache.org> on 2026/10/12 10:56:00 UTC
[PR] Add Groovy 6 groovy.concurrent async and events modules, deprecate GPars [grails-core]
jdaugherty opened a new pull request, #16620:
URL: https://github.com/apache/grails-core/pull/16620
## Summary
Groovy 6 brings a unified concurrency toolkit into core under [GEP-18: Integrated Concurrency and Parallel Processing](https://groovy-lang.org/releasenotes/groovy-6.0.html#concurrency-toolkit). The `groovy.concurrent` package provides `Awaitable`, `DataflowVariable`, `Actor`, `Agent`, `Pool`, `ParallelScope` and the parallel collection methods. The release notes describe it as modernising the patterns from GPars around virtual threads and structured concurrency, and say previous GPars users "will find much of its functionality here". GPars itself (1.2.1, 2014, built against Groovy 2.x with a Multiverse dependency we exclude) is a separate, unmaintained project, so Grails 9 should stop depending on it.
This PR adds Groovy-native replacements alongside the GPars modules and deprecates the GPars modules for removal in a later release.
## Changes
- **`grails-async-groovy-concurrent`** (`org.grails.async.factory.groovy.AwaitablePromiseFactory`, `AwaitablePromise`): tasks run through `Awaitable` on Groovy's `async` executor (virtual threads by default) or a supplied `Executor`/`Pool`; unfulfilled promises are `DataflowVariable`s; every promise is itself an `Awaitable`, so `await promise` and `Awaitable.all(p1, p2)` need no conversion. Failure semantics follow the default `CompletableFuture` factory (`ExecutionException` with the original cause, single `onError` recovers, aggregate `onError` observes and stays failed). Promises that are not awaitables are resolved inline when done and otherwise bridged on the factory's own executor, so bounded pools cannot deadlock on bridging work.
- **`grails-events-groovy-concurrent`** (`org.grails.events.groovy.ActorEventBus`): one reactor actor delivers events in publication order off the publishing thread; a subscriber that throws without a reply handler is logged and later deliveries continue.
- **GPars modules deprecated, not removed**: `GparsPromiseFactory`, `GparsPromise`, `LoggingPoolFactory` and the GPars `ActorEventBus` carry `@Deprecated(since = '9.0', forRemoval = true)` and log a one-time warning naming the replacement.
- **`EventBusFactoryBean`** implements `DisposableBean` and closes a `Closeable` bus with the context, so actor-backed buses (Groovy and GPars) do not outlive the application.
- **Internal GPars usage ported**: grails-cache and neo4j tests use `everyParallel`/`collectParallel`/`eachParallel` and `ParallelScope.withPool`. The two grails-cache cache-manager tests were JUnit 4 classes that the JUnit Platform runner never executed; they are now Spock specs that run. The neo4j test module drops its GPars dependency. `grails-cache` still declares `api gpars` (unused by its main code) and is left as is for now.
- **Docs**: async and events guide tables list the Groovy modules and mark the GPars rows deprecated; the executor configuration advice points at `Awaitable.setExecutor`; a new `upgrading90x` page (first Grails 9 upgrade page, added to the toc) carries the rationale and migration notes.
Both module sets register through `META-INF/services`, so applications switch by replacing the dependency. Only one `PromiseFactory` is service-loaded and `EventBusBuilder` refuses more than one `EventBus`, which the docs now state.
## Known limitation
`PromiseFactoryBuilder` ignores Boot's `applicationTaskExecutor` and the `TaskDecorator` chain for any service-loaded factory. That is pre-existing behaviour shared with the GPars and RxJava factories; the guide now says so and names `Awaitable.setExecutor` as the supported knob. Passing the executor through the builder is a separate follow-up.
## Verification
Run locally: specs of both new modules (40 and 10 tests), the GPars module specs, grails-events-core and grails-cache suites, `codeStyle` and `validateDependencyVersions` for every touched module, `validateRepositoryConventions`, and a check that the generated base BOM lists the new artifacts. The neo4j `MiscSpec` compiles but needs a Neo4j harness, and the guide build and full `aggregateViolations` gate were left to CI.
--
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: notifications-unsubscribe@grails.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Add Groovy 6 groovy.concurrent async and events modules, deprecate GPars [grails-core]
Posted by "jdaugherty (via GitHub)" <gi...@apache.org>.
jdaugherty merged PR #16620:
URL: https://github.com/apache/grails-core/pull/16620
--
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: notifications-unsubscribe@grails.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Add Groovy 6 groovy.concurrent async and events modules, deprecate GPars [grails-core]
Posted by "codecov[bot] (via GitHub)" <gi...@apache.org>.
codecov[bot] commented on PR #16620:
URL: https://github.com/apache/grails-core/pull/16620#issuecomment-6123365745
## [Codecov](https://app.codecov.io/gh/apache/grails-core/pull/16620?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache) Report
:x: Patch coverage is `77.45098%` with `23 lines` in your changes missing coverage. Please review.
:white_check_mark: Project coverage is 60.8830%. Comparing base ([`144f6bb`](https://app.codecov.io/gh/apache/grails-core/commit/144f6bbacd31ce27baf776c808cfa2634ae23678?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache)) to head ([`a8535ab`](https://app.codecov.io/gh/apache/grails-core/commit/a8535abace6745589592bca5d27fa59b5f6eed07?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache)).
:warning: Report is 8 commits behind head on 9.0.x.
| [Files with missing lines](https://app.codecov.io/gh/apache/grails-core/pull/16620?dropdown=coverage&src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache) | Patch % | Lines |
|---|---|---|
| [...rails/async/factory/groovy/AwaitablePromise.groovy](https://app.codecov.io/gh/apache/grails-core/pull/16620?src=pr&el=tree&filepath=grails-async%2Fgroovy-concurrent%2Fsrc%2Fmain%2Fgroovy%2Forg%2Fgrails%2Fasync%2Ffactory%2Fgroovy%2FAwaitablePromise.groovy&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache#diff-Z3JhaWxzLWFzeW5jL2dyb292eS1jb25jdXJyZW50L3NyYy9tYWluL2dyb292eS9vcmcvZ3JhaWxzL2FzeW5jL2ZhY3RvcnkvZ3Jvb3Z5L0F3YWl0YWJsZVByb21pc2UuZ3Jvb3Z5) | 67.8571% | [8 Missing and 1 partial :warning: ](https://app.codecov.io/gh/apache/grails-core/pull/16620?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache) |
| [...sync/factory/groovy/AwaitablePromiseFactory.groovy](https://app.codecov.io/gh/apache/grails-core/pull/16620?src=pr&el=tree&filepath=grails-async%2Fgroovy-concurrent%2Fsrc%2Fmain%2Fgroovy%2Forg%2Fgrails%2Fasync%2Ffactory%2Fgroovy%2FAwaitablePromiseFactory.groovy&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache#diff-Z3JhaWxzLWFzeW5jL2dyb292eS1jb25jdXJyZW50L3NyYy9tYWluL2dyb292eS9vcmcvZ3JhaWxzL2FzeW5jL2ZhY3RvcnkvZ3Jvb3Z5L0F3YWl0YWJsZVByb21pc2VGYWN0b3J5Lmdyb292eQ==) | 80.4348% | [5 Missing and 4 partials :warning: ](https://app.codecov.io/gh/apache/grails-core/pull/16620?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache) |
| [...ils/async/factory/gpars/GparsPromiseFactory.groovy](https://app.codecov.io/gh/apache/grails-core/pull/16620?src=pr&el=tree&filepath=grails-async%2Fgpars%2Fsrc%2Fmain%2Fgroovy%2Forg%2Fgrails%2Fasync%2Ffactory%2Fgpars%2FGparsPromiseFactory.groovy&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache#diff-Z3JhaWxzLWFzeW5jL2dwYXJzL3NyYy9tYWluL2dyb292eS9vcmcvZ3JhaWxzL2FzeW5jL2ZhY3RvcnkvZ3BhcnMvR3BhcnNQcm9taXNlRmFjdG9yeS5ncm9vdnk=) | 33.3333% | [0 Missing and 2 partials :warning: ](https://app.codecov.io/gh/apache/grails-core/pull/16620?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache) |
| [...oovy/org/grails/events/groovy/ActorEventBus.groovy](https://app.codecov.io/gh/apache/grails-core/pull/16620?src=pr&el=tree&filepath=grails-events%2Fgroovy-concurrent%2Fsrc%2Fmain%2Fgroovy%2Forg%2Fgrails%2Fevents%2Fgroovy%2FActorEventBus.groovy&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache#diff-Z3JhaWxzLWV2ZW50cy9ncm9vdnktY29uY3VycmVudC9zcmMvbWFpbi9ncm9vdnkvb3JnL2dyYWlscy9ldmVudHMvZ3Jvb3Z5L0FjdG9yRXZlbnRCdXMuZ3Jvb3Z5) | 89.4737% | [0 Missing and 2 partials :warning: ](https://app.codecov.io/gh/apache/grails-core/pull/16620?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache) |
| [...roovy/org/grails/events/gpars/ActorEventBus.groovy](https://app.codecov.io/gh/apache/grails-core/pull/16620?src=pr&el=tree&filepath=grails-events%2Fgpars%2Fsrc%2Fmain%2Fgroovy%2Forg%2Fgrails%2Fevents%2Fgpars%2FActorEventBus.groovy&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache#diff-Z3JhaWxzLWV2ZW50cy9ncGFycy9zcmMvbWFpbi9ncm9vdnkvb3JnL2dyYWlscy9ldmVudHMvZ3BhcnMvQWN0b3JFdmVudEJ1cy5ncm9vdnk=) | 66.6667% | [0 Missing and 1 partial :warning: ](https://app.codecov.io/gh/apache/grails-core/pull/16620?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache) |
<details><summary>Additional details and impacted files</summary>
[](https://app.codecov.io/gh/apache/grails-core/pull/16620?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache)
```diff
@@ Coverage Diff @@
## 9.0.x #16620 +/- ##
==================================================
+ Coverage 60.8606% 60.8830% +0.0224%
- Complexity 26372 26430 +58
==================================================
Files 2226 2229 +3
Lines 110970 111072 +102
Branches 20095 20106 +11
==================================================
+ Hits 67537 67624 +87
- Misses 34519 34522 +3
- Partials 8914 8926 +12
```
| [Files with missing lines](https://app.codecov.io/gh/apache/grails-core/pull/16620?dropdown=coverage&src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache) | Coverage Δ | |
|---|---|---|
| [...org/grails/async/factory/gpars/GparsPromise.groovy](https://app.codecov.io/gh/apache/grails-core/pull/16620?src=pr&el=tree&filepath=grails-async%2Fgpars%2Fsrc%2Fmain%2Fgroovy%2Forg%2Fgrails%2Fasync%2Ffactory%2Fgpars%2FGparsPromise.groovy&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache#diff-Z3JhaWxzLWFzeW5jL2dwYXJzL3NyYy9tYWluL2dyb292eS9vcmcvZ3JhaWxzL2FzeW5jL2ZhY3RvcnkvZ3BhcnMvR3BhcnNQcm9taXNlLmdyb292eQ==) | `72.4138% <ø> (ø)` | |
| [...ails/async/factory/gpars/LoggingPoolFactory.groovy](https://app.codecov.io/gh/apache/grails-core/pull/16620?src=pr&el=tree&filepath=grails-async%2Fgpars%2Fsrc%2Fmain%2Fgroovy%2Forg%2Fgrails%2Fasync%2Ffactory%2Fgpars%2FLoggingPoolFactory.groovy&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache#diff-Z3JhaWxzLWFzeW5jL2dwYXJzL3NyYy9tYWluL2dyb292eS9vcmcvZ3JhaWxzL2FzeW5jL2ZhY3RvcnkvZ3BhcnMvTG9nZ2luZ1Bvb2xGYWN0b3J5Lmdyb292eQ==) | `55.5556% <ø> (ø)` | |
| [...rails/events/bus/spring/EventBusFactoryBean.groovy](https://app.codecov.io/gh/apache/grails-core/pull/16620?src=pr&el=tree&filepath=grails-events%2Fcore%2Fsrc%2Fmain%2Fgroovy%2Forg%2Fgrails%2Fevents%2Fbus%2Fspring%2FEventBusFactoryBean.groovy&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache#diff-Z3JhaWxzLWV2ZW50cy9jb3JlL3NyYy9tYWluL2dyb292eS9vcmcvZ3JhaWxzL2V2ZW50cy9idXMvc3ByaW5nL0V2ZW50QnVzRmFjdG9yeUJlYW4uZ3Jvb3Z5) | `63.1579% <100.0000%> (+6.9079%)` | :arrow_up: |
| [...roovy/org/grails/events/gpars/ActorEventBus.groovy](https://app.codecov.io/gh/apache/grails-core/pull/16620?src=pr&el=tree&filepath=grails-events%2Fgpars%2Fsrc%2Fmain%2Fgroovy%2Forg%2Fgrails%2Fevents%2Fgpars%2FActorEventBus.groovy&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache#diff-Z3JhaWxzLWV2ZW50cy9ncGFycy9zcmMvbWFpbi9ncm9vdnkvb3JnL2dyYWlscy9ldmVudHMvZ3BhcnMvQWN0b3JFdmVudEJ1cy5ncm9vdnk=) | `66.6667% <66.6667%> (ø)` | |
| [...ils/async/factory/gpars/GparsPromiseFactory.groovy](https://app.codecov.io/gh/apache/grails-core/pull/16620?src=pr&el=tree&filepath=grails-async%2Fgpars%2Fsrc%2Fmain%2Fgroovy%2Forg%2Fgrails%2Fasync%2Ffactory%2Fgpars%2FGparsPromiseFactory.groovy&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache#diff-Z3JhaWxzLWFzeW5jL2dwYXJzL3NyYy9tYWluL2dyb292eS9vcmcvZ3JhaWxzL2FzeW5jL2ZhY3RvcnkvZ3BhcnMvR3BhcnNQcm9taXNlRmFjdG9yeS5ncm9vdnk=) | `50.0000% <33.3333%> (-1.7241%)` | :arrow_down: |
| [...oovy/org/grails/events/groovy/ActorEventBus.groovy](https://app.codecov.io/gh/apache/grails-core/pull/16620?src=pr&el=tree&filepath=grails-events%2Fgroovy-concurrent%2Fsrc%2Fmain%2Fgroovy%2Forg%2Fgrails%2Fevents%2Fgroovy%2FActorEventBus.groovy&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache#diff-Z3JhaWxzLWV2ZW50cy9ncm9vdnktY29uY3VycmVudC9zcmMvbWFpbi9ncm9vdnkvb3JnL2dyYWlscy9ldmVudHMvZ3Jvb3Z5L0FjdG9yRXZlbnRCdXMuZ3Jvb3Z5) | `89.4737% <89.4737%> (ø)` | |
| [...rails/async/factory/groovy/AwaitablePromise.groovy](https://app.codecov.io/gh/apache/grails-core/pull/16620?src=pr&el=tree&filepath=grails-async%2Fgroovy-concurrent%2Fsrc%2Fmain%2Fgroovy%2Forg%2Fgrails%2Fasync%2Ffactory%2Fgroovy%2FAwaitablePromise.groovy&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache#diff-Z3JhaWxzLWFzeW5jL2dyb292eS1jb25jdXJyZW50L3NyYy9tYWluL2dyb292eS9vcmcvZ3JhaWxzL2FzeW5jL2ZhY3RvcnkvZ3Jvb3Z5L0F3YWl0YWJsZVByb21pc2UuZ3Jvb3Z5) | `67.8571% <67.8571%> (ø)` | |
| [...sync/factory/groovy/AwaitablePromiseFactory.groovy](https://app.codecov.io/gh/apache/grails-core/pull/16620?src=pr&el=tree&filepath=grails-async%2Fgroovy-concurrent%2Fsrc%2Fmain%2Fgroovy%2Forg%2Fgrails%2Fasync%2Ffactory%2Fgroovy%2FAwaitablePromiseFactory.groovy&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache#diff-Z3JhaWxzLWFzeW5jL2dyb292eS1jb25jdXJyZW50L3NyYy9tYWluL2dyb292eS9vcmcvZ3JhaWxzL2FzeW5jL2ZhY3RvcnkvZ3Jvb3Z5L0F3YWl0YWJsZVByb21pc2VGYWN0b3J5Lmdyb292eQ==) | `80.4348% <80.4348%> (ø)` | |
... and [9 files with indirect coverage changes](https://app.codecov.io/gh/apache/grails-core/pull/16620/indirect-changes?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache)
</details>
<details><summary> :rocket: New features to boost your workflow: </summary>
- :snowflake: [Test Analytics](https://docs.codecov.com/docs/test-analytics): Detect flaky tests, report on failures, and find test suite problems.
- :package: [JS Bundle Analysis](https://docs.codecov.com/docs/javascript-bundle-analysis): Save yourself from yourself by tracking and limiting bundle sizes in JS merges.
</details>
--
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: notifications-unsubscribe@grails.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Add Groovy 6 groovy.concurrent async and events modules, deprecate GPars [grails-core]
Posted by "testlens-app[bot] (via GitHub)" <gi...@apache.org>.
testlens-app[bot] commented on PR #16620:
URL: https://github.com/apache/grails-core/pull/16620#issuecomment-6125940668
## ✅ All tests passed ✅
🏷️ Commit: a8535abace6745589592bca5d27fa59b5f6eed07
▶️ Tests: 99891 executed
⚪️ Checks: 87/87 completed
---
_Learn more about TestLens at [testlens.app/docs](https://testlens.app/docs/features/pr-comment/)._
--
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: notifications-unsubscribe@grails.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] Add Groovy 6 groovy.concurrent async and events modules, deprecate GPars [grails-core]
Posted by "matrei (via GitHub)" <gi...@apache.org>.
matrei commented on code in PR #16620:
URL: https://github.com/apache/grails-core/pull/16620#discussion_r4256625410
##########
grails-cache/src/test/groovy/grails/plugin/cache/GrailsConcurrentLinkedMapCacheManagerSpec.groovy:
##########
@@ -0,0 +1,100 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package grails.plugin.cache
+
+import groovy.concurrent.ParallelScope
+
+import spock.lang.Specification
+
+/**
+ * @author Jakob Drangmeister
Review Comment:
`@author`?
##########
grails-cache/src/test/groovy/grails/plugin/cache/GrailsConcurrentMapCacheManagerSpec.groovy:
##########
@@ -0,0 +1,100 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package grails.plugin.cache
+
+import groovy.concurrent.ParallelScope
+
+import spock.lang.Specification
+
+/**
+ * @author Burt Beckwith
Review Comment:
`@author`?
--
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: notifications-unsubscribe@grails.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org