Skip to content

Commit f0b7cd8

Browse files
committed
Simplify job reset mechanism and migration path
Major changes: - Remove reset() method; use delete() + refresh() instead - Jobs go from any state → (none) via delete, then → pending via refresh() - Shorten deprecation roadmap: clean break, no legacy support - Jobs tables created lazily on first populate(reserve_jobs=True) - Legacy tables with extra PK attributes: jobs table uses only FK-derived keys
1 parent 68d876d commit f0b7cd8

File tree

1 file changed

+47
-37
lines changed

1 file changed

+47
-37
lines changed

docs/src/design/autopopulate-2.0-spec.md

Lines changed: 47 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ class Analysis(dj.Computed):
7474
"""
7575
```
7676

77-
**Migration note**: Existing tables that violate this constraint will continue to work but cannot use the new jobs system. A deprecation warning will be issued.
77+
**Legacy table support**: Existing tables that introduce additional primary key attributes (beyond foreign keys) can still use the jobs system, but their jobs table will only include the foreign-key-derived primary key attributes. This means multiple target rows may map to a single job entry. A deprecation warning will be issued for such tables.
7878

7979
## Architecture
8080

@@ -148,16 +148,24 @@ Automatic transitions during `populate()`:
148148
149149
│ error()
150150
151+
┌───────────┐
152+
│ error │
153+
└───────────┘
154+
155+
│ delete
156+
151157
┌───────────┐ ┌──────────┐
152-
error │───▶│ pending │
158+
(none) │───▶│ pending │
153159
└───────────┘ └──────────┘
154-
reset()
160+
refresh()
155161
```
156162

163+
**Resetting jobs:** To reset a job (error or otherwise), simply delete it from the jobs table. The next `refresh()` will re-add it as `pending` if the key is still in `key_source`.
164+
157165
**Manual status control:**
158166
- `ignore` is set manually via `jobs.ignore(key)` and is not part of automatic transitions
159167
- Jobs with `status='ignore'` are skipped by `populate()` and `refresh()`
160-
- Use `jobs.reset()` to move `ignore` jobs back to `pending`
168+
- To reset an ignored job, delete it and call `refresh()`
161169

162170
## API Design
163171

@@ -223,19 +231,22 @@ class JobsTable(Table):
223231
def ignore(self, key: dict) -> None:
224232
"""
225233
Mark a job to be ignored (skipped during populate).
234+
235+
To reset an ignored job, delete it and call refresh().
226236
"""
227237
...
228238

229-
def reset(self, *restrictions, include_errors: bool = True) -> int:
239+
def delete(self, *restrictions) -> int:
230240
"""
231-
Reset jobs to pending status.
241+
Delete jobs matching restrictions.
232242
233-
Args:
234-
restrictions: Conditions to filter which jobs to reset
235-
include_errors: If True, also reset error jobs (default: True)
243+
Deleted jobs return to (none) state. Call refresh() to re-add
244+
them as pending if their keys are still in key_source.
245+
246+
This is the standard way to "reset" error or ignored jobs.
236247
237248
Returns:
238-
Number of jobs reset.
249+
Number of jobs deleted.
239250
"""
240251
...
241252

@@ -409,18 +420,21 @@ FilteredImage.alter()
409420
FilteredImage.jobs.refresh()
410421
```
411422

412-
### Migration from Current System
423+
### Lazy Table Creation
413424

414-
The schema-level `~jobs` table will be:
415-
1. **Maintained** for backward compatibility during transition
416-
2. **Deprecated** with warnings when `reserve_jobs=True` is used
417-
3. **Migration utility** provided to convert existing jobs to new format
425+
Jobs tables are created automatically on first use:
418426

419427
```python
420-
# Migration utility
421-
schema.migrate_jobs() # Migrates ~jobs entries to per-table jobs tables
428+
# First call to populate with reserve_jobs=True creates the jobs table
429+
FilteredImage.populate(reserve_jobs=True)
430+
# Creates ~filtered_image__jobs if it doesn't exist, then populates
431+
432+
# Alternatively, explicitly create/refresh the jobs table
433+
FilteredImage.jobs.refresh()
422434
```
423435

436+
The jobs table is created with the appropriate primary key structure matching the target table's foreign-key-derived attributes.
437+
424438
### Race Condition Handling
425439

426440
Job reservation uses database-level locking to prevent race conditions:
@@ -447,16 +461,17 @@ WHERE <primary_key_match>;
447461
COMMIT;
448462
```
449463

450-
### Stale Job Detection
464+
### Stale Reserved Job Detection
451465

452466
Reserved jobs that have been running too long may indicate crashed workers:
453467

454468
```python
455469
# Find potentially stale jobs (reserved > 1 hour ago)
456470
stale = MyTable.jobs & 'status="reserved"' & 'reserved_time < NOW() - INTERVAL 1 HOUR'
457471

458-
# Reset stale jobs to pending
459-
MyTable.jobs.reset(stale)
472+
# Delete stale jobs and re-add as pending
473+
stale.delete()
474+
MyTable.jobs.refresh()
460475
```
461476

462477
## Configuration Options
@@ -518,11 +533,14 @@ errors = FilteredImage.jobs.errors.fetch(as_dict=True)
518533
for err in errors:
519534
print(f"Key: {err['subject_id']}, Error: {err['error_message']}")
520535

521-
# Reset specific errors after fixing the issue
522-
FilteredImage.jobs.reset('subject_id=42')
536+
# Delete specific error jobs after fixing the issue
537+
(FilteredImage.jobs & 'subject_id=42').delete()
523538

524-
# Reset all errors
525-
FilteredImage.jobs.reset(include_errors=True)
539+
# Delete all error jobs
540+
FilteredImage.jobs.errors.delete()
541+
542+
# Re-add deleted jobs as pending (if keys still in key_source)
543+
FilteredImage.jobs.refresh()
526544
```
527545

528546
### Dashboard Queries
@@ -556,21 +574,13 @@ for jt in schema.jobs:
556574

557575
## Backward Compatibility
558576

559-
### Deprecation Path
560-
561-
1. **Phase 1 (Current Release)**:
562-
- New jobs tables created alongside existing `~jobs`
563-
- `reserve_jobs=True` uses new system by default
564-
- `reserve_jobs='legacy'` uses old system
565-
- Deprecation warning when using legacy system
577+
### Migration
566578

567-
2. **Phase 2 (Next Release)**:
568-
- Legacy `~jobs` table no longer updated
569-
- `reserve_jobs='legacy'` removed
570-
- Migration utility provided
579+
This is a major release. The legacy schema-level `~jobs` table is replaced by per-table jobs tables:
571580

572-
3. **Phase 3 (Future Release)**:
573-
- Legacy `~jobs` table dropped on schema upgrade
581+
- **Legacy `~jobs` table**: No longer used; can be dropped manually if present
582+
- **New jobs tables**: Created automatically on first `populate(reserve_jobs=True)` call
583+
- **No parallel support**: Teams should migrate cleanly to the new system
574584

575585
### API Compatibility
576586

0 commit comments

Comments
 (0)