Skip to content

Commit 049366b

Browse files
Edward AlmondEdward Almond
authored andcommitted
Implement S3 pagination in persistent storage
- Same fix as ephemeral storage: decode continuation token, skip keys, return proper is_truncated and next_continuation_token
1 parent d14d250 commit 049366b

1 file changed

Lines changed: 30 additions & 3 deletions

File tree

ruststack-s3/src/storage/persistent.rs

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
33
use super::traits::*;
44
use async_trait::async_trait;
5+
use base64::{engine::general_purpose::STANDARD as BASE64, Engine};
56
use bytes::Bytes;
67
use chrono::Utc;
78
use md5::{Digest, Md5};
@@ -289,13 +290,22 @@ impl ObjectStorage for PersistentStorage {
289290
bucket: &str,
290291
prefix: Option<&str>,
291292
delimiter: Option<&str>,
292-
_continuation_token: Option<&str>,
293+
continuation_token: Option<&str>,
293294
max_keys: i32,
294295
) -> Result<ListObjectsResult, StorageError> {
295296
let conn = self.conn.lock();
296297
let prefix = prefix.unwrap_or("");
297298
let max_keys = max_keys as usize;
298299

300+
let mut skip_key: Option<String> = None;
301+
if let Some(token) = continuation_token {
302+
if let Ok(decoded) = BASE64.decode(token) {
303+
if let Ok(key) = String::from_utf8(decoded) {
304+
skip_key = Some(key);
305+
}
306+
}
307+
}
308+
299309
let mut stmt = conn
300310
.prepare(
301311
"SELECT key, etag, size, last_modified, storage_class FROM objects WHERE bucket = ?1 AND key LIKE ?2",
@@ -320,9 +330,18 @@ impl ObjectStorage for PersistentStorage {
320330

321331
let mut objects = Vec::new();
322332
let mut common_prefixes = std::collections::HashSet::new();
333+
let mut last_key: Option<String> = None;
334+
let mut has_more = false;
323335

324336
for row in rows.flatten() {
325337
let key = &row.key;
338+
339+
if let Some(ref skip) = skip_key {
340+
if key <= skip {
341+
continue;
342+
}
343+
}
344+
326345
let suffix = &key[prefix.len()..];
327346

328347
if let Some(delim) = delimiter {
@@ -334,19 +353,27 @@ impl ObjectStorage for PersistentStorage {
334353
}
335354

336355
if objects.len() >= max_keys {
356+
has_more = true;
337357
break;
338358
}
339359

360+
last_key = Some(key.clone());
340361
objects.push(row);
341362
}
342363

343364
objects.sort_by(|a, b| a.key.cmp(&b.key));
344365

366+
let next_token = if has_more {
367+
last_key.map(|k| BASE64.encode(k.as_bytes()))
368+
} else {
369+
None
370+
};
371+
345372
Ok(ListObjectsResult {
346373
objects,
347374
common_prefixes: common_prefixes.into_iter().collect(),
348-
is_truncated: false,
349-
next_continuation_token: None,
375+
is_truncated: has_more,
376+
next_continuation_token: next_token,
350377
})
351378
}
352379

0 commit comments

Comments
 (0)