ReUseX  0.0.5
3D Point Cloud Processing for Building Reuse
Loading...
Searching...
No Matches
JobRunner.hpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2026 Povl Filip Sonne-Frederiksen
2//
3// SPDX-License-Identifier: GPL-3.0-or-later
4
5#pragma once
6
7// In-process pipeline job runner for ONE project (#265, Phase 1).
8//
9// A FIFO queue of stage runs on a single worker thread, with a submit /
10// status / cancel surface and per-job progress events. Since phase S2 of the
11// ruxd multi-case spec it is a thin wrapper: a JobScheduler with one worker
12// and one JobQueue (JobScheduler.hpp). Use the scheduler directly to run
13// several projects' queues on one bounded worker pool — that is what ruxd
14// does — and this class where one project is all there is (the Qt client,
15// tests).
16//
17// PROGRESS: each job's stage reports through a core::ScopedProgressObserver
18// installed on the worker thread for that job, chained to whatever global
19// observer was installed (e.g. the rux CLI progress bar) — so progress is
20// per-job even when several schedulers or workers run stages at once.
21//
22// THREAD SAFETY: every public member is safe to call from any thread. The
23// ProjectDB instance used to execute a job is created and destroyed on the
24// worker thread and never escapes it — ProjectDB itself is not thread-safe.
25//
26// WRITER EXCLUSION: the runner also owns the project's *writer lock* (see
27// try_acquire_writer). The worker holds it for the whole execution of a stage,
28// so anything else that wants to write to the same `.rux` — the GUI's editor
29// endpoints, for instance — can take the same lock and be genuinely exclusive
30// with the pipeline rather than merely hoping sqlite sorts it out.
31
32#include "reusex/core/stages.hpp"
33#include "reusex/pipeline/job_types.hpp"
34#include "reusex/pipeline/stages.hpp"
35
36#include <chrono>
37#include <cstddef>
38#include <cstdint>
39#include <filesystem>
40#include <functional>
41#include <memory>
42#include <mutex>
43#include <optional>
44#include <string>
45#include <string_view>
46#include <vector>
47
48namespace reusex::pipeline {
49
63 size_t max_terminal_jobs = 256;
64};
65
85class JobRunner {
86 public:
90 explicit JobRunner(std::filesystem::path project,
92
94 JobRunner(std::filesystem::path project, StageExecutor executor,
95 JobRunnerOptions options);
96
99
100 JobRunner(const JobRunner &) = delete;
101 JobRunner &operator=(const JobRunner &) = delete;
102
104 const std::filesystem::path &project() const noexcept;
105
109 std::string submit(JobStage stage, std::string parameters = {});
110
116 bool cancel(std::string_view id);
117
124 std::optional<JobRecord> job(std::string_view id) const;
125
130 std::vector<JobRecord> jobs() const;
131
133 size_t queued_count() const;
134
136 bool is_busy() const;
137
140 void wait_idle();
141
160 [[nodiscard]] WriterLease
161 try_acquire_writer(std::chrono::milliseconds timeout);
162
164 size_t add_listener(JobListener listener);
165
167 void remove_listener(size_t token);
168
169 private:
170 class Impl;
171 std::unique_ptr<Impl> impl_;
172};
173
174} // namespace reusex::pipeline
size_t queued_count() const
Number of jobs still waiting to start.
std::string submit(JobStage stage, std::string parameters={})
Enqueue a stage run.
bool is_busy() const
True while a job is executing.
size_t add_listener(JobListener listener)
Register a listener. Returns a token for remove_listener().
void wait_idle()
Block until the queue is empty and no job is running.
JobRunner(const JobRunner &)=delete
JobRunner(std::filesystem::path project, StageExecutor executor, JobRunnerOptions options)
As above, with an explicit job-store policy.
const std::filesystem::path & project() const noexcept
The project every job of this runner targets.
~JobRunner()
Requests cancellation of anything in flight and joins the worker.
std::vector< JobRecord > jobs() const
Snapshot of every retained job, most recently submitted first.
void remove_listener(size_t token)
Unregister a listener. Safe to call with an unknown token.
JobRunner(std::filesystem::path project, StageExecutor executor=default_stage_executor())
WriterLease try_acquire_writer(std::chrono::milliseconds timeout)
Try to take the project's exclusive writer lock, giving up after timeout.
bool cancel(std::string_view id)
Request cancellation.
std::optional< JobRecord > job(std::string_view id) const
Snapshot of one job, or nullopt if the id is unknown or evicted.
JobRunner & operator=(const JobRunner &)=delete
std::function< void(const JobEvent &)> JobListener
Listener callback.
JobStage
A pipeline stage that can be executed as a job.
Definition stages.hpp:43
StageExecutor default_stage_executor()
The executor that actually runs the pipeline (a thin wrap of run_stage).
std::function< StageResult(const StageContext &)> StageExecutor
Stage execution strategy.
Definition stages.hpp:148
std::unique_lock< std::timed_mutex > WriterLease
Exclusive right to write to a runner's project.
Tuning knobs for the job store.
Definition JobRunner.hpp:51
size_t max_terminal_jobs
Terminal (succeeded/failed/cancelled) jobs retained before the oldest are dropped.
Definition JobRunner.hpp:63