libstore: use monotonic clock for SQLITE_BUSY warnings
Using time_t meant a warning could be printed arbitrarily soon depending on when the second rolled over relative to when the SQLite transaction was attempted. Change-Id: I93401aea65f90e37cd450a293c4dd4d64fba7628
This commit is contained in:
@@ -278,11 +278,11 @@ void SQLiteTxn::Rollback::operator()(sqlite3 * db)
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
static std::chrono::milliseconds handleSQLiteBusyCommon(const SQLiteBusy & e, time_t & nextWarning)
|
||||
static std::chrono::milliseconds handleSQLiteBusyCommon(const SQLiteBusy & e, std::chrono::time_point<std::chrono::steady_clock> & nextWarning)
|
||||
{
|
||||
time_t now = time(0);
|
||||
auto now = std::chrono::steady_clock::now();
|
||||
if (now > nextWarning) {
|
||||
nextWarning = now + 10;
|
||||
nextWarning = now + std::chrono::seconds(10);
|
||||
logWarning({
|
||||
.msg = HintFmt(e.what())
|
||||
});
|
||||
@@ -297,12 +297,12 @@ static std::chrono::milliseconds handleSQLiteBusyCommon(const SQLiteBusy & e, ti
|
||||
return std::chrono::milliseconds { uniform_dist(generator) };
|
||||
}
|
||||
|
||||
void handleSQLiteBusy(const SQLiteBusy & e, time_t & nextWarning)
|
||||
void handleSQLiteBusy(const SQLiteBusy & e, std::chrono::time_point<std::chrono::steady_clock> & nextWarning)
|
||||
{
|
||||
std::this_thread::sleep_for(handleSQLiteBusyCommon(e, nextWarning));
|
||||
}
|
||||
|
||||
kj::Promise<Result<void>> handleSQLiteBusyAsync(const SQLiteBusy & e, time_t & nextWarning)
|
||||
kj::Promise<Result<void>> handleSQLiteBusyAsync(const SQLiteBusy & e, std::chrono::time_point<std::chrono::steady_clock> & nextWarning)
|
||||
try {
|
||||
std::chrono::milliseconds delay_ms = handleSQLiteBusyCommon(e, nextWarning);
|
||||
co_await AIO().provider.getTimer().afterDelay(delay_ms.count() * kj::MILLISECONDS);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
///@file
|
||||
|
||||
#include <chrono>
|
||||
#include <kj/async.h>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
@@ -190,8 +191,8 @@ protected:
|
||||
|
||||
MakeError(SQLiteBusy, SQLiteError);
|
||||
|
||||
void handleSQLiteBusy(const SQLiteBusy & e, time_t & nextWarning);
|
||||
kj::Promise<Result<void>> handleSQLiteBusyAsync(const SQLiteBusy & e, time_t & nextWarning);
|
||||
void handleSQLiteBusy(const SQLiteBusy & e, std::chrono::time_point<std::chrono::steady_clock> & nextWarning);
|
||||
kj::Promise<Result<void>> handleSQLiteBusyAsync(const SQLiteBusy & e, std::chrono::time_point<std::chrono::steady_clock> & nextWarning);
|
||||
|
||||
/**
|
||||
* Convenience function for retrying a SQLite transaction when the
|
||||
@@ -200,10 +201,10 @@ kj::Promise<Result<void>> handleSQLiteBusyAsync(const SQLiteBusy & e, time_t & n
|
||||
template<typename F>
|
||||
auto retrySQLite(F fun)
|
||||
{
|
||||
time_t nextWarning = time(0) + 1;
|
||||
auto nextWarning = std::chrono::steady_clock::now() + std::chrono::seconds(1);
|
||||
|
||||
if constexpr (requires (F f) { []<typename T>(kj::Promise<Result<T>>){}(f()); }) {
|
||||
return [](time_t nextWarning, F fun) -> decltype(fun()) {
|
||||
return [](std::chrono::time_point<std::chrono::steady_clock> nextWarning, F fun) -> decltype(fun()) {
|
||||
while (true) {
|
||||
kj::Promise<Result<void>> handleBusy{nullptr};
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user