-
Type:
Task
-
Resolution: Unresolved
-
Priority:
Minor - P4
-
None
-
Affects Version/s: None
-
Component/s: None
-
None
-
Query Execution
-
None
-
None
-
None
-
None
-
None
-
None
-
None
Summary
The internal transaction API (txn_api::SyncTransactionWithRetries / SEPTransactionClient, in src/mongo/db/transaction/sep_transaction_client.cpp) creates a fresh Client + OperationContext for each internally-dispatched command (SEPTransactionClient::_runCommand). The caller's IncrementalFeatureRolloutContext (IFR flags + ifrSenderVersion) is not carried onto that fresh opCtx, so commands issued inside an internal transaction re-derive the IFR context instead of preserving the caller's wire-installed one. On a mongod shard (where isRouter == false), this means an internal transaction that fans out would drop ifrSenderVersion/ifrFlags instead of forwarding the original sender's values.
Proposed fix
* Capture the caller's IFRContext in Transaction::_primeTransaction (src/mongo/db/transaction/transaction_api.cpp), guarded on isInstalledFromWire() so only wire-originated contexts are forwarded (a locally-derived forRequestWithoutIfrFlags() context must not be re-forwarded).
* Thread it through TxnHooks and install it on the child opCtx in SEPTransactionClient::_runCommand via IncrementalFeatureRolloutContext::set(...) so the egress metadata hook stamps the original sender's values.
* Unit tests already drafted in src/mongo/db/transaction/transaction_api_test.cpp (ForwardsWireInstalledIfrContextToInternalTransaction / DoesNotForwardLocallyDerivedIfrContext).
NOT needed in 9.0
Static analysis shows that in 9.0 no IFR flag value is consumed inside any shard-originated internal transaction. IFR flag consumption is confined to the aggregate/query parsing + planning path (via ExpressionContext::getIfrContext()->getSavedFlagValue(...)); the write-execution code that internal transactions actually run (write_ops_exec.cpp, timeseries writes, performUpdates/Inserts/Deletes) never touches the IFRContext (write-path flags use the process-global checkEnabled()). Every observable end-to-end path is either mongos-coordinated (where isRouter re-stamps the local senderVersion, masking the gap) or shard-local (no cross-shard egress). So this is a defensive/future-proofing change only; it has no functional effect in 9.0.
Epic
Filed under the IFR epic (SPM-4726) for visibility, but it probably does not belong in that epic since it is not required for the IFR 9.0 rollout — triage may want to move or defer it.