Reduce ExpirePipelineCacheService load on the database by fixing unnecessary cache invalidations
## Problem
In https://gitlab.com/gitlab-com/gl-infra/production/-/work_items/21562 we found that `ExpirePipelineCacheService` is running ~400 RPS against the CI primary database ([dashboard](https://dashboards.gitlab.net/goto/bfgvx3tua94aoa?orgId=1)).
We introduced https://gitlab.com/gitlab-org/gitlab/-/merge_requests/228054 to expire the cache async using the replica nodes, but that didn't reduce the calls to the primary node.
The root cause is that `ExpirePipelineCacheService` is also called synchronously from `AtomicProcessingService`, which already executes on the primary database:
- `app/services/ci/pipeline_processing/atomic_processing_service.rb` [L43-51](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/services/ci/pipeline_processing/atomic_processing_service.rb?plain=1#L43-51)
This call site was originally async but was switched to synchronous ~5 years ago in [!75611](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/75611/diffs), bypassing the background worker routing introduced by the feature flag.
Additionally, the cache may be invalidated unnecessarily. The [pipeline model](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/models/ci/pipeline.rb?plain=1#L327-355) gates invalidation on pipeline status changes, but `AtomicProcessingService` ([L43-51](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/services/ci/pipeline_processing/atomic_processing_service.rb?plain=1#L43-51)) calls `ExpirePipelineCacheService` unconditionally -- including cases where the pipeline status may not have changed (e.g. replacing a running job with the next running job). The two call sites also appear redundant.
If the speculation is correct that the cache does not need to be expired on every `AtomicProcessingService` run, we would expect the ~400 RPS to drop to around ~10 RPS.
## Proposal
- Investigate whether the ETag cache expiration call in `AtomicProcessingService` ([L43-51](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/services/ci/pipeline_processing/atomic_processing_service.rb?plain=1#L43-51)) can be removed entirely, or conditionally called only when the pipeline status actually changes.
- Consolidate the two call sites to eliminate redundancy and ensure all cache expiration is routed through the background worker.
### UPDATE [2026-04-14]
We can't remove Etag cache expiration in `AtomicProcessingService` because many paths cache more granular data than just pipeline status (https://gitlab.com/gitlab-org/gitlab/-/work_items/594454#note_3191936546).
See discussion thread for new proposals in https://gitlab.com/gitlab-org/gitlab/-/work_items/594454#note_3193561359.
issue