Skip to content

Commit 1bc2cb2

Browse files
author
Piotr Jastrzebski
committed
Support redirects in sync
Signed-off-by: Piotr Jastrzebski <[email protected]>
1 parent 40c272d commit 1bc2cb2

File tree

1 file changed

+27
-2
lines changed

1 file changed

+27
-2
lines changed

libsql/src/sync.rs

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,10 @@ pub enum SyncError {
5454
InvalidPushFrameNoHigh(u32, u32),
5555
#[error("failed to pull frame: status={0}, error={1}")]
5656
PullFrame(StatusCode, String),
57+
#[error("failed to get location header for redirect: {0}")]
58+
RedirectHeader(http::header::ToStrError),
59+
#[error("redirect response with no location header")]
60+
NoRedirectLocationHeader,
5761
}
5862

5963
impl SyncError {
@@ -194,7 +198,7 @@ impl SyncContext {
194198
Ok(durable_frame_num)
195199
}
196200

197-
async fn push_with_retry(&self, uri: String, body: Bytes, max_retries: usize) -> Result<(u32, u32)> {
201+
async fn push_with_retry(&self, mut uri: String, body: Bytes, max_retries: usize) -> Result<(u32, u32)> {
198202
let mut nr_retries = 0;
199203
loop {
200204
let mut req = http::Request::post(uri.clone());
@@ -243,6 +247,17 @@ impl SyncContext {
243247
return Ok((generation as u32, max_frame_no as u32));
244248
}
245249

250+
if res.status().is_redirection() {
251+
uri = match res.headers().get(hyper::header::LOCATION) {
252+
Some(loc) => loc.to_str().map_err(SyncError::RedirectHeader)?.to_string(),
253+
None => return Err(SyncError::NoRedirectLocationHeader.into()),
254+
};
255+
if nr_retries == 0 {
256+
nr_retries += 1;
257+
continue;
258+
}
259+
}
260+
246261
// If we've retried too many times or the error is not a server error,
247262
// return the error.
248263
if nr_retries > max_retries || !res.status().is_server_error() {
@@ -263,7 +278,7 @@ impl SyncContext {
263278
}
264279
}
265280

266-
async fn pull_with_retry(&self, uri: String, max_retries: usize) -> Result<PullResult> {
281+
async fn pull_with_retry(&self, mut uri: String, max_retries: usize) -> Result<PullResult> {
267282
let mut nr_retries = 0;
268283
loop {
269284
let mut req = http::Request::builder().method("GET").uri(uri.clone());
@@ -308,6 +323,16 @@ impl SyncContext {
308323
.ok_or_else(|| SyncError::JsonValue(generation.clone()))?;
309324
return Ok(PullResult::EndOfGeneration { max_generation: generation as u32 });
310325
}
326+
if res.status().is_redirection() {
327+
uri = match res.headers().get(hyper::header::LOCATION) {
328+
Some(loc) => loc.to_str().map_err(SyncError::RedirectHeader)?.to_string(),
329+
None => return Err(SyncError::NoRedirectLocationHeader.into()),
330+
};
331+
if nr_retries == 0 {
332+
nr_retries += 1;
333+
continue;
334+
}
335+
}
311336
// If we've retried too many times or the error is not a server error,
312337
// return the error.
313338
if nr_retries > max_retries || !res.status().is_server_error() {

0 commit comments

Comments
 (0)