@@ -62,7 +62,7 @@ use std::io::{BufRead, BufReader};
6262use std:: path:: { Path , PathBuf } ;
6363use std:: process:: { Command , Output , Stdio } ;
6464use std:: sync:: OnceLock ;
65- use std:: time:: Instant ;
65+ use std:: time:: { Duration , Instant } ;
6666use which:: which;
6767
6868/// Returns the remote server URL if running against a remote server.
@@ -1317,6 +1317,49 @@ log = "0.4"
13171317 ) ;
13181318 }
13191319
1320+ /// Asserts that a SQL query eventually produces the expected output.
1321+ ///
1322+ /// Use this only for read-only queries after operations that can briefly
1323+ /// leave the database worker unavailable, such as publishing an update.
1324+ pub fn assert_sql_eventually ( & self , query : & str , expected : & str ) {
1325+ let expected_normalized = normalize_whitespace ( expected) ;
1326+ let deadline = Instant :: now ( ) + Duration :: from_secs ( 10 ) ;
1327+ let mut last_actual = None ;
1328+ let mut last_error = None ;
1329+
1330+ while Instant :: now ( ) < deadline {
1331+ match self . sql ( query) {
1332+ Ok ( actual) => {
1333+ let actual_normalized = normalize_whitespace ( & actual) ;
1334+ if actual_normalized == expected_normalized {
1335+ return ;
1336+ }
1337+ last_actual = Some ( actual_normalized) ;
1338+ last_error = None ;
1339+ }
1340+ Err ( err) => {
1341+ last_error = Some ( err. to_string ( ) ) ;
1342+ }
1343+ }
1344+
1345+ std:: thread:: sleep ( Duration :: from_millis ( 200 ) ) ;
1346+ }
1347+
1348+ if let Some ( actual_normalized) = last_actual {
1349+ assert_eq ! (
1350+ actual_normalized, expected_normalized,
1351+ "SQL output mismatch for query after retry: {}\n \n Expected:\n {}\n \n Actual:\n {}" ,
1352+ query, expected_normalized, actual_normalized
1353+ ) ;
1354+ }
1355+
1356+ panic ! (
1357+ "SQL query failed after retry: {}\n \n Last error:\n {}" ,
1358+ query,
1359+ last_error. unwrap_or_else( || "no attempts completed" . to_string( ) )
1360+ ) ;
1361+ }
1362+
13201363 /// Fetches the last N log entries from the database.
13211364 pub fn logs ( & self , n : usize ) -> Result < Vec < String > > {
13221365 let records = self . log_records ( n) ?;
0 commit comments