JHSUYU opened a new pull request, #4862:
URL: https://github.com/apache/solr/pull/4862

   JIRA: SOLR-18413
   # Description
   
   A SolrCloud `MIGRATE` adds a temporary routing rule to the source slice so 
that matching updates are also forwarded to the target collection.
   
   For example, migrating route key `a!` from `source` to `target` creates 
state similar to:
   
   ```text
   source/shard1.routingRules["a!"].targetCollection = "target"
   ```
   
   The routing rule stores the target collection name as a string. Deleting 
`target` does not remove routing rules in other collections that refer to it, 
so the source can retain an unexpired rule whose target is no longer present in 
`ClusterState`.
   
   A subsequent matching update, such as adding `id=a!2` to `source`, is first 
applied locally on the source shard leader. 
`DistributedZkUpdateProcessor.doDistribAdd()` then resolves routing-rule 
destinations before distributing the update to the source shard replicas:
   
   ```java
   final List<SolrCmdDistributor.Node> nodesByRoutingRules =
       getNodesByRoutingRules(
           clusterState, coll, cmd.getIndexedIdStr(), 
cmd.getSolrInputDocument());
   ...
   if (nodes != null) {
     cmdDistrib.distribAdd(...);
   }
   ```
   
   `getNodesByRoutingRules()` previously resolved the target using:
   
   ```java
   DocCollection targetColl =
       cstate.getCollection(rule.getTargetCollectionName());
   ```
   
   If the target had been deleted, this threw:
   
   ```text
   HTTP 400
   Could not find collection : target
   ```
   
   Because the source leader had already applied the update, but the exception 
occurred before source-replica distribution, the request could leave the shard 
in this state:
   
   ```text
   source shard leader:    a!2 exists
   source shard replica:   a!2 is missing
   client:                 HTTP 400
   ```
   
   No request was sent to the source replica, so `SolrCmdDistributor` did not 
record a replica failure and this update did not trigger term demotion or 
recovery. Queries can then return different results depending on which replica 
serves them. If leadership subsequently moves to a replica that never received 
the update, the document is lost.
   
   
   # Solution
   
   Resolve the routing-rule target with `getCollectionOrNull()`:
   
   ```java
   DocCollection targetColl =
       cstate.getCollectionOrNull(rule.getTargetCollectionName());
   if (targetColl == null) {
     removeRoutingRule(myShardId, routeKey);
     break;
   }
   ```
   
   When the target collection no longer exists, the routing rule is treated as 
invalid. The existing routing-rule removal logic used for expired rules was 
extracted into `removeRoutingRule()`. Expired rules and rules with missing 
targets now share the same cleanup path. The cleanup remains guarded by the 
core's routing-rule lock.
   
   The behavior for a target collection that exists but has no active slices is 
unchanged. That condition may be temporary and continues to produce an error 
rather than permanently removing the routing rule.
   
   # Tests
   
   Added:
   
   - `MigrateRouteKeyTest.updateSucceedsAfterMigrateTargetIsDeleted`
   
   The test uses a real two-node `MiniSolrCloudCluster` and performs this 
sequence:
   
   1. Creates a `source` collection.
   2. Creates a `target` collection.
   3. Adds and commits `id=a!1` to the source.
   4. Migrates route key `a!` from the source to the target.
   5. Confirms that the source shard contains an active routing rule targeting 
the target collection.
   6. Deletes the target collection and waits for it to disappear from 
`ClusterState`.
   7. Adds `id=a!2` to the source and commits.
   8. Queries each source replica directly with `distrib=false`.
   9. Confirms that both the leader and non-leader replica contain `a!2`.
   10. Confirms that the dangling routing rule is removed.
   
   Without the fix, the add in step 7 fails with:
   
   ```text
   Could not find collection : deletedMigrateTarget-target
   ```


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