Skip to content

Schedule poll notifications with Fedify tasks - #649

Merged
dahlia merged 1 commit into
fedify-dev:mainfrom
dahlia:refactor/poll-notifications-jobs
Oct 4, 2026
Merged

dahlia merged 1 commit into
fedify-dev:mainfrom
dahlia:refactor/poll-notifications-jobs

Conversation

@dahlia

@dahlia dahlia commented Oct 3, 2026 •

Copy link
Copy Markdown
Member

Poll expiry notifications now use the shared Fedify task queue. Tasks are scheduled after database commits and carry only the poll ID. Handlers lock and reload the poll before notifying, so expiry changes and repeated delivery cannot cause early notifications or inflate notification groups.

Recovery scans fill the gap between committing a poll or vote and enqueueing its task. They page through missing notifications, pause when the queue is busy, and advance past failures so the oldest poll cannot stall the backlog. This replaces the dedicated polling worker.

Fixes #639.

Summary by CodeRabbit

  • New Features
    • Poll expiry notifications are now scheduled and delivered through the shared task queue. Notifications reflect current poll expiry and recipients, with recovery for missed schedules and backlogs.
    • Notifications are scheduled when polls are created, when their expiry changes, and after a vote is recorded.
  • Bug Fixes
    • Vote and poll creation requests can still succeed if notification scheduling encounters an error.
    • Repeated expiry updates and concurrent processing avoid duplicate notifications.
  • Documentation
    • Updated worker setup guidance to explain where poll notification tasks run and how scheduling, recovery, and retries work.

Enqueue expiry tasks after committed poll creation, votes, and remote
expiry changes. Reload current recipients and expiry under database
locks so stale messages cannot notify early or inflate groups.

Recover missed dispatches in bounded cursor passes and remove the
polling worker. Cover retries, shutdown, backlog, and shared recovery
registration, and update the deployment guides.

Fixes fedify-dev#639

Assisted-by: Codex:gpt-6.1-sol
Assisted-by: Claude Code:claude-fable-5-1
@dahlia dahlia added this to the Hollo 0.10 milestone Oct 3, 2026
@dahlia dahlia self-assigned this Oct 3, 2026
@dahlia dahlia added the enhancement New feature or request label Oct 3, 2026
@coderabbitai

coderabbitai Bot commented Oct 3, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

🧰 Additional context used
📚 Code guidelines (1)
AGENTS.md — auto-discovered

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 552ce2a5-4fbb-407d-a02c-c6d1f95bd63c
📥 Commits

Reviewing files that changed from the base of the PR and between c73408f and fc4577a.

📒 Files selected for processing (26)
  • CHANGES.md
  • bin/server.ts
  • docs/src/content/docs/install/env.mdx
  • docs/src/content/docs/install/workers.mdx
  • docs/src/content/docs/ja/install/env.mdx
  • docs/src/content/docs/ja/install/workers.mdx
  • docs/src/content/docs/ko/install/env.mdx
  • docs/src/content/docs/ko/install/workers.mdx
  • docs/src/content/docs/zh-cn/install/env.mdx
  • docs/src/content/docs/zh-cn/install/workers.mdx
  • docs/src/content/docs/zh-tw/install/env.mdx
  • docs/src/content/docs/zh-tw/install/workers.mdx
  • src/api/v1/notifications.test.ts
  • src/api/v1/polls.test.ts
  • src/api/v1/polls.ts
  • src/api/v1/statuses.test.ts
  • src/api/v1/statuses.ts
  • src/api/v2/notifications.test.ts
  • src/federation/federation.ts
  • src/federation/post.test.ts
  • src/federation/post.ts
  • src/notification.test.ts
  • src/notification.ts
  • src/poll-notification-tasks.test.ts
  • src/poll-notification-tasks.ts
  • src/poll-notification-worker.ts
💤 Files with no reviewable changes (1)
  • src/poll-notification-worker.ts

Included review availability: This review used your included allowance. Your plan provides up to 2 included reviews per hour; 1 remain after this review.


📝 Walkthrough

Walkthrough

Poll-expiry notifications now use delayed tasks on the shared Fedify queue. Task handlers reload poll state and recipients, while bounded recovery scans schedule missing work. Poll creation, voting, and federation updates enqueue tasks, and worker configuration and documentation reflect the shared queue.

Changes

Poll expiry notifications

Layer / File(s) Summary
Reload poll state and create notifications
src/notification.ts, src/notification.test.ts, src/api/v1/notifications.test.ts, src/api/v2/notifications.test.ts
Notification creation accepts a database argument. The missing-notification query supports bounded cursor scans. Delivery reloads the poll and recipients in a transaction before creating notifications.
Schedule tasks and recover missed work
src/poll-notification-tasks.ts, src/poll-notification-tasks.test.ts, src/federation/federation.ts, bin/server.ts, src/poll-notification-worker.ts
Fedify tasks schedule delayed notifications and reschedule when expiry is still in the future. Recovery scans for missing notifications. Federation setup registers the tasks, and worker startup uses the shared abort signal instead of the separate polling worker.
Connect poll changes to scheduling
src/api/v1/polls.ts, src/api/v1/polls.test.ts, src/api/v1/statuses.ts, src/api/v1/statuses.test.ts, src/federation/post.ts, src/federation/post.test.ts
The voting API, status creation, and federation post persistence enqueue tasks. Federation persistence enqueues when a poll is new or its expiry changes. Tests cover enqueue timing and failure handling.
Document shared-queue operation
CHANGES.md, docs/src/content/docs/install/*, docs/src/content/docs/{ja,ko,zh-cn,zh-tw}/install/*
The changelog and installation documentation describe poll notification tasks, node placement, recovery, retries, shutdown, and upgrade requirements.

Priority: ⬇️ Low

Estimated code review effort: 4 (Complex) | ~60 minutes

Change: Bug fix

Sequence Diagram(s)

sequenceDiagram
  participant PollProducer
  participant enqueuePollNotification
  participant FedifyTaskQueue
  participant notifyExpiredPoll
  participant Database
  PollProducer->>enqueuePollNotification: poll ID and base URL
  enqueuePollNotification->>FedifyTaskQueue: dispatch poll task
  FedifyTaskQueue->>notifyExpiredPoll: run task with poll ID
  notifyExpiredPoll->>Database: reload poll, post, and recipients
  Database-->>notifyExpiredPoll: current expiry and local recipients
  notifyExpiredPoll->>FedifyTaskQueue: reschedule if expiry is in the future
  notifyExpiredPoll->>Database: create notifications if poll has expired
Loading

Merge Risk: ⚪ Minimal · up to fc457

No identified issue blocks merging the poll-notification task change after normal checks.

Security Architecture Review

Security architecture risk: 🟡 Moderate · up to fc457

Current-state reloads and database deduplication protect notification correctness. However, user-driven poll activity now feeds a queue shared with other background operations, without the recovery scanner’s admission check. Queue containment and rollback compatibility remain unresolved.

Retained concerns

  • Medium · security · inferred: Authenticated poll creation and successful votes now schedule shared-queue work without the recovery scanner’s ready-depth admission check. Early deliveries schedule replacement tasks, and notification deduplication does not limit enqueue requests. Compared with the former bounded dedicated scanner, this introduces a potential resource-exhaustion path affecting unrelated background workloads in the same installation. Backend coalescing, quotas, and the load required to cause starvation remain unverified.
Security review details

Security Blast Radius

  • inferred — The supported availability exposure extends across workloads and account owners sharing this installation’s task queue and worker capacity. Separate activity queues limit direct queue coupling to federation delivery; no cross-installation authority gain is established by this path.

Security Findings and Attack Paths

  • inferred — A user with write:statuses permission can create polls that trigger shared task scheduling. Successful votes add further scheduling requests, although repeated voting by the same account is rejected. Ready-depth gating applies to recovery rather than these direct producers, creating the inferred contention path; actual denial of service and backend duplicate retention were not verified.

Trust Boundaries and Controls

  • observed — The task validates a UUID poll ID and reloads database state instead of trusting enqueue-time recipients or expiry. Enqueue eligibility requires a local author or voter, and delivery derives local recipients again. The inspected notification handler performs database work rather than federation sends or caller-selected network requests.

Resilience and Maintainability Implications

  • observed — Database-level idempotency and transactional recipient creation contain duplicate delivery effects. Recovery repairs the commit-to-enqueue gap and interrupted or exhausted deliveries after expiry. These controls protect durable notification state but do not provide workload-specific queue isolation.

Hardening Proposals

  • proposed — Establish queue coalescing and quota behavior, then consider workload-specific admission limits or capacity reservations if poll traffic can starve unrelated work. Any scheduling coalescing must preserve replacement wakeups and durable recovery after failed dispatch.
  • proposed — Document and validate rollback handling for already-persisted poll tasks, including whether older workers reject, discard, or retain unknown task definitions. Keep the existing stop-old-nodes requirement explicit until compatibility is established.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 38.46% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 13 functions across 14 files. (11 skipped… Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: scheduling poll notifications with Fedify tasks.
Linked Issues check ✅ Passed Issue #639’s scheduling requirements are implemented. Poll creation, vote submission, and remote poll expiry changes dispatch tasks after commit; task payloads contain only the poll ID. The handler re…
Out of Scope Changes check ✅ Passed The changes stay within issue #639. The worker removal and startup changes replace the old poll-notification worker. Tests, changelog entries, and translated deployment documentation support the task-…
Full details: Docstring Coverage

Explanation

Docstring coverage is 38.46% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 13 functions across 14 files. (11 skipped: 11 unsupported.)

  • Fix all pre-merge checks with AI
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@dahlia
dahlia merged commit 4ba4fed into fedify-dev:main Oct 4, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Schedule poll notifications with Fedify background tasks

1 participant