Skip to content

Reuse scheduler catalog ranking before publication locks - #71

Merged
abhi1693 merged 2 commits into
masterfrom
fix/scheduler-catalog-reuse
Oct 4, 2026
Merged

abhi1693 merged 2 commits into
masterfrom
fix/scheduler-catalog-reuse

Conversation

@abhi1693

@abhi1693 abhi1693 commented Oct 3, 2026 •

Copy link
Copy Markdown
Owner

What changes and why?

Scheduler ticks repeatedly loaded the full catalog and ranked the same article during validity checks, publication evaluation and policy application. The audit attributed about 84% of sampled CPU to catalog validity. A fresh production check measured a 105.7-second average tick over one hour, about 0.90 scheduler CPU cores and a 470 MiB working set. Ranking also ran while source/article rows and the topic catalog were locked.

The production PostgreSQL audit window recorded 57 topic write-lock calls averaging 541 ms. The activity snapshot also showed an idle transaction waiting on ClientRead, consistent with the sampled Python catalog work occurring between database calls. These are baseline observations; this PR makes no claim of a measured production improvement.

Article automation now reuses a catalog snapshot and prepared retrieval indexes within each batch. PostgreSQL UUID revisions remain authoritative, including when Redis caching is disabled. Each article is ranked after the preparation transaction closes; the locked transaction verifies the current article input and catalog revisions before reusing the result. A changed input or catalog leaves the article due for the next tick. Source eligibility, editorial revisions, job state, negative classifications and paywall checks retain their existing guards. Candidate results are bounded to eight articles and released at the end of the batch. Publication evaluation is reused only within its existing locked transaction.

Migration 0022 includes topic description and ai_description in revision invalidation because ranking reads both. It invalidates existing topic snapshots once. The application now requires schema revision 0022.

On a synthetic catalog matching the measured production size (4,450 topics and 34,057 tags), the catalog hot path for 50 articles improved from 40.39 seconds to 1.77 seconds, with identical candidate outputs and 95.6% less CPU time. The baseline used the functions from ba167ee7, one JSON catalog decode per article and three candidate checks per article; the optimized run used one decode per batch, an additional preparation call and the same three checks. Both runs started with cold retrieval caches. This measures the catalog hot path locally; production tick latency and lock waits still need post-release verification.

This branch contains only scheduler/catalog reuse, its correctness migration, regression tests and documentation. Authentication-log redaction (#69) and OpenSSF Scorecard (#70) remain on separate branches.

Validation

  • Python project checks: Ruff lint/format, mypy, pre-commit configuration and version consistency passed.
  • Commit hooks passed, including the complete backend unit suite.
  • Focused catalog/scheduler regression suite: 29 passed. This covers unchanged inputs, content/catalog/limit invalidation, bounded result retention, Redis enabled/disabled, raw SQL edits, rollback, description vocabulary, and source/editorial/catalog/content races.
  • The publication batch regression confirms one catalog load for five publishable articles, one ranking and evaluation per article, and no acquired lock or checked-out database connection during ranking.
  • Populated release-schema and legacy topic-kind upgrades passed, retaining records and relationships.
  • 0022 downgrade/re-upgrade passed, including snapshot invalidation and restored/upgraded description-trigger behavior. The migration introduces no model-schema differences; the existing migration-only search statistics index is retained.
  • Full CI integration suite: 1,111 passed, no skips, including disposable PostgreSQL/Redis, imgproxy and database-failure recovery checks.
  • No UI changes; browser screenshots and extension packaging are not applicable.

Rollout notes

Apply migration 0022 through the normal migration-first release before starting updated services. It replaces the revision trigger function and bumps the topics revision; it changes no tables, indexes or stored content. A source rollback to the previous exact-schema version also requires the migration downgrade. Downgrade restores the earlier description-invalidation behavior and invalidates snapshots again.

No production mutation or deployment was performed. After release, compare scheduler tick duration and CPU together with PostgreSQL topic-lock waits over matching windows. The existing 15-second scheduler pause remains unchanged.

Merge queue validation

Updated against current master after #69. The only conflict was in CHANGELOG.md; both user-facing fixes are retained. After the update, 46 catalog/CI unit regressions and 19 catalog/scheduler integration tests passed against disposable PostgreSQL 18 and Redis 8, with migration 0022 applied. Full hosted CI, CI required, CodeQL and Sonar passed on updated commit 84649215. Hosted suites passed with 2,619 backend unit tests, 1,111 integration tests, 785 reader tests and 647 admin tests, with no skips. Populated-schema migration upgrades, web/Chrome/Edge parity and all ARM64 image build/scan/smoke checks passed. Sonar MCP confirms 89.4% new-code coverage, 0.0% duplication, and zero new bugs, vulnerabilities or code smells. The separate GitHub-managed AI review remains quota-blocked, independently of these passing checks.

Merge this PR before #72, then retarget #72 to master. Merge the worker-lock fix before updating #79, preserving its computation outside catalog locks and rerunning its lock regressions. Auto-merge remains disabled; draft #59 is excluded.

Ready for review

  • The description explains the change and the validation results, including any gaps.
  • Relevant documentation and regression tests are updated.

@github-actions

github-actions Bot commented Oct 3, 2026 •

Copy link
Copy Markdown

PR reader API performance

Result: INCONCLUSIVE

7 inconclusive · 1 within threshold. Zero request failures across all six runs.

Base 82dba10cab7da4514682ca6a725aa72b4b8264ef → PR 84649215df71ec78bf7d5f99af9c6b41922efd8a

Three independent runs per revision, each on a fresh GitHub-hosted ARM64 runner. 16 users, 60 seconds/run, 1,000 synthetic articles, cache off, five PgBouncer slots.

Latency comparison

All latency values are in milliseconds; lower is better. Values are medians of three runs.

Route Base p95 PR p95 Change Result
All requests 130 92 -38 (-29.2%) Inconclusive
Latest feed 180 120 -60 (-33.3%) Inconclusive
Feed pagination 130 87 -43 (-33.1%) Inconclusive
Article detail 89 79 -10 (-11.2%) Inconclusive
Source feed 130 82 -48 (-36.9%) Inconclusive
Topic feed 78 81 +3 (+3.8%) Inconclusive
Feed filters 120 73 -47 (-39.2%) Inconclusive
Sources 41 38 -3 (-7.3%) Within threshold
Topics 74 51 -23 (-31.1%) Inconclusive
Additional latency and throughput metrics

Each cell shows base → PR. Latencies are in milliseconds.

Endpoint p50 p99 Requests/s
Aggregated 34 → 27 200 → 140 29.92 → 29.65
/v1/feed [latest] 52 → 43 220 → 150 8.61 → 8.76
/v1/feed [page] 33 → 22 170 → 130 3.55 → 3.59
/v1/articles/[id] 23 → 17 160 → 110 6.04 → 6.84
/v1/feed [source] 32 → 25 190 → 130 1.83 → 1.65
/v1/feed [topic] 32 → 26 110 → 130 2.09 → 1.71
/v1/feed/options 24 → 19 170 → 100 2.55 → 2.53
/v1/sources 15 → 10 110 → 78 2.55 → 2.53
/v1/topics 17 → 11 120 → 75 2.55 → 2.53
Individual runs
Run Requests Failures Exit code
Base 1 1678 0 0
Base 2 1686 0 0
Base 3 1683 0 0
PR 1 1716 0 0
PR 2 1665 0 0
PR 3 1629 0 0
How to interpret this report

Regressed / Improved: a p95 regression needs >20% and >20 ms increase in the medians and at least two head samples versus the base median. Improvements use the inverse threshold. Within threshold means the change did not meet both thresholds.

Inconclusive: a within-revision p95 range >35% of its median and >20 ms is too noisy for a confident latency verdict.

Inconclusive latency comparisons are non-blocking: the check passes without claiming an improvement. Confirmed regressions and test/report errors fail the PR gate. Throughput is descriptive: paced users do not measure maximum capacity. This uncached public API test does not establish production health, browser performance or worker capacity. Separate runners can differ in hardware or host load; repetitions and noise checks reduce but cannot eliminate that uncertainty.

Full HTML/CSV reports and logs · attempt 1

@gitar-bot

gitar-bot Bot commented Oct 4, 2026 •

Copy link
Copy Markdown
CI failed: 1 infrastructure failure in the GitHub Advanced Security workflow due to an exceeded monthly model API quota.

Overview

One failure pattern was found across 1 analyzed log, entirely related to an infrastructure limitation with the AI model quota.

Failures

GitHub Advanced Security Quota Exceeded (confidence: high)

  • Type: infrastructure
  • Affected jobs: 111419028063
  • Related to change: no
  • Root cause: The job failed with a SessionModelError indicating that the monthly quota was exceeded (HTTP 402 / errorType: quota) when creating the Copilot SDK session.
  • Suggested fix: Wait for the account quota to reset or provision additional API credits/quota for the subscription.

Summary

  • Change-related failures: 0 failures
  • Infrastructure/flaky failures: 1 infrastructure failure due to quota exhaustion
  • Recommended action: Resolve the quota or billing limit on the external API subscription.
Code Review ✅ Approved

🔴 High risk · Migration 0022 changes catalog revision triggers and the required application schema.

Reuses scheduler catalog ranking within batch transactions to eliminate redundant catalog loads and rankings while maintaining correctness. Synthetic benchmarks show 95.6% CPU reduction (40.39s to 1.77s for 50 articles) with identical outputs; production validation recommended post-release. Migration 0022 updates topic revision invalidation and includes comprehensive regression tests. No issues found.

Review coverage

📋 Rules No rules evaluated

🧪 Functional validation Not enabled · Set up

Tip

Comment Gitar fix CI or enable auto-apply: gitar auto-apply:on

Options

Auto-apply is off → Gitar will not commit updates to this branch.
Display: compact → Counting what did not apply, without listing it.

Comment with these commands to change the behavior for this request:

Auto-apply Compact
gitar auto-apply:on         
gitar display:verbose         

Was this helpful? React with 👍 / 👎 | Gitar

@sonarqubecloud

sonarqubecloud Bot commented Oct 4, 2026

Copy link
Copy Markdown

@abhi1693
abhi1693 merged commit d4030c8 into master Oct 4, 2026
57 of 58 checks passed
@abhi1693
abhi1693 deleted the fix/scheduler-catalog-reuse branch October 4, 2026 10:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant