FOSSredder 0.5.0
Loading...
Searching...
No Matches
ImportStrategySupport.cpp
Go to the documentation of this file.
1
5
7
8#include "ImportConstants.h"
10#include "core/jobs/Scheduler.h"
12
13#include <chrono>
14#include <future>
15#include <nlohmann/json.hpp>
16#include <thread>
17#include <utility>
18
20
21namespace {
22
23constexpr auto kPausePollInterval = std::chrono::milliseconds(50);
24
25void waitWhilePaused(const ImportRequest& req)
26{
27 while (req.pauseFlag && req.pauseFlag->load()) {
28 if (req.cancelFlag && req.cancelFlag->load()) return;
29 std::this_thread::sleep_for(kPausePollInterval);
30 }
31}
32
33}
34
36 const ImportRequest& req,
37 std::shared_ptr<core::ports::diagnostics::IErrorReporter> errorReporter)
38 : localScheduler(constants::kLocalSchedulerWorkers,
39 constants::kLocalSchedulerQueueCapacity,
40 std::move(errorReporter))
41 , localOcrLimiter(constants::kLocalOcrSlots)
44{
45}
46
47void ensureDirectoryExists(const std::filesystem::path& path,
49 const char* origin)
50{
51 try {
52 std::filesystem::create_directories(path);
53 } catch (...) {
54 core::errors::reportException(errorReporter, core::errors::ErrorSeverity::Warning, origin, std::current_exception());
55 }
56}
57
60{
61 return [&](double progress, const std::string& phase) {
62 if (!req.progressCallback) return;
63 waitWhilePaused(req);
64
65 try {
66 req.progressCallback(progress, phase);
67 } catch (...) {
70 "core::import::DefaultImportStatementStrategy::progressCallback",
71 std::current_exception());
72 }
73 };
74}
75
77{
79 request.pdfPath = std::filesystem::path(req.sourcePath);
80 request.dpi = constants::kRenderDpi;
81 request.outputDir = std::filesystem::path();
83 request.filePrefix = std::string(constants::kPopplerRenderPrefix);
84 request.cancelFlag = req.cancelFlag;
85 return request;
86}
87
89 const ImportRequest& req)
90{
92 request.pdfPath = renderRequest.pdfPath;
93 request.dpi = renderRequest.dpi;
94 request.outputDir = std::filesystem::path();
96 request.filePrefix = std::string(constants::kPopplerExtractPrefix);
97 request.cancelFlag = req.cancelFlag;
98 return request;
99}
100
101std::vector<internal::PageWork> collectPageWork(const ImportRequest& req,
104 const std::shared_ptr<core::ports::document_image_processing::IDocumentImageProcessor>& documentImageProcessor,
105 const std::shared_ptr<core::ports::text_recognition::ITextRecognizer>& tesseract,
106 SchedulerResources& resources,
107 const internal::ProgressReporter& report,
109 ImportResult& out,
110 std::mutex& artifactsMutex)
111{
112 const size_t totalPages = std::max(renderResult.images.size(), renderResult.imageBytes.size());
113 static constexpr size_t unitsPerPage = constants::kUnitsPerPage;
114 const size_t totalUnits = std::max<size_t>(1, totalPages * unitsPerPage);
115
116 std::atomic<size_t> doneUnits{0};
117 std::vector<internal::PageWork> pages(totalPages);
118 std::vector<std::future<internal::PageWork>> futures;
119 futures.reserve(totalPages);
120
121 for (size_t pageIndex = 0; pageIndex < totalPages; ++pageIndex) {
122 waitWhilePaused(req);
123 if (req.cancelFlag && req.cancelFlag->load()) break;
124
125 auto promise = std::make_shared<std::promise<internal::PageWork>>();
126 futures.push_back(promise->get_future());
127
128 resources.scheduler->enqueue([&, pageIndex, promise]() mutable {
129 promise->set_value(internal::processImportPage(pageIndex,
130 totalPages,
131 req,
132 renderResult,
133 extractResult,
134 documentImageProcessor,
135 tesseract,
136 resources.ocrLimiter,
137 report,
138 doneUnits,
139 totalUnits,
140 errorReporter,
141 out,
142 artifactsMutex));
143 });
144 }
145
146 for (auto& future : futures) {
147 try {
148 auto pageWork = future.get();
149 if (pageWork.pageIndex < pages.size()) pages[pageWork.pageIndex] = std::move(pageWork);
150 } catch (...) {
151 core::errors::reportException(errorReporter,
153 "core::import::DefaultImportStatementStrategy::pageFutureGet",
154 std::current_exception());
155 }
156 }
157
158 return pages;
159}
160
162 const ImportRequest& req,
163 const std::vector<internal::PageWork>& pages,
164 size_t totalPages,
165 const internal::FinalizeStats& finalizeStats,
166 const ImportRunTimings& timings,
168{
169 try {
170 nlohmann::json metrics;
171 metrics[constants::metrics::kJobId] = req.jobId;
173 metrics[constants::metrics::kPagesTotal] = totalPages;
180 metrics[constants::metrics::kOcrSecondsSum] = finalizeStats.sumOcrSec;
181 metrics[constants::metrics::kOcrWordsTotal] = finalizeStats.totalOcrWords;
182 metrics[constants::metrics::kTotalSeconds] = std::chrono::duration<double>(ImportClock::now() - timings.startedAt).count();
183
184 auto& pageArray = metrics[constants::metrics::kPages];
185 pageArray = nlohmann::json::array();
186 for (const auto& page : pages) {
187 nlohmann::json pageJson;
188 pageJson[constants::metrics::kIndex] = page.pageIndex;
189 pageJson[constants::metrics::kHasTable] = page.hasTable;
190 pageJson[constants::metrics::kTotalSeconds] = page.totalSec;
191 pageJson[constants::metrics::kOcrSecondsSum] = page.ocrSec;
192 pageJson[constants::metrics::kOcrWords] = page.ocrWords;
193 pageArray.push_back(std::move(pageJson));
194 }
195
196 const auto serialized = metrics.dump(2);
198 std::vector<uint8_t>(serialized.begin(), serialized.end());
199 } catch (...) {
200 core::errors::reportException(errorReporter,
202 "core::import::DefaultImportStatementStrategy::metricsArtifact",
203 std::current_exception());
204 }
205}
206
207}
Provides shared helpers for reporting structured errors and exceptions.
Defines private constants shared by core import orchestration.
Declares private support types and helpers for the default import strategy.
Declares a bounded worker queue and a simple slot limiter for import tasks.
Declares private unique identifier helpers for transient import/job artifacts.
void enqueue(Task t)
Enqueue a task, blocking when the queue is full.
Definition Scheduler.cpp:85
Port for reporting structured diagnostic error events.
constexpr std::string_view kPopplerExtractPrefix
constexpr std::string_view kMetricsArtifactName
constexpr std::string_view kPopplerRenderPrefix
PageWork processImportPage(size_t pageIndex, size_t totalPages, const ImportRequest &req, const poppler::RenderResult &renderRes, const poppler::ExtractResult &extractRes, const std::shared_ptr< core::ports::document_image_processing::IDocumentImageProcessor > &documentImageProcessor, const std::shared_ptr< core::ports::text_recognition::ITextRecognizer > &tesseract, core::jobs::SlotLimiter *ocrLimiter, const ProgressReporter &report, std::atomic< size_t > &doneUnits, size_t totalUnits, core::ports::diagnostics::IErrorReporter *errorReporter, ImportResult &out, std::mutex &artifactsMutex)
std::function< void(double, const std::string &)> ProgressReporter
core::ports::pdf_rendering::RenderRequest makeRenderRequest(const ImportRequest &req)
std::vector< internal::PageWork > collectPageWork(const ImportRequest &req, const core::ports::pdf_rendering::RenderResult &renderResult, const core::ports::pdf_rendering::ExtractResult &extractResult, const std::shared_ptr< core::ports::document_image_processing::IDocumentImageProcessor > &documentImageProcessor, const std::shared_ptr< core::ports::text_recognition::ITextRecognizer > &tesseract, SchedulerResources &resources, const internal::ProgressReporter &report, core::ports::diagnostics::IErrorReporter *errorReporter, ImportResult &out, std::mutex &artifactsMutex)
internal::ProgressReporter makeProgressReporter(const ImportRequest &req, core::ports::diagnostics::IErrorReporter *errorReporter)
void ensureDirectoryExists(const std::filesystem::path &path, core::ports::diagnostics::IErrorReporter *errorReporter, const char *origin)
core::ports::pdf_rendering::ExtractRequest makeExtractRequest(const core::ports::pdf_rendering::RenderRequest &renderRequest, const ImportRequest &req)
void attachMetricsArtifact(ImportResult &out, const ImportRequest &req, const std::vector< internal::PageWork > &pages, size_t totalPages, const internal::FinalizeStats &finalizeStats, const ImportRunTimings &timings, core::ports::diagnostics::IErrorReporter *errorReporter)
void reportException(core::ports::diagnostics::IErrorReporter *reporter, ErrorSeverity severity, const char *origin, std::exception_ptr exception)
Report an exception through the reporter's default exception handling.
std::string makeTransientId()
Generates a transient unique identifier for import and job artifacts.
std::function< void(double, const std::string &)> progressCallback
std::map< std::string, std::vector< std::uint8_t > > artifacts
SchedulerResources(const ImportRequest &req, std::shared_ptr< core::ports::diagnostics::IErrorReporter > errorReporter)
std::shared_ptr< std::atomic< bool > > cancelFlag
std::shared_ptr< std::atomic< bool > > cancelFlag
std::vector< std::vector< uint8_t > > imageBytes
std::vector< std::filesystem::path > images