Skip to content

perf(store-pg): consolidate ScopeLinkRepo into single UNION ALL query #56

@chaizhenhua

Description

@chaizhenhua

Follow-up from PR #55 review.

Context

PR #55 introduced ScopeLinkRepo::list_authz_scope_links() to replace the legacy "hydrate full entities then map to scope edges" approach with ID-only queries. The Postgres implementation in crates/oversight-store-pg/src/repo_scope_link.rs currently issues 7 sequential SQL queries (projects, collections, documents, tasks, workflows, cycles, agent_definitions).

This is already a significant improvement over the legacy collector that hydrated Document labels/attrs/version, Task assignees/labels, nested workflow state, etc. But each authz reload still incurs 7 PG round-trips, which adds up under frequent reload (membership/grant churn, hot-reload triggers).

Proposed change

Collapse into one UNION ALL shaped as (child_type, child_id, parent_type, parent_id), then map tuples to Scope variants in Rust:

SELECT 'project'    AS child_type, id        AS child_id, 'workspace'  AS parent_type, NULL::text AS parent_id FROM projects
UNION ALL
SELECT 'collection', id, 'project',    project_id    FROM collections
UNION ALL
SELECT 'document',   id, 'collection', collection_id FROM documents
UNION ALL
SELECT 'task',       id, 'project',    project_id    FROM tasks      WHERE project_id IS NOT NULL
UNION ALL
SELECT 'workflow',   id, 'project',    project_id    FROM workflows  WHERE project_id IS NOT NULL
UNION ALL
SELECT 'cycle',      id, 'project',    project_id    FROM cycles     WHERE project_id IS NOT NULL
UNION ALL
SELECT 'agent',      agent_id, 'workspace', NULL::text                FROM agent_definitions;

Acceptance

  • Single PG query replaces the 7 sequential ones in crates/oversight-store-pg/src/repo_scope_link.rs.
  • Existing pg_scope_link_repo testcontainer test in crates/oversight-store-pg/tests/repo_contracts.rs passes unchanged.
  • Cross-backend parity stays asserted via the same fixture in both sqlite_scope_link_repo and pg_scope_link_repo.
  • Behavior on empty tables remains identical (returns Vec::new()).

Notes

  • Deferred from PR ✨ feat(authz): add scope link repo loader #55 review ("可选优化 PG 为单个 UNION ALL 查询;不做也可以先合并").
  • Worth a quick benchmark under realistic reload frequency before/after to confirm the readability tradeoff is worth it.
  • Pure perf/internal change — no API surface or scope-graph semantics change.

Refs: PR #55, commits 67b76766 + ddb07217.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions