summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Goodliffe <dan@randomdan.homeip.net>2026-04-10 20:22:35 +0100
committerDan Goodliffe <dan@randomdan.homeip.net>2026-04-10 20:22:35 +0100
commit72bfa9dd305258789b0d2e80f8af13962e5aac42 (patch)
tree4f4dd17921154452289107fae6b6358047f35bce
parent1e551e618a63c869fde6a4b327566b38696a5f45 (diff)
downloadwebstat-72bfa9dd305258789b0d2e80f8af13962e5aac42.tar.bz2
webstat-72bfa9dd305258789b0d2e80f8af13962e5aac42.tar.xz
webstat-72bfa9dd305258789b0d2e80f8af13962e5aac42.zip
Return path of parked lines log file from parkQueuedLogLines
Or the last errno on failure.
-rw-r--r--src/ingestor.cpp13
-rw-r--r--src/ingestor.hpp3
-rw-r--r--test/test-ingest.cpp34
3 files changed, 28 insertions, 22 deletions
diff --git a/src/ingestor.cpp b/src/ingestor.cpp
index c5cb8d8..0659f1f 100644
--- a/src/ingestor.cpp
+++ b/src/ingestor.cpp
@@ -275,11 +275,11 @@ namespace WebStat {
}
}
- void
+ std::expected<std::filesystem::path, int>
Ingestor::parkQueuedLogLines()
{
if (queuedLines.empty()) {
- return;
+ return std::unexpected(0);
}
const std::filesystem::path path {
settings.fallbackDir / std::format("parked-{}.short", crc32(queuedLines.front()))};
@@ -290,16 +290,19 @@ namespace WebStat {
}
if (fflush(parked.get()) == 0) {
queuedLines.clear();
- auto finalPath = auto {path}.replace_extension(".log");
+ auto finalPath = std::filesystem::path {path}.replace_extension(".log");
+ parked.reset();
if (rename(path.c_str(), finalPath.c_str()) == 0) {
- return;
+ return finalPath;
}
}
}
+ const int err = errno;
log(LOG_ERR, "Failed to park %zu queued lines:", queuedLines.size());
for (const auto & line : queuedLines) {
log(LOG_ERR, "\t%.*s", static_cast<int>(line.length()), line.data());
}
+ return std::unexpected(err);
}
void
@@ -334,7 +337,7 @@ namespace WebStat {
unsigned int count = 0;
for (auto pathIter = std::filesystem::directory_iterator {settings.fallbackDir};
pathIter != std::filesystem::directory_iterator {}; ++pathIter) {
- if (scn::scan<Crc32Value>(pathIter->path().filename().string(), "parked-{}.log")) {
+ if (scn::scan<std::string>(pathIter->path().filename().string(), "parked-{:[a-zA-Z0-9]}.log")) {
jobIngestParkedLines(pathIter->path());
count += 1;
}
diff --git a/src/ingestor.hpp b/src/ingestor.hpp
index fcddc92..b2e0fed 100644
--- a/src/ingestor.hpp
+++ b/src/ingestor.hpp
@@ -7,6 +7,7 @@
#include <connectionPool.h>
#include <connection_fwd.h>
#include <cstdio>
+#include <expected>
#include <flat_set>
#include <future>
#include <scn/scan.h>
@@ -54,7 +55,7 @@ namespace WebStat {
void ingestLog(std::FILE *);
void tryIngestQueuedLogLines();
void ingestLogLines(DB::Connection *, const LineBatch & lines);
- void parkQueuedLogLines();
+ std::expected<std::filesystem::path, int> parkQueuedLogLines();
void runJobsAsNeeded();
unsigned int jobIngestParkedLines();
diff --git a/test/test-ingest.cpp b/test/test-ingest.cpp
index 5fc8195..d399288 100644
--- a/test/test-ingest.cpp
+++ b/test/test-ingest.cpp
@@ -155,7 +155,6 @@ BOOST_DATA_TEST_CASE(CLFStringsBad,
constexpr std::string_view LOGLINE1
= R"LOG(git.randomdan.homeip.net 98.82.40.168 1755561576768318 GET "/repo/gentoobrowse-api/commit/gentoobrowse-api/unittests/fixtures/756569aa764177340726dd3d40b41d89b11b20c7/app-crypt/pdfcrack/Manifest" "?h=gentoobrowse-api-0.9.1&id=a2ed3fd30333721accd4b697bfcb6cc4165c7714" HTTP/1.1 200 1884 107791 "-" "Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; Amazonbot/0.1; +https://developer.amazon.com/support/amazonbot) Chrome/119.0.6045.214 Safari/537.36" "test/plain")LOG";
-constexpr std::string_view LOGLINE1_PARKED = "parked-237093379.log";
constexpr std::string_view LOGLINE2
= R"LOG(www.randomdan.homeip.net 43.128.84.166 1755561575973204 GET "/app-dicts/myspell-et/Manifest" "" HTTP/1.1 200 312 10369 "https://google.com" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36" "image/png")LOG";
@@ -298,11 +297,11 @@ BOOST_AUTO_TEST_CASE(ParkLogLine)
{
queuedLines.emplace_back(LOGLINE1);
queuedLines.emplace_back(LOGLINE2);
- parkQueuedLogLines();
- const auto path = settings.fallbackDir / LOGLINE1_PARKED;
- BOOST_TEST_INFO(path);
- BOOST_REQUIRE(std::filesystem::exists(path));
- BOOST_CHECK_EQUAL(std::filesystem::file_size(path), LOGLINE1.length() + LOGLINE2.length() + 4);
+ const auto path = parkQueuedLogLines();
+ BOOST_REQUIRE(path);
+ BOOST_TEST_INFO(*path);
+ BOOST_REQUIRE(std::filesystem::exists(*path));
+ BOOST_CHECK_EQUAL(std::filesystem::file_size(*path), LOGLINE1.length() + LOGLINE2.length() + 4);
}
BOOST_AUTO_TEST_CASE(ParkLogLineOnError, *boost::unit_test::depends_on("I/ParkLogLine"))
@@ -318,11 +317,12 @@ BOOST_AUTO_TEST_CASE(IngestParked, *boost::unit_test::depends_on("I/ParkLogLine"
{
queuedLines.emplace_back(LOGLINE1);
queuedLines.emplace_back(LOGLINE2);
- parkQueuedLogLines();
+ BOOST_REQUIRE(parkQueuedLogLines());
+ BOOST_CHECK(!std::filesystem::is_empty(settings.fallbackDir));
BOOST_REQUIRE(queuedLines.empty());
jobIngestParkedLines();
BOOST_CHECK_EQUAL(queuedLines.size(), 2);
- BOOST_CHECK(!std::filesystem::exists(settings.fallbackDir / LOGLINE1_PARKED));
+ BOOST_CHECK(std::filesystem::is_empty(settings.fallbackDir));
}
BOOST_AUTO_TEST_CASE(DefaultLaunchNoJobs)
@@ -338,21 +338,22 @@ BOOST_AUTO_TEST_CASE(IngestParkedJob,
const auto now = Job::LastRunTime::clock::now();
ingestParkedLines.lastRun = now - 1s;
queuedLines.emplace_back(LOGLINE1);
- parkQueuedLogLines();
+ const auto path = parkQueuedLogLines();
+ BOOST_REQUIRE(path);
BOOST_REQUIRE(queuedLines.empty());
- BOOST_REQUIRE(std::filesystem::exists(settings.fallbackDir / LOGLINE1_PARKED));
+ BOOST_REQUIRE(std::filesystem::exists(*path));
runJobsAsNeeded();
BOOST_REQUIRE(!ingestParkedLines.currentRun);
BOOST_CHECK(queuedLines.empty());
- BOOST_CHECK(std::filesystem::exists(settings.fallbackDir / LOGLINE1_PARKED));
+ BOOST_CHECK(std::filesystem::exists(*path));
BOOST_CHECK_EQUAL(ingestParkedLines.lastRun, now - 1s);
ingestParkedLines.lastRun = now - settings.freqIngestParkedLines + 2s;
runJobsAsNeeded();
BOOST_REQUIRE(!ingestParkedLines.currentRun);
BOOST_CHECK(queuedLines.empty());
- BOOST_CHECK(std::filesystem::exists(settings.fallbackDir / LOGLINE1_PARKED));
+ BOOST_CHECK(std::filesystem::exists(*path));
BOOST_CHECK_EQUAL(ingestParkedLines.lastRun, now - settings.freqIngestParkedLines + 2s);
ingestParkedLines.lastRun = now - settings.freqIngestParkedLines - 1s;
@@ -363,7 +364,7 @@ BOOST_AUTO_TEST_CASE(IngestParkedJob,
BOOST_REQUIRE(!ingestParkedLines.currentRun);
BOOST_CHECK_EQUAL(queuedLines.size(), 1);
BOOST_CHECK_GE(ingestParkedLines.lastRun, now);
- BOOST_CHECK(!std::filesystem::exists(settings.fallbackDir / LOGLINE1_PARKED));
+ BOOST_CHECK(!std::filesystem::exists(*path));
}
BOOST_AUTO_TEST_CASE(JobErrorRescheduler, *boost::unit_test::depends_on("I/IngestParkedJob"))
@@ -371,14 +372,15 @@ BOOST_AUTO_TEST_CASE(JobErrorRescheduler, *boost::unit_test::depends_on("I/Inges
const auto now = Job::LastRunTime::clock::now();
ingestParkedLines.lastRun = now - settings.freqIngestParkedLines - 1s;
queuedLines.emplace_back(LOGLINE1);
- parkQueuedLogLines();
- std::filesystem::permissions(settings.fallbackDir / LOGLINE1_PARKED, std::filesystem::perms::owner_write);
+ const auto path = parkQueuedLogLines();
+ BOOST_REQUIRE(path);
+ std::filesystem::permissions(*path, std::filesystem::perms::owner_write);
runJobsAsNeeded();
BOOST_REQUIRE(ingestParkedLines.currentRun);
ingestParkedLines.currentRun->wait();
runJobsAsNeeded();
BOOST_REQUIRE(!ingestParkedLines.currentRun);
- BOOST_CHECK(std::filesystem::exists(settings.fallbackDir / LOGLINE1_PARKED));
+ BOOST_CHECK(std::filesystem::exists(*path));
BOOST_CHECK_GE(ingestParkedLines.lastRun, now - (settings.freqIngestParkedLines / 2) - 1s);
BOOST_CHECK_LE(ingestParkedLines.lastRun, now - (settings.freqIngestParkedLines / 2) + 1s);
}