Loading src/backend.cpp +4 −0 Original line number Diff line number Diff line Loading @@ -133,6 +133,10 @@ void authdb::AuthBackend::purge(){ _Api->purge(); } void authdb::AuthBackend::flushSync(){ _Api->flushSync(); } bool authdb::AuthBackend::clusterDataExists() const { return _Api->clusterDataExists(); } Loading src/backend.h +2 −0 Original line number Diff line number Diff line Loading @@ -76,6 +76,7 @@ namespace authdb{ virtual void newRevesion()=0; virtual void vacuum()=0; virtual void purge(){}; virtual void flushSync(){} virtual bool clusterDataExists() const { return false; } }; Loading Loading @@ -109,6 +110,7 @@ namespace authdb{ void vacuum(size_t &sizeBefore, size_t &sizeAfter); void purge(); void flushSync(); void lock(); void unlock(); Loading src/backends/cluster.cpp +26 −3 Original line number Diff line number Diff line Loading @@ -470,13 +470,27 @@ namespace authdb { _Dirty = false; } void ClusterBackend::flushSync() { // Synchronous push to cluster — ensures data is durably stored // before returning. Used after import to guarantee persistence. if (_Buffer.size() <= sizeof(AuthHeader)) return; auto entities = parseEntities(); std::set<EntityKey> keys; for (auto &[ek, data] : entities) keys.insert(ek); pushManifestSync(keys); // Update shared cache auto cache = getDomainCache(); cache->buffer = _Buffer; } ClusterBackend::ClusterBackend(const char *domain, size_t version, const char *filepath) : _Domain(domain), _Pos(0), _Dirty(false) { // Try the shared domain cache first — no network I/O needed. // This is critical: the constructor must NOT call pclient_->retrieve() // because the push_worker may hold pclient_->mutex_ for seconds, // blocking this constructor and causing HTTP timeouts. if (g_Cluster && g_Cluster->isRunning()) { auto cache = getDomainCache(); if (!cache->buffer.empty()) { Loading @@ -503,6 +517,15 @@ namespace authdb { _Buffer.resize(sizeof(AuthHeader)); std::memcpy(_Buffer.data(), &head, sizeof(AuthHeader)); _Dirty = false; // Eager fetch: if cluster data exists but nothing is cached yet, // load it now so end() returns the real size immediately. // fetchFromCluster() uses the read client (not the push client) // and does a one-time synchronous wait when the cache is empty. if (_ClusterDataExists.load()) { fetchFromCluster(); _Dirty = false; // fetch must never mark buffer dirty } } } Loading src/backends/cluster.h +1 −0 Original line number Diff line number Diff line Loading @@ -81,6 +81,7 @@ namespace authdb { void vacuum(); void purge(); void flushSync() override; bool clusterDataExists() const override { return _ClusterDataExists.load(); } Loading src/import.cpp +4 −0 Original line number Diff line number Diff line Loading @@ -112,6 +112,10 @@ namespace authdb { ++count; } // Ensure imported data is durably pushed to the cluster (synchronous) // before returning, so a restart won't lose the import. backend.flushSync(); return count; } }; Loading Loading
src/backend.cpp +4 −0 Original line number Diff line number Diff line Loading @@ -133,6 +133,10 @@ void authdb::AuthBackend::purge(){ _Api->purge(); } void authdb::AuthBackend::flushSync(){ _Api->flushSync(); } bool authdb::AuthBackend::clusterDataExists() const { return _Api->clusterDataExists(); } Loading
src/backend.h +2 −0 Original line number Diff line number Diff line Loading @@ -76,6 +76,7 @@ namespace authdb{ virtual void newRevesion()=0; virtual void vacuum()=0; virtual void purge(){}; virtual void flushSync(){} virtual bool clusterDataExists() const { return false; } }; Loading Loading @@ -109,6 +110,7 @@ namespace authdb{ void vacuum(size_t &sizeBefore, size_t &sizeAfter); void purge(); void flushSync(); void lock(); void unlock(); Loading
src/backends/cluster.cpp +26 −3 Original line number Diff line number Diff line Loading @@ -470,13 +470,27 @@ namespace authdb { _Dirty = false; } void ClusterBackend::flushSync() { // Synchronous push to cluster — ensures data is durably stored // before returning. Used after import to guarantee persistence. if (_Buffer.size() <= sizeof(AuthHeader)) return; auto entities = parseEntities(); std::set<EntityKey> keys; for (auto &[ek, data] : entities) keys.insert(ek); pushManifestSync(keys); // Update shared cache auto cache = getDomainCache(); cache->buffer = _Buffer; } ClusterBackend::ClusterBackend(const char *domain, size_t version, const char *filepath) : _Domain(domain), _Pos(0), _Dirty(false) { // Try the shared domain cache first — no network I/O needed. // This is critical: the constructor must NOT call pclient_->retrieve() // because the push_worker may hold pclient_->mutex_ for seconds, // blocking this constructor and causing HTTP timeouts. if (g_Cluster && g_Cluster->isRunning()) { auto cache = getDomainCache(); if (!cache->buffer.empty()) { Loading @@ -503,6 +517,15 @@ namespace authdb { _Buffer.resize(sizeof(AuthHeader)); std::memcpy(_Buffer.data(), &head, sizeof(AuthHeader)); _Dirty = false; // Eager fetch: if cluster data exists but nothing is cached yet, // load it now so end() returns the real size immediately. // fetchFromCluster() uses the read client (not the push client) // and does a one-time synchronous wait when the cache is empty. if (_ClusterDataExists.load()) { fetchFromCluster(); _Dirty = false; // fetch must never mark buffer dirty } } } Loading
src/backends/cluster.h +1 −0 Original line number Diff line number Diff line Loading @@ -81,6 +81,7 @@ namespace authdb { void vacuum(); void purge(); void flushSync() override; bool clusterDataExists() const override { return _ClusterDataExists.load(); } Loading
src/import.cpp +4 −0 Original line number Diff line number Diff line Loading @@ -112,6 +112,10 @@ namespace authdb { ++count; } // Ensure imported data is durably pushed to the cluster (synchronous) // before returning, so a restart won't lose the import. backend.flushSync(); return count; } }; Loading