FOSSredder 0.5.0
Loading...
Searching...
No Matches
StatementImportJobSystem.cpp
Go to the documentation of this file.
1
5
7
11#include "ImportConstants.h"
12#include "core/jobs/JobSystem.h"
13#include "core/jobs/Scheduler.h"
14
15#include <exception>
16#include <filesystem>
17#include <mutex>
18#include <string_view>
19#include <unordered_map>
20#include <utility>
21
23
24namespace {
25
26inline constexpr std::string_view kImportServiceUnavailable =
27 "core::domain::Statement import service not available";
28inline constexpr std::string_view kUnknownError = "Unknown error";
29
30} // namespace
31
33public:
34 Impl(std::shared_ptr<IImportStatement> importService,
35 std::shared_ptr<core::jobs::JobSystem> jobSystem)
36 : importService(std::move(importService))
37 , jobSystem(std::move(jobSystem))
38 {
39 }
40
42 std::shared_ptr<core::domain::Statement> statement;
43 std::vector<draft::TransactionDraft> transactions;
44 std::map<std::string, std::vector<std::uint8_t>> artifacts;
45 };
46
48 {
49 std::lock_guard<std::mutex> lock(resultsMutex);
50 auto& entry = results[id];
51 entry.statement = std::move(result.data);
52 entry.transactions = std::move(result.transactions);
53 entry.artifacts = std::move(result.artifacts);
54 }
55
56 std::shared_ptr<IImportStatement> importService;
57 std::shared_ptr<core::jobs::JobSystem> jobSystem;
58 mutable std::mutex resultsMutex;
59 std::unordered_map<core::jobs::JobId, ImportJobResult> results;
60};
61
63 std::shared_ptr<IImportStatement> importService,
64 std::shared_ptr<core::ports::diagnostics::IErrorReporter> errorReporter,
65 std::size_t workers)
67 std::move(importService),
68 std::make_shared<core::jobs::JobSystem>(std::move(errorReporter), workers))
69{
70}
71
73 std::shared_ptr<IImportStatement> importService,
74 std::shared_ptr<core::jobs::JobSystem> jobSystem)
75 : impl_(std::make_unique<Impl>(std::move(importService), std::move(jobSystem)))
76{
77}
78
80
82
84
86{
87 if (!impl_->jobSystem) {
88 return {};
89 }
90
91 const auto id = impl_->jobSystem->submit();
92
93 impl_->jobSystem->scheduler().enqueue([this, id, spec]() {
94 impl_->jobSystem->start(id);
95
96 try {
97 if (!impl_->importService) {
98 impl_->jobSystem->fail(id, std::string(kImportServiceUnavailable));
99 return;
100 }
101
102 if (spec.sourcePath.empty() || !std::filesystem::exists(spec.sourcePath)) {
103 impl_->jobSystem->fail(id, std::string(constants::kErrorSourceMissing));
104 return;
105 }
106
107 if (spec.runRoot.empty()) {
108 impl_->jobSystem->fail(id, std::string(constants::kErrorRunRootMissing));
109 return;
110 }
111
112 const auto cancel = impl_->jobSystem->cancelFlag(id);
113 const auto pause = impl_->jobSystem->pauseFlag(id);
114 auto progressCallback = [this, id](double progress, const std::string& message) {
116 event.jobId = id;
117 event.kind = core::jobs::JobKind::Generic;
118 event.state = core::jobs::JobState::Running;
119 event.stage = core::jobs::JobStage::None;
120 event.progress = progress;
121 event.message = message;
122 impl_->jobSystem->publish(event);
123 };
124
125 ImportRequest importRequest{};
126 importRequest.sourcePath = spec.sourcePath;
127 importRequest.runRoot = spec.runRoot;
128 importRequest.runIdPrefix = spec.runIdPrefix;
129 importRequest.jobId = id;
130 importRequest.progressCallback = std::move(progressCallback);
131 importRequest.cancelFlag = cancel;
132 importRequest.pauseFlag = pause;
133 importRequest.scheduler = &impl_->jobSystem->scheduler();
134 importRequest.ocrLimiter = &impl_->jobSystem->slotLimiter();
135
136 auto result = impl_->importService->importStatement(importRequest);
137 if (!result.data) {
138 impl_->jobSystem->fail(id, std::string(constants::kErrorExtractionFailed));
139 return;
140 }
141
142 impl_->setResult(id, std::move(result));
143
144 if (cancel && cancel->load()) {
145 impl_->jobSystem->cancel(id);
146 return;
147 }
148
149 impl_->jobSystem->finish(id);
150 } catch (const std::exception& ex) {
151 impl_->jobSystem->fail(id, ex.what());
152 } catch (...) {
153 impl_->jobSystem->fail(id, std::string(kUnknownError));
154 }
155 });
156
157 return id;
158}
159
161 const core::jobs::JobId& id,
163{
164 return impl_->jobSystem ? impl_->jobSystem->subscribe(id, std::move(cb)) : 0;
165}
166
168{
169 if (impl_->jobSystem) impl_->jobSystem->unsubscribe(id, subId);
170}
171
173{
174 if (impl_->jobSystem) impl_->jobSystem->cancel(id);
175}
176
178{
179 if (impl_->jobSystem) impl_->jobSystem->pause(id);
180}
181
183{
184 if (impl_->jobSystem) impl_->jobSystem->resume(id);
185}
186
187std::optional<core::jobs::JobSnapshot> StatementImportJobSystem::snapshot(const core::jobs::JobId& id) const
188{
189 return impl_->jobSystem ? impl_->jobSystem->snapshot(id) : std::nullopt;
190}
191
192std::shared_ptr<core::domain::Statement> StatementImportJobSystem::statementResult(const core::jobs::JobId& id) const
193{
194 std::lock_guard<std::mutex> lock(impl_->resultsMutex);
195 const auto it = impl_->results.find(id);
196 return it == impl_->results.end() ? nullptr : it->second.statement;
197}
198
199std::vector<draft::TransactionDraft> StatementImportJobSystem::statementTransactions(const core::jobs::JobId& id) const
200{
201 std::lock_guard<std::mutex> lock(impl_->resultsMutex);
202 const auto it = impl_->results.find(id);
203 return it == impl_->results.end() ? std::vector<draft::TransactionDraft>{} : it->second.transactions;
204}
205
206std::map<std::string, std::vector<std::uint8_t>>
208{
209 std::lock_guard<std::mutex> lock(impl_->resultsMutex);
210 const auto it = impl_->results.find(id);
211 if (it == impl_->results.end()) return {};
212 auto out = std::move(it->second.artifacts);
213 it->second.artifacts.clear();
214 return out;
215}
216
218{
219 if (impl_->jobSystem) impl_->jobSystem->shutdown();
220}
221
222} // namespace core::application::importing
Declares the public statement import service interface and factory.
Defines private constants shared by core import orchestration.
Declares the generic job system facade.
Declares a bounded worker queue and a simple slot limiter for import tasks.
Declares asynchronous statement import job orchestration.
Declares the import execution request contract.
Declares the import execution result contract.
void setResult(const core::jobs::JobId &id, ImportResult result)
std::unordered_map< core::jobs::JobId, ImportJobResult > results
Impl(std::shared_ptr< IImportStatement > importService, std::shared_ptr< core::jobs::JobSystem > jobSystem)
void unsubscribe(const core::jobs::JobId &id, core::jobs::SubscriptionId subId)
std::map< std::string, std::vector< std::uint8_t > > takeStatementArtifacts(const core::jobs::JobId &id)
core::jobs::SubscriptionId subscribe(const core::jobs::JobId &id, core::jobs::JobEventCallback cb)
core::jobs::JobId startImportStatement(const ImportStatementJobSpec &spec)
std::optional< core::jobs::JobSnapshot > snapshot(const core::jobs::JobId &id) const
std::shared_ptr< core::domain::Statement > statementResult(const core::jobs::JobId &id) const
StatementImportJobSystem(std::shared_ptr< IImportStatement > importService, std::shared_ptr< core::ports::diagnostics::IErrorReporter > errorReporter, std::size_t workers=0)
std::vector< draft::TransactionDraft > statementTransactions(const core::jobs::JobId &id) const
constexpr std::string_view kErrorSourceMissing
constexpr std::string_view kErrorRunRootMissing
constexpr std::string_view kErrorExtractionFailed
std::uint64_t SubscriptionId
Identifier for a job event subscription.
Definition JobTypes.h:88
std::string JobId
Stable identifier for one tracked job.
Definition JobTypes.h:21
std::function< void(const JobEvent &)> JobEventCallback
Callback invoked for published job events.
Definition JobTypes.h:93
std::map< std::string, std::vector< std::uint8_t > > artifacts
std::shared_ptr< core::domain::Statement > data
std::vector< core::application::importing::draft::TransactionDraft > transactions
Event emitted when a job changes state or progress.
Definition JobTypes.h:52