codeconsole opened a new pull request, #16368:
URL: https://github.com/apache/grails-core/pull/16368

   Fixes #16366.
   
   `MongoDatastore` takes part in the Spring lifecycle so an application can be 
checkpointed with CRaC and restored (#16095). Until now only the default 
connection's `MongoClient` was covered. This makes checkpoint and restore cover 
every client GORM creates. A second commit fixes `withConnection`, which I 
found while testing named connections.
   
   ### Checkpoint and restore cover every connection
   
   - **Every connection is closed and replaced.** `stop()` closes the client of 
the default connection, of each connection under `grails.mongodb.connections`, 
and of any added at runtime. `start()` builds a replacement for each from the 
same settings.
   - **The replacement is handed out wherever the original was.** 
`MongoConnectionSourceFactory` now creates a `MongoConnectionSource`, a 
`DefaultConnectionSource` whose client can be replaced. Code that reads the 
client from the datastore's connection sources gets the new one. This fixes 
SCHEMA multi-tenancy, where `eachTenant` listed databases through the closed 
client, and `MongoConnectionSources`, which recorded a connection added after a 
restore through the closed client.
   - **`close()` after a restore closes the replacements**, on every connection.
   - **Spring Data follows the datastore.** The auto-configured 
`MongoDatabaseFactory` asks the datastore for its client on every use, so 
`MongoTemplate` and repositories keep working after a restore.
   - **Client options survive a restore.** A datastore built from a 
`MongoClientSettings.Builder` builds its replacement default client with those 
options. Before, the replacement was built from the configuration alone and 
lost them.
   - **A supplied client is still left alone**, and with a supplied default 
client, the named connections GORM created are still closed and replaced.
   
   The guide gains a "Checkpoint and Restore (CRaC)" section under Advanced 
Configuration, plus a release-notes entry and a line on the Spring Data interop 
page.
   
   ### `withConnection` routes the class's own calls
   
   The guide shows `Book.withConnection('moreBooks') { Book.list() }`, but only 
the calls made without naming the class, such as `list()`, used the named 
connection. `Book.list()`, dynamic finders, `where` queries and `book.save()` 
went to the default connection, so a save inside the block was written to the 
wrong database. They now use the block's connection:
   
   ```groovy
   Book.withConnection('moreBooks') {
       new Book(title: 'Dune').save(flush: true)   // written to moreBooks
       Book.countByTitle('Dune')                    // read from moreBooks
   }
   ```
   
   An operation that names its own connection, such as 
`Book.moreBooks.count()`, keeps it, and the default connection applies again 
after the block, including when it throws. The routing lives in 
`GormRegistry.withConnectionScope`, which `MongoEntity.withConnection` uses. 
The guide's page for `withConnection` now says exactly what the block covers.
   
   ### Limitations
   
   - A custom `MongoConnectionSourceFactory` whose `create` returns a plain 
`DefaultConnectionSource` has its clients closed and replaced in the datastore, 
but those connection sources keep handing out the closed originals.
   - When `MongoDbGormAutoConfiguration` creates the client itself (a 
`MongoProperties` bean but no `MongoClient` bean), it passes that client to the 
datastore as supplied, so a checkpoint leaves it open, as before.
   - A `MongoClient` that application code obtained before the checkpoint is 
closed; code keeping one has to obtain it again after the restore.
   - `Book.moreBooks.withNewSession { }` and `Book.moreBooks.withTransaction { 
}` are not scopes: `book.save()` inside them still uses the entity's default 
connection. Use `withConnection`, or the qualified API itself 
(`Book.moreBooks.save(book)`).
   - Neo4j's `withConnection` has the same routing problem and is not changed 
here. A Neo4j datastore with a named connection currently fails to start (the 
driver config builder calls `withEventLoopThreads(0)`), so the change could not 
be tested.
   


-- 
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]

Reply via email to