@@ -162,8 +162,15 @@ void Database::OnSaveGame(ISaveGame* pSaveGame)
162162 std::lock_guard lock (m_mutex);
163163 if (!m_saveCache.empty ())
164164 {
165- BatchOperation (*m_db, m_saveCache, newSave);
166- LogInfo (" Data saved: %d entries" , m_saveCache.size ());
165+ if (const int successCount = BatchOperation (*m_db, m_saveCache, newSave);
166+ successCount == m_saveCache.size ())
167+ {
168+ LogInfo (" Data saved: %d entries" , m_saveCache.size ());
169+ }
170+ else
171+ {
172+ LogError (" Save data error: %d/%d entries saved" , successCount, m_saveCache.size ());
173+ }
167174 }
168175 }
169176 catch (const std::exception& e)
@@ -181,9 +188,12 @@ void Database::OnPostUpdate(float /*fDeltaTime*/)
181188 std::lock_guard lock (m_mutex);
182189 if (!m_globalDirty) return ;
183190 if (const auto now = steady_clock::now (); now - m_lastSaveTime < SAVE_INTERVAL) return ;
191+
192+ int successCount = 0 ;
193+
184194 try
185195 {
186- ExecuteTransaction ([this ]( SQLite::Database& db)
196+ ExecuteTransaction ([this , &successCount]( const SQLite::Database& db)
187197 {
188198 SQLite::Statement clearStmt (db, " DELETE FROM Store WHERE savefile = ''" );
189199 clearStmt.exec ();
@@ -201,12 +211,20 @@ void Database::OnPostUpdate(float /*fDeltaTime*/)
201211 stmt.bind (3 , *val);
202212 stmt.exec ();
203213 stmt.reset ();
214+ successCount++;
204215 }
205216 }
206217 });
207218 m_globalDirty = false ;
208219 m_lastSaveTime = steady_clock::now ();
209- LogInfo (" Global data saved: %d entries" , m_globalCache.size ());
220+ if (successCount == m_globalCache.size ())
221+ {
222+ LogInfo (" Global data saved: %d entries" , m_globalCache.size ());
223+ }
224+ else
225+ {
226+ LogError (" Global save failed: %d/%d entries saved" , successCount, m_globalCache.size ());
227+ }
210228 }
211229 catch (const std::exception& e)
212230 {
@@ -221,7 +239,7 @@ void Database::ExecuteTransaction(const std::function<void(SQLite::Database&)>&
221239 transaction.commit ();
222240}
223241
224- void Database::BatchOperation (SQLite::Database& db, const Cache& cache, const std::string& savefile)
242+ int Database::BatchOperation (SQLite::Database& db, const Cache& cache, const std::string& savefile)
225243{
226244 static constexpr auto UPSERT_SQL = R"sql(
227245 INSERT INTO Store (key, savefile, type, value, updated_at)
@@ -235,6 +253,8 @@ void Database::BatchOperation(SQLite::Database& db, const Cache& cache, const st
235253 SQLite::Statement stmt (db, UPSERT_SQL);
236254 SQLite::Transaction transaction (db);
237255
256+ int count = 0 ;
257+
238258 for (const auto & [k, v] : cache)
239259 {
240260 if (auto val = SerializeAnyValue (v))
@@ -246,8 +266,10 @@ void Database::BatchOperation(SQLite::Database& db, const Cache& cache, const st
246266 stmt.exec ();
247267 stmt.reset ();
248268 }
269+ count++;
249270 }
250271 transaction.commit ();
272+ return count;
251273}
252274
253275std::optional<ScriptAnyValue> Database::ParseAnyValue (const int type, const std::string& value)
@@ -341,7 +363,7 @@ int Database::Dump(IFunctionHandler* pH)
341363
342364 dumpCache (m_globalCache, " [Global Data]" );
343365 std::ostringstream oss;
344- oss << " [Save Data For : " << (m_currentSaveGame.empty () ? " No active save file" : m_currentSaveGame) <<" ]" ;
366+ oss << " [Save Data For : " << (m_currentSaveGame.empty () ? " No active save file" : m_currentSaveGame) << " ]" ;
345367 dumpCache (m_saveCache, oss.str ());
346368 return pH->EndFunction ();
347369}
0 commit comments