Add batch authorization cache pre-seeding to RedactionService
What does this MR do and why?
Before policy evaluation, RedactionService now batch-loads authorization data using ProjectPolicyPreloader and GroupPolicyPreloader. This replaces per-resource N+1 queries on project_authorizations and members tables with batch lookups.
Also wraps License.current in SafeRequestStore to avoid repeated JSON deserialization and AR object allocation on every call. Each warm-cache call to License.current parses JSON and allocates two License AR objects. With 50 projects and 16 licensed-feature checks per ProjectPolicy, that is ~800 unnecessary allocations per batch.
Stacked on !229374 (merged) (merged).
How to set up and validate locally
1. Check out the branch
git fetch origin michaelangeloio/redaction-batch-preseeding
git checkout michaelangeloio/redaction-batch-preseeding2. Run the specs (92 examples)
bundle exec rspec spec/services/authz/redaction_service_spec.rb \
ee/spec/services/ee/authz/redaction_service_spec.rb3. Run License.current caching specs
bundle exec rspec ee/spec/models/license_spec.rb \
-e ".current" -e "reset_current"4. Verify with rails runner (requires seeded database)
bundle exec rails runner '
admin = User.find_by(admin: true)
regular = User.where(admin: false).first
projects = Project.limit(10).pluck(:id)
issues = Issue.limit(10).pluck(:id)
notes = Note.limit(10).pluck(:id)
resources = {
"project" => { "ids" => projects, "ability" => "read_project" },
"issue" => { "ids" => issues, "ability" => "read_issue" },
"note" => { "ids" => notes, "ability" => "read_note" }
}
[admin, regular].each do |u|
result = Authz::RedactionService.new(
user: u, resources_by_type: resources, source: "test"
).execute
result.each do |type, auths|
auth = auths.count { |_, v| v }
puts "#{u.username} - #{type}: #{auth}/#{auths.size} authorized"
end
end
'Expected: admin sees all resources, regular user is denied access to private projects/issues/notes.
References
- Depends on: !229374 (merged) (merged)
- Part of: orbit/knowledge-graph#348
- Postgres.ai benchmarks: session webui-150381