Commit d949b3b
feat: durable out-of-process job scheduling for file_processors (#6160)
## Summary
Inline providers run in the server's event loop today, so a single large
`file_processors.process_file` call blocks the whole server, and the
work is an
in-process closure that dies on restart.
This PR introduces **one substrate** that delivers both **process
isolation** and
**durable scheduling**: a job is an addressable record in a SQL-backed
queue that a
separate worker process leases by id. That simultaneously gives
non-blocking
execution (separate process, separate GIL) and survives restarts. The
engine is
generic; only a thin per-API adapter is provider-specific.
Scope is intentionally **file_processors only**. Migrating `batches` and
promoting
other inline APIs are deferred follow-ups.
## Design
New package `src/ogx/core/jobs/`:
- **`queue.py`** — `JobQueue` over `SqlStore` (the DB is the IPC
channel). Atomic
guarded-UPDATE leasing claims a job exclusively; `fail()` requeues until
`max_attempts`; `reclaim_stale()` returns expired leases to `scheduled`
on startup
(the durability/restart property).
- **`worker.py`** — `WorkerPool` spawns N processes (spawn context, own
GIL). Each
rebuilds the real provider impl and its dependencies from a
`ProviderDescriptor`,
then loops: lease → run method → complete/fail, heartbeating the lease.
- **`proxy.py`** — generic `JobBackedProxy` base (enqueue, blocking
run-and-wait,
get, cancel, list) plus a `WORKER_PROXY_FACTORIES` registry.
- **`file_processor_proxy.py`** — the only file-processor-specific code:
maps the
`FileProcessors` protocol onto the base, stages direct uploads into the
Files API
so payloads carry only a `file_id` (never bytes), and self-registers via
`register_worker_proxy(Api.file_processors, ...)`.
- **`dispatch.py` / `runtime.py` / `bootstrap.py`** — per-(api, method)
payload
(de)serialization, and process-global runtime construction wired into
the stack
lifecycle.
Wiring:
- `InlineProviderSpec` gains `execution_mode` (`"inline" | "worker"`),
default
`"inline"` so **no other API's topology changes**. The resolver returns
the
registered worker proxy instead of importing the impl in-process when
`execution_mode == "worker"`.
- All four `file_processors` specs (auto, pypdf, markitdown, docling)
are set to
worker mode — the problem is file size and blocking in general, not CPU
heaviness.
### Adding worker mode for another API later
Purely additive, no engine/resolver/worker changes: set `execution_mode:
worker` on
the spec, add a `dispatch.py` entry, write a ~15-line proxy adapter,
call
`register_worker_proxy(...)`.
## API changes
`file_processors` is `/v1alpha`, so no minimum deprecation window
applies.
- `POST /file-processors/process` is marked **deprecated** — it still
works and keeps
its signature, but now runs out-of-process via the job engine.
- New async endpoints: `POST /file-processors/jobs` (submit),
`GET /file-processors/jobs`, `GET /file-processors/jobs/{job_id}`,
`POST /file-processors/jobs/{job_id}/cancel`, with `ProcessFileJob` and
`ListProcessFileJobsResponse` models. OpenAPI specs regenerated.
## Test plan
Unit coverage for every layer of the substrate:
- `test_queue.py` — lease/complete/fail/retry/cancel/reclaim,
lease-expiry recovery
- `test_worker.py` — worker dispatch (complete and failure paths)
- `test_build_impl.py` — descriptor → real provider reconstruction (with
a dependency)
- `test_proxy.py` — proxy round-trip incl. the deprecated blocking
surface
- `test_resolver_worker_mode.py` — the resolver seam: a worker spec
mounts the proxy
and registers a reconstructable descriptor that captures dependencies
```bash
uv run --no-sync pytest tests/unit/core/jobs/ -q
```
```
25 passed
```
No regressions in the surrounding suites:
```bash
uv run --no-sync pytest tests/unit/core tests/unit/providers/files -q
```
```
347 passed (+ jobs)
```
## Out of scope (follow-ups)
- Streaming the upload to storage so large files never transit server
memory.
- Migrating `batches` onto this substrate.
- Off-box workers over HTTP (the queue boundary already makes this
reachable).
- Promoting other inline APIs to `execution_mode: worker`.
- End-to-end integration tests (real spawned-worker round-trip,
durability across
restart, non-blocking-latency proof).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Signed-off-by: Charlie Doern <cdoern@redhat.com>
Signed-off-by: Francisco Javier Arceo <farceo@redhat.com>
Co-authored-by: Francisco Javier Arceo <farceo@redhat.com>1 parent a84aa6b commit d949b3b
44 files changed
Lines changed: 4348 additions & 191 deletions
File tree
- client-sdks/stainless
- docs
- docs/providers/file_processors
- static
- src
- ogx_api
- file_processors
- internal
- types
- ogx
- core
- jobs
- storage/sqlstore
- providers/registry
- tests
- integration/file_processors
- unit
- core/jobs
- utils/sqlstore
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
3717 | 3717 | | |
3718 | 3718 | | |
3719 | 3719 | | |
3720 | | - | |
| 3720 | + | |
3721 | 3721 | | |
3722 | 3722 | | |
3723 | 3723 | | |
3724 | 3724 | | |
3725 | 3725 | | |
3726 | 3726 | | |
| 3727 | + | |
| 3728 | + | |
| 3729 | + | |
| 3730 | + | |
| 3731 | + | |
| 3732 | + | |
| 3733 | + | |
| 3734 | + | |
| 3735 | + | |
| 3736 | + | |
| 3737 | + | |
| 3738 | + | |
| 3739 | + | |
| 3740 | + | |
| 3741 | + | |
| 3742 | + | |
| 3743 | + | |
| 3744 | + | |
| 3745 | + | |
| 3746 | + | |
| 3747 | + | |
| 3748 | + | |
| 3749 | + | |
| 3750 | + | |
| 3751 | + | |
| 3752 | + | |
| 3753 | + | |
| 3754 | + | |
| 3755 | + | |
| 3756 | + | |
| 3757 | + | |
| 3758 | + | |
| 3759 | + | |
| 3760 | + | |
| 3761 | + | |
| 3762 | + | |
| 3763 | + | |
| 3764 | + | |
| 3765 | + | |
| 3766 | + | |
| 3767 | + | |
| 3768 | + | |
| 3769 | + | |
| 3770 | + | |
| 3771 | + | |
| 3772 | + | |
| 3773 | + | |
| 3774 | + | |
| 3775 | + | |
| 3776 | + | |
| 3777 | + | |
| 3778 | + | |
| 3779 | + | |
| 3780 | + | |
| 3781 | + | |
| 3782 | + | |
| 3783 | + | |
| 3784 | + | |
| 3785 | + | |
| 3786 | + | |
| 3787 | + | |
| 3788 | + | |
| 3789 | + | |
| 3790 | + | |
| 3791 | + | |
| 3792 | + | |
| 3793 | + | |
| 3794 | + | |
| 3795 | + | |
| 3796 | + | |
| 3797 | + | |
| 3798 | + | |
| 3799 | + | |
| 3800 | + | |
| 3801 | + | |
| 3802 | + | |
| 3803 | + | |
| 3804 | + | |
| 3805 | + | |
| 3806 | + | |
| 3807 | + | |
| 3808 | + | |
| 3809 | + | |
| 3810 | + | |
| 3811 | + | |
| 3812 | + | |
| 3813 | + | |
| 3814 | + | |
| 3815 | + | |
| 3816 | + | |
| 3817 | + | |
| 3818 | + | |
| 3819 | + | |
| 3820 | + | |
| 3821 | + | |
| 3822 | + | |
| 3823 | + | |
| 3824 | + | |
| 3825 | + | |
| 3826 | + | |
| 3827 | + | |
| 3828 | + | |
| 3829 | + | |
| 3830 | + | |
| 3831 | + | |
| 3832 | + | |
| 3833 | + | |
| 3834 | + | |
| 3835 | + | |
| 3836 | + | |
| 3837 | + | |
| 3838 | + | |
| 3839 | + | |
| 3840 | + | |
| 3841 | + | |
| 3842 | + | |
| 3843 | + | |
| 3844 | + | |
| 3845 | + | |
| 3846 | + | |
| 3847 | + | |
| 3848 | + | |
| 3849 | + | |
| 3850 | + | |
| 3851 | + | |
| 3852 | + | |
| 3853 | + | |
| 3854 | + | |
| 3855 | + | |
| 3856 | + | |
| 3857 | + | |
| 3858 | + | |
| 3859 | + | |
| 3860 | + | |
| 3861 | + | |
| 3862 | + | |
| 3863 | + | |
| 3864 | + | |
| 3865 | + | |
| 3866 | + | |
| 3867 | + | |
| 3868 | + | |
| 3869 | + | |
| 3870 | + | |
| 3871 | + | |
3727 | 3872 | | |
3728 | 3873 | | |
3729 | 3874 | | |
| |||
11547 | 11692 | | |
11548 | 11693 | | |
11549 | 11694 | | |
| 11695 | + | |
| 11696 | + | |
| 11697 | + | |
| 11698 | + | |
| 11699 | + | |
| 11700 | + | |
| 11701 | + | |
| 11702 | + | |
| 11703 | + | |
| 11704 | + | |
| 11705 | + | |
| 11706 | + | |
| 11707 | + | |
| 11708 | + | |
| 11709 | + | |
| 11710 | + | |
| 11711 | + | |
| 11712 | + | |
| 11713 | + | |
| 11714 | + | |
| 11715 | + | |
| 11716 | + | |
| 11717 | + | |
| 11718 | + | |
| 11719 | + | |
| 11720 | + | |
11550 | 11721 | | |
11551 | 11722 | | |
11552 | 11723 | | |
| |||
12728 | 12899 | | |
12729 | 12900 | | |
12730 | 12901 | | |
| 12902 | + | |
| 12903 | + | |
| 12904 | + | |
| 12905 | + | |
| 12906 | + | |
| 12907 | + | |
| 12908 | + | |
| 12909 | + | |
| 12910 | + | |
| 12911 | + | |
12731 | 12912 | | |
12732 | 12913 | | |
12733 | 12914 | | |
| |||
12768 | 12949 | | |
12769 | 12950 | | |
12770 | 12951 | | |
| 12952 | + | |
| 12953 | + | |
| 12954 | + | |
| 12955 | + | |
| 12956 | + | |
| 12957 | + | |
| 12958 | + | |
| 12959 | + | |
| 12960 | + | |
| 12961 | + | |
| 12962 | + | |
| 12963 | + | |
| 12964 | + | |
| 12965 | + | |
| 12966 | + | |
| 12967 | + | |
| 12968 | + | |
| 12969 | + | |
12771 | 12970 | | |
12772 | 12971 | | |
12773 | 12972 | | |
| |||
13634 | 13833 | | |
13635 | 13834 | | |
13636 | 13835 | | |
| 13836 | + | |
| 13837 | + | |
| 13838 | + | |
| 13839 | + | |
| 13840 | + | |
| 13841 | + | |
| 13842 | + | |
| 13843 | + | |
| 13844 | + | |
| 13845 | + | |
| 13846 | + | |
| 13847 | + | |
| 13848 | + | |
| 13849 | + | |
| 13850 | + | |
| 13851 | + | |
| 13852 | + | |
| 13853 | + | |
| 13854 | + | |
| 13855 | + | |
| 13856 | + | |
| 13857 | + | |
| 13858 | + | |
| 13859 | + | |
| 13860 | + | |
| 13861 | + | |
| 13862 | + | |
| 13863 | + | |
| 13864 | + | |
| 13865 | + | |
| 13866 | + | |
| 13867 | + | |
| 13868 | + | |
| 13869 | + | |
| 13870 | + | |
| 13871 | + | |
| 13872 | + | |
| 13873 | + | |
13637 | 13874 | | |
13638 | 13875 | | |
13639 | 13876 | | |
| |||
15048 | 15285 | | |
15049 | 15286 | | |
15050 | 15287 | | |
| 15288 | + | |
| 15289 | + | |
| 15290 | + | |
| 15291 | + | |
| 15292 | + | |
| 15293 | + | |
| 15294 | + | |
| 15295 | + | |
| 15296 | + | |
| 15297 | + | |
| 15298 | + | |
| 15299 | + | |
15051 | 15300 | | |
15052 | 15301 | | |
15053 | 15302 | | |
| |||
15787 | 16036 | | |
15788 | 16037 | | |
15789 | 16038 | | |
15790 | | - | |
15791 | | - | |
15792 | | - | |
15793 | | - | |
15794 | | - | |
15795 | | - | |
15796 | | - | |
15797 | | - | |
15798 | | - | |
15799 | | - | |
15800 | 16039 | | |
15801 | 16040 | | |
15802 | 16041 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
11 | 11 | | |
12 | 12 | | |
13 | 13 | | |
14 | | - | |
15 | | - | |
| 14 | + | |
| 15 | + | |
16 | 16 | | |
17 | 17 | | |
18 | 18 | | |
| |||
33 | 33 | | |
34 | 34 | | |
35 | 35 | | |
36 | | - | |
| 36 | + | |
37 | 37 | | |
38 | | - | |
39 | | - | |
40 | | - | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
41 | 41 | | |
42 | | - | |
43 | | - | |
44 | | - | |
45 | | - | |
46 | | - | |
47 | | - | |
48 | | - | |
49 | | - | |
50 | | - | |
51 | | - | |
52 | | - | |
| 42 | + | |
53 | 43 | | |
54 | 44 | | |
55 | 45 | | |
| |||
80 | 70 | | |
81 | 71 | | |
82 | 72 | | |
83 | | - | |
84 | | - | |
| 73 | + | |
| 74 | + | |
85 | 75 | | |
86 | 76 | | |
87 | 77 | | |
| |||
102 | 92 | | |
103 | 93 | | |
104 | 94 | | |
105 | | - | |
| 95 | + | |
106 | 96 | | |
107 | | - | |
108 | | - | |
109 | | - | |
110 | | - | |
111 | | - | |
112 | | - | |
113 | | - | |
114 | | - | |
115 | | - | |
116 | | - | |
117 | | - | |
118 | | - | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
119 | 100 | | |
120 | | - | |
121 | | - | |
| 101 | + | |
122 | 102 | | |
123 | 103 | | |
124 | 104 | | |
| |||
0 commit comments