Allow group-scoped rollout of session credits ingestion
What does this MR do and why?
Both session credits workers, Ai::DuoWorkflows::FetchSessionCreditsCronWorker and Ai::DuoWorkflows::FetchNamespaceSessionCreditsWorker, checked the flag duo_workflow_session_credits_ingestion only with the :instance actor. A group gate set through ChatOps had no effect. The only way to turn ingestion on was instance-wide for all of gitlab.com, which the rollout thread wants to avoid before a production check on the gitlab-org group.
Both workers now check the flag once per batch using the root namespace as actor, Feature.enabled?(:duo_workflow_session_credits_ingestion, Group.actor_from_id(root_namespace_id)). Flipper returns true for either a group gate or the global toggle, so the separate :instance check is gone. This follows the feature flag docs' guidance to prefer group actors and use root_ancestor. The cron only advances its ClickHouse sync cursor when at least one batch was dispatched, so a fully-off flag holds the cursor and loses nothing.
- Known tradeoff: during a group-only rollout, sessions from other root namespaces that get scanned are skipped for good, since there is a single cursor. This is acceptable because the rollout plan is
gitlab-orgonly, then global, then remove the flag. - Self-managed batches carry no namespace and use the
:instanceactor. - No
Namespacelookup is needed.Group.actor_from_idbuilds the actor without a query. - No schema or CustomersDot change.
References
- Rollout work item: https://gitlab.com/gitlab-org/gitlab/-/work_items/607369
- Original ingestion MR: !247620 (merged)
- Discussion that prompted this change: https://gitlab.com/gitlab-org/gitlab/-/work_items/607369#note_3774576674
- Feature flag definition:
ee/config/feature_flags/gitlab_com_derisk/duo_workflow_session_credits_ingestion.yml
How to set up and validate locally
-
Enable ClickHouse for analytics in GDK and enable the flag for one group only:
Feature.enable(:duo_workflow_session_credits_ingestion, Group.find_by_full_path('gitlab-org')) -
Create two workflows in a billable status older than the settle horizon, one under that group and one under another group. For example, in a console:
create(:duo_workflows_workflow, status: 3, updated_at: 3.hours.ago, namespace: group)Use
FactoryBotthis way, or update existing rows directly. -
Run the cron worker and check Sidekiq or the logs. Only the gated group's session ids should be passed to the child worker.
Ai::DuoWorkflows::FetchSessionCreditsCronWorker.new.perform -
Check that the cursor advanced to the gated session's
updated_at:ClickHouse::SyncCursor.cursor_for(:duo_workflow_session_credits) -
Disable the flag entirely, create another billable session, and run the cron again. Check that nothing was dispatched and the cursor did not move:
Feature.disable(:duo_workflow_session_credits_ingestion) -
Run the specs:
bin/rspec ee/spec/workers/ai/duo_workflows/fetch_session_credits_cron_worker_spec.rb ee/spec/workers/ai/duo_workflows/fetch_namespace_session_credits_worker_spec.rb
MR acceptance checklist
Evaluate this MR against the MR acceptance checklist.