11use reqwest:: Client ;
22use serde:: Deserialize ;
3- use std:: { collections:: HashMap , error:: Error } ;
3+ use std:: { collections:: HashMap , error:: Error , time :: Duration } ;
44
55use crate :: {
66 sqlite:: { SQLite3 , Value } ,
@@ -51,12 +51,6 @@ pub async fn execute_sql_and_params(
5151) -> Result < RemoteSqliteResponse , Box < dyn Error > > {
5252 let mut query_request = serde_json:: Map :: new ( ) ;
5353
54- if let Some ( b) = baton {
55- query_request. insert ( "baton" . to_string ( ) , serde_json:: json!( b) ) ;
56- }
57-
58- let can_keep_open = !( baton. is_some ( ) && sql. contains ( "COMMIT" ) ) ;
59-
6054 let mut json_array: Vec < serde_json:: Value > = Vec :: new ( ) ;
6155
6256 json_array. push ( serde_json:: json!( {
@@ -67,7 +61,9 @@ pub async fn execute_sql_and_params(
6761 }
6862 } ) ) ;
6963
70- if !can_keep_open {
64+ if db. has_began_transaction ( ) {
65+ query_request. insert ( "baton" . to_string ( ) , serde_json:: json!( baton) ) ;
66+ } else {
7167 json_array. push ( serde_json:: json!( {
7268 "type" : "close"
7369 } ) ) ;
@@ -122,55 +118,107 @@ async fn send_sql_request(
122118 Ok ( parsed)
123119}
124120
125- async fn send_remote_request (
121+ pub async fn send_remote_request (
126122 client : & Client ,
127123 turso_config : & TursoConfig ,
128124 path : & str ,
129125 request : serde_json:: Value ,
130126) -> Result < serde_json:: Value , Box < dyn Error > > {
131- let response = client
132- . post ( format ! ( "https://{}/{}" , turso_config. db_url, path) )
133- . header ( "Content-Type" , "application/json" )
134- . header ( "Authorization" , format ! ( "Bearer {}" , turso_config. db_token) )
135- . json ( & request)
136- . send ( )
137- . await ?;
127+ const MAX_ATTEMPTS : usize = 5 ;
128+ let mut last_error = String :: new ( ) ;
129+
130+ for attempt in 1 ..=MAX_ATTEMPTS {
131+ if cfg ! ( debug_assertions) {
132+ println ! (
133+ "Attempt {}: Sending request to {}" ,
134+ attempt, turso_config. db_url
135+ ) ;
136+ }
138137
139- let status = response. status ( ) ;
140- let response_text = response. text ( ) . await ?;
138+ let resp = client
139+ . post ( format ! ( "https://{}/{}" , turso_config. db_url, path) )
140+ . header ( "Content-Type" , "application/json" )
141+ . header ( "Authorization" , format ! ( "Bearer {}" , turso_config. db_token) )
142+ . json ( & request)
143+ . send ( )
144+ . await ;
145+
146+ let resp = match resp {
147+ Ok ( r) => r,
148+ Err ( e) => {
149+ last_error = format ! ( "Request failed: {}" , e) ;
150+ if attempt < MAX_ATTEMPTS {
151+ tokio:: time:: sleep ( Duration :: from_millis ( 100 ) ) . await ;
152+ continue ;
153+ } else {
154+ return Err ( last_error. into ( ) ) ;
155+ }
156+ }
157+ } ;
158+
159+ let status = resp. status ( ) ;
160+ let text = match resp. text ( ) . await {
161+ Ok ( t) => t,
162+ Err ( e) => {
163+ last_error = format ! ( "Failed to read response body: {}" , e) ;
164+ if attempt < MAX_ATTEMPTS {
165+ tokio:: time:: sleep ( Duration :: from_millis ( 100 ) ) . await ;
166+ continue ;
167+ } else {
168+ return Err ( last_error. into ( ) ) ;
169+ }
170+ }
171+ } ;
141172
142- if cfg ! ( debug_assertions) {
143- println ! ( "Received Response: {}\n " , & response_text ) ;
144- }
173+ if cfg ! ( debug_assertions) {
174+ println ! ( "Response received : {}" , text ) ;
175+ }
145176
146- if !status. is_success ( ) {
147- if let Ok ( error_body) = serde_json:: from_str :: < serde_json:: Value > ( & response_text) {
148- if let Some ( error_message) = error_body. get ( "error" ) . and_then ( |e| e. as_str ( ) ) {
149- return Err ( error_message. into ( ) ) ;
177+ if !status. is_success ( ) {
178+ if let Ok ( err_json) = serde_json:: from_str :: < serde_json:: Value > ( & text) {
179+ if let Some ( msg) = err_json. get ( "error" ) . and_then ( |v| v. as_str ( ) ) {
180+ last_error = format ! ( "API error: {}" , msg) ;
181+ } else {
182+ last_error = format ! ( "HTTP error {}: {}" , status, text) ;
183+ }
184+ } else {
185+ last_error = format ! ( "HTTP error {} with invalid JSON: {}" , status, text) ;
150186 }
151- }
152- return Err ( format ! ( "LibSqlite3_Turso Error: {}" , response_text) . into ( ) ) ;
153- }
154187
155- let parsed_response = serde_json:: from_str ( & response_text) ;
156- if parsed_response. is_err ( ) {
157- return Err ( format ! ( "Failed to parse response: {}" , parsed_response. unwrap_err( ) ) . into ( ) ) ;
158- }
188+ if attempt < MAX_ATTEMPTS {
189+ tokio:: time:: sleep ( Duration :: from_millis ( 100 ) ) . await ;
190+ continue ;
191+ } else {
192+ return Err ( last_error. into ( ) ) ;
193+ }
194+ }
159195
160- let parsed_response: serde_json:: Value = parsed_response. unwrap ( ) ;
161- if let Some ( results) = parsed_response. get ( "results" ) . and_then ( |r| r. as_array ( ) ) {
162- for result in results {
163- if let Some ( error) = result
164- . get ( "error" )
165- . and_then ( |e| e. get ( "message" ) )
166- . and_then ( |m| m. as_str ( ) )
167- {
168- return Err ( error. into ( ) ) ;
196+ let parsed: serde_json:: Value = match serde_json:: from_str ( & text) {
197+ Ok ( v) => v,
198+ Err ( e) => return Err ( format ! ( "Failed to parse JSON: {}" , e) . into ( ) ) ,
199+ } ;
200+
201+ // Check for embedded DB errors
202+ if let Some ( results) = parsed. get ( "results" ) . and_then ( |r| r. as_array ( ) ) {
203+ for result in results {
204+ if let Some ( msg) = result
205+ . get ( "error" )
206+ . and_then ( |e| e. get ( "message" ) )
207+ . and_then ( |m| m. as_str ( ) )
208+ {
209+ return Err ( msg. to_string ( ) . into ( ) ) ;
210+ }
169211 }
170212 }
213+
214+ return Ok ( parsed) ;
171215 }
172216
173- Ok ( parsed_response)
217+ Err ( format ! (
218+ "Failed to get successful response after {} attempts: {}" ,
219+ MAX_ATTEMPTS , last_error
220+ )
221+ . into ( ) )
174222}
175223
176224pub fn convert_params_to_json ( params : & HashMap < i32 , Value > ) -> Vec < serde_json:: Value > {
0 commit comments