@@ -177,6 +177,10 @@ class SqliteKv: private SqliteDatabase::ResetListener {
177177 // first write.
178178
179179 void beforeSqliteReset () override ;
180+
181+ // Helper function that rolls back a multi-put statement and swallows any exceptions that may
182+ // occur during the rollback.
183+ void rollbackMultiPut (Initialized& stmts, WriteOptions options);
180184};
181185
182186// Iterator over list results.
@@ -272,20 +276,13 @@ void SqliteKv::put(ArrayOfKeyValuePair& pairs, WriteOptions options) {
272276 // general structure can be shared somehow?
273277 auto & stmts = ensureInitialized (options.allowUnconfirmed );
274278 stmts.stmtMultiPutSavepoint .run ({.allowUnconfirmed = options.allowUnconfirmed });
275- for (const auto & pair: pairs) {
276- try {
279+
280+ {
281+ // If any of the puts throw an exception, rollback the transaction and re-throw the exception
282+ // from the put that failed.
283+ KJ_ON_SCOPE_FAILURE (rollbackMultiPut (stmts, options));
284+ for (const auto & pair: pairs) {
277285 put (pair.key , pair.value , {.allowUnconfirmed = options.allowUnconfirmed });
278- } catch (...) {
279- try {
280- // This should be rare, so we don't prepare a statement for it.
281- stmts.db .run ({.regulator = stmts.regulator , .allowUnconfirmed = options.allowUnconfirmed },
282- kj::str (" ROLLBACK TO _cf_put_multiple_savepoint" ));
283- stmts.stmtMultiPutRelease .run ({.allowUnconfirmed = options.allowUnconfirmed });
284- } catch (...) {
285- auto e = kj::getCaughtExceptionAsKj ();
286- KJ_LOG (WARNING, " silencing exception encountered while rolling back multi-put" , e);
287- }
288- throw ;
289286 }
290287 }
291288 stmts.stmtMultiPutRelease .run ({.allowUnconfirmed = options.allowUnconfirmed });
0 commit comments