Phinhas214 opened a new issue, #75830:
URL: https://github.com/apache/airflow/issues/75830

   ### Under which category would you file this issue?
   
   Airflow Core
   
   ### Apache Airflow version
   
   3.4.0
   
   ### What happened and how to reproduce it?
   
   ### Issue Description
   
   Airflow allows one active backfill per Dag. Concurrent `POST 
/api/v2/backfills` requests for the same Dag can create more than one. Related: 
#68699 (same setup), #68705.
   
   `_create_backfill` counts active backfills (`num_active`) without a lock, 
then inserts the `Backfill` row. Two requests can both count 0 before either 
one commits. Both get HTTP 200.
   
   Only the first backfill gets Dag runs. The later ones have one 
`backfill_dag_run` row per date with `exception_reason = 'in flight'` and no 
Dag runs. The user sees success for a backfill that will never run anything.
   
   ### How to reproduce 
   Steps:
   1. Use the Dag from #68699 (`@daily`, 2020-01-01 to 2022-12-31, 1096 runs).
   2. Send N concurrent `POST /api/v2/backfills` for that Dag with the same 
date range.
   3. Count active backfills:
      `SELECT id FROM backfill WHERE dag_id = 'test_backfill_bug' AND 
completed_at IS NULL;`
   
   My results on main went like this. (one "round" = N concurrent requests 
after deleting all backfills):
   
   | Requests per round | Rounds | Active backfills per round |
   |---|---|---|
   | 10 | 5 | 1, 1, 1, 1, 1 |
   | 20 | 4 | 2, 3, 1, 3 |
   | 100 | 1 | 3 |
   
   Example (20 requests): backfill 28 is active with 1096 Dag runs. Backfill 29 
is active with 1096 `in flight` rows and 0 Dag runs.
   
   The race is in main today. #68705 replaces the early `session.commit()` with 
a flush, so the window becomes the whole run creation and the race gets easier 
to hit.
   
   (With 20 or more requests, some requests also return HTTP 500. These are 
SQLAlchemy `QueuePool` timeouts after 30 s with the default pool size (5 + 10 
overflow). I think that is a separate load limit, not this bug.)
   
   ### What you think should happen instead?
   
   ### What you think should happen instead?
   
   One request gets HTTP 200. All other requests get HTTP 409 
(`AlreadyRunningBackfill`), until that backfill completes.
   
   
   
   
   ### Operating System
   
   MacOS
   
   ### Deployment
   
   Docker-Compose
   
   ### Apache Airflow Provider(s)
   
   _No response_
   
   ### Versions of Apache Airflow Providers
   
   _No response_
   
   ### Official Helm Chart version
   
   _No response_
   
   ### Kubernetes Version
   
   _No response_
   
   ### Helm Chart configuration
   
   _No response_
   
   ### Docker Image customizations
   
   _No response_
   
   ### Anything else?
   
   ### Options for a guard
   
   1. **Row lock:** lock the `DagModel` row with `with_row_locks` before the 
`num_active` count. Works on PostgreSQL and MySQL 8. Does nothing on SQLite (no 
`FOR UPDATE`) or when `[scheduler] use_row_level_locking = False`. While the 
lock is held, the scheduler skips this Dag (`skip_locked`).
   2. **Partial unique index** on `backfill(dag_id) WHERE completed_at IS 
NULL`. Works on PostgreSQL and SQLite. MySQL has no partial indexes, so it 
needs a different design there. Needs a migration that handles existing 
duplicates.
   3. **SQLite only:** count again after the insert. On SQLite the second 
writer waits for the first one's lock, so the second count can see the first 
row. Not tested yet.
   
   ### Question for maintainers
   
   Do you prefer an application-level guard (row lock on `DagModel`, plus 
option 3 for SQLite) or a database constraint (partial unique index, with a 
different design for MySQL)?
   
   I am working on a fix.
   
   ### Are you willing to submit PR?
   
   - [x] Yes I am willing to submit a PR!
   
   ### Code of Conduct
   
   - [x] I agree to follow this project's [Code of 
Conduct](https://github.com/apache/airflow/blob/main/CODE_OF_CONDUCT.md)
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to