Skip to content

fix: resolve race condition in compound trigger evaluation#7

Open
tomerqodo wants to merge 2 commits into
codex_full_base_fix_resolve_race_condition_in_compound_trigger_evaluation_pr7from
codex_full_head_fix_resolve_race_condition_in_compound_trigger_evaluation_pr7
Open

fix: resolve race condition in compound trigger evaluation#7
tomerqodo wants to merge 2 commits into
codex_full_base_fix_resolve_race_condition_in_compound_trigger_evaluation_pr7from
codex_full_head_fix_resolve_race_condition_in_compound_trigger_evaluation_pr7

Conversation

@tomerqodo

Copy link
Copy Markdown

Benchmark PR from agentic-review-benchmarks#7

desertaxle and others added 2 commits January 25, 2026 12:10
Fixes two race conditions in compound trigger evaluation:

1. **Never-firing race** (transactional): When two child triggers fire
   concurrently in separate transactions, each only sees its own
   uncommitted insert due to READ COMMITTED isolation. Neither sees
   enough firings to trigger the parent.

   Fix: Use PostgreSQL advisory locks to serialize concurrent evaluations
   for the same compound trigger.

2. **Double-firing race** (autocommit): When both transactions see all
   firings, both delete and both fire the parent.

   Fix: Use DELETE ... RETURNING to make clearing a claim operation.
   Only the worker that successfully deletes the expected firings
   proceeds; others bail out.

Based on the fix in PrefectHQ/nebula#10716.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

import prefect.types._datetime
from prefect._internal.retries import retry_async_fn
from prefect.logging import get_logger

P1 Badge Remove unused get_logger import per repo rules

After switching to logging.getLogger, get_logger is now unused, which violates the repo-root AGENTS.md rule “Unused Imports Must Be Automatically Removed” and will likely trip ruff/unused-import checks. Since this was introduced by the change, the import should be removed or the previous logger pattern restored.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +38 to +42
if dialect.name == "postgresql":
# Use the trigger's UUID as the lock key
# pg_advisory_xact_lock takes a bigint, so we use the UUID's int representation
# truncated to fit (collision is extremely unlikely and benign)
lock_key = hash(str(trigger.id)) % (2**63)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Use a stable advisory-lock key across processes

The lock key uses hash(str(trigger.id)), but Python’s string hash is randomized per process, so different workers will compute different keys for the same trigger ID. In Postgres this means concurrent evaluations on separate processes won’t serialize on the same advisory lock, so the race condition can still occur. This is only a problem when multiple processes evaluate the same composite trigger concurrently, but that’s the case the lock is meant to fix. A stable key (e.g., trigger.id.int truncated to 63 bits) avoids this.

Useful? React with 👍 / 👎.

Comment on lines +71 to +73
import logging

logger: "logging.Logger" = get_logger(__name__)
logger = logging.getLogger(__name__)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Restore standard logger initialization pattern

Repo-root AGENTS.md requires the pattern logger: "logging.Logger" = get_logger("module_name"). This change replaces it with logging.getLogger(__name__) and removes the type annotation, which violates the logging standard in this repo and undermines consistent logger configuration/type safety. Please revert to the prescribed get_logger + annotated pattern.

Useful? React with 👍 / 👎.

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.

2 participants