codeconsole opened a new pull request, #16208:
URL: https://github.com/apache/grails-core/pull/16208
Two settings for the MongoDB index build that runs when the datastore
starts, plus the reporting to make either decision an informed one.
## `grails.mongodb.buildIndexes`
```groovy
grails {
mongodb {
buildIndexes = false
}
}
```
GORM creates and reconciles every index declared in a mapping block each
time the datastore starts, with no way to switch it off. That is unwanted when
deploying against live data whose indexes are managed separately, by a DBA or a
migration step: the deployment builds indexes against production collections
and reconciles the index set the running application depends on.
With the setting off, no `createIndex` or `collMod` is issued for any domain
class and the indexes on the server are left exactly as they are. Persistence
and querying are unaffected and keep using whichever indexes exist. It also
covers domain classes registered after startup, and resolves per connection
like every other connection setting, so index building can be switched off
globally and left on for one connection:
```groovy
grails {
mongodb {
buildIndexes = false
connections {
reporting {
url = "mongodb://localhost/reporting"
buildIndexes = true
}
}
}
}
```
A collection that has never started up with index building enabled will have
no declared indexes at all, so this is for environments where the indexes are
already in place or are applied by other means. It governs only what GORM
derives from mapping blocks; an explicit `createIndex` in application code is
unaffected.
## `grails.mongodb.buildIndexesAsync`
```groovy
grails {
mongodb {
buildIndexesAsync = true
}
}
```
MongoDB answers a `createIndex` only once the index has been built, so by
default startup waits for every declared index in turn. Measured against
MongoDB 7.0 with 200k documents: 172ms to create one index on the calling
thread, 1.2ms to re-issue the same declaration. `background: true` has been
ignored since MongoDB 4.2 and costs the same.
With this enabled the startup build runs on one daemon thread per
connection, named `gorm-mongo-index-build-<connection>`, and startup continues
without waiting. Indexes are still built one at a time rather than all at once
against the server.
Worth planning for:
- A query issued before its index has been built is served without it —
correctly, but unindexed. A `unique` index likewise constrains nothing until
the build finishes.
- Startup no longer waits, so a failed index build can no longer fail
startup. It is logged at error level and the application runs without that
index. The default synchronous build still propagates the exception.
- It applies to the startup build only. A domain class registered afterwards
is indexed on the thread registering it, which keeps the tenant context that
path can depend on.
## Index build reporting
A successful build previously logged nothing at all — only conflicts, TTL
updates and failures — so there was no way to tell how much of startup went on
indexes, and with the async build no signal that it had finished. It now logs
one summary:
```
Index build for database [myDb] finished in 412ms: 2 created, 5 already
present, from 3 domain class(es)
```
The created/already-present split is what makes the elapsed time
interpretable: a restart that changed no mappings reports everything as already
present and costs milliseconds, so a summary reporting indexes created is the
one that accounts for a slow start. A build with failures is logged at `WARN`
and reports how many. Each index also logs its own elapsed time at `DEBUG`
under `org.grails.datastore.mapping.core`, which is how to find the single slow
index behind a slow summary.
`createIndexes` reports `numIndexesBefore` / `numIndexesAfter`, but the
driver's `createIndex` helper discards the response and returns only the index
name. Rather than hand-roll the command — the `IndexOptions` to
index-specification mapping is not worth reimplementing — the build lists the
indexes a collection already has. That listing is lazy, so an entity declaring
no indexes costs no round trip, and it replaces the listing the conflict path
used to make for itself. If it cannot be read, the build still runs and the
summary falls back to reporting how many declarations were applied.
## Settings were ignored when the application supplies its own `MongoClient`
Found while testing the above. The constructors taking a `MongoClient` (or a
`MongoClientSettings.Builder`) built the default connection source from a bare
`MongoConnectionSourceSettings`, so every `grails.mongodb` setting describing
how the datastore behaves — `stateless`, `transactional`, `engine`, flush mode,
`decimalType`, and now `buildIndexes` — was silently left at its default. Only
`databaseName` survived, because it is set explicitly from the mapping context.
That path is not obscure: Spring Boot's MongoDB auto-configuration
contributes a `MongoClient` bean and `MongoDbGormAutoConfiguration` hands that
client to GORM whenever one is present, so a Spring Boot application
configuring GORM through `grails.mongodb` was being ignored. The settings are
now bound from the configuration on that path too; the connection details in
them go unused, as the client arrives already connected.
This is a behaviour change for anyone who had been running on defaults
without knowing it — a `stateless = true` or `transactional = true` that was
previously discarded now takes effect.
## Notes
- Documented in `grails-data-mongodb/docs` under Querying Indexing and
Advanced Configuration, with the 8.0 release notes updated.
- The mongo core tests now run against logback rather than the no-op SLF4J
binding, as `grails-data-neo4j/core` already does, so a test can assert on what
was logged. The root logger is pinned to `WARN` by a `logback-test.xml`, and
the build output is unchanged.
--
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]