Restore a rocks database from object storage
9
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 138 lines 3.9 kB view raw
1//! Restore a [rocks backup](https://github.com/facebook/rocksdb/wiki/How-to-backup-RocksDB) 2//! from object storage 3//! 4//! ```rust,no_run 5//! use eat_rocks::{public_bucket, restore}; 6//! # async fn example() -> Result<(), eat_rocks::Error> { 7//! let store = public_bucket("https://constellation.t3.storage.dev")?; 8//! restore(store, "", "/tmp/constellation-db", Default::default()).await?; 9//! # Ok(()) 10//! # } 11//! ``` 12//! 13//! the `public_bucket` function (`easy` feature, enabled by default) works with 14//! s3-compatible stores (like tigris) which are configured for public read access. 15//! 16//! you can use any [`ObjectStore`](object_store::ObjectStore) to restore from pretty much any backend (S3, GCS, Azure, local filesystem, ...) 17 18pub mod meta; 19pub mod restore; 20 21pub use meta::{BackupFile, BackupMeta}; 22pub use restore::{DEFAULT_CONCURRENCY, RestoreOptions, fetch_meta, list_backup_ids, restore}; 23 24use std::io; 25use std::path::PathBuf; 26use std::string::FromUtf8Error; 27 28use object_store::path::Path as StorePath; 29 30/// Build an unsigned s3-compatible object store 31/// 32/// `endpoint` should include the bucket as a subdomain for virtual-hosted style: 33/// 34/// ```text 35/// https://constellation.t3.storage.dev 36/// ``` 37/// 38/// you can construct your own [`object_store::ObjectStore`] implementation directly for more control. 39#[cfg(feature = "easy")] 40pub fn public_bucket( 41 endpoint: &str, 42) -> Result<std::sync::Arc<dyn object_store::ObjectStore>, Error> { 43 use object_store::aws::AmazonS3Builder; 44 use std::sync::Arc; 45 46 let store = AmazonS3Builder::new() 47 .with_endpoint(endpoint) 48 .with_bucket_name("_") 49 .with_skip_signature(true) 50 .with_allow_http(true) 51 .with_virtual_hosted_style_request(true) 52 .build() 53 .map_err(|e| Error::ObjectStoreBuild { 54 endpoint: endpoint.to_string(), 55 source: e, 56 })?; 57 58 Ok(Arc::new(store)) 59} 60 61/// Errors that can occur during backup discovery, metadata parsing, or restore. 62#[derive(Debug, thiserror::Error)] 63pub enum Error { 64 #[cfg(feature = "easy")] 65 #[error("failed to build object store")] 66 ObjectStoreBuild { 67 endpoint: String, 68 #[source] 69 source: object_store::Error, 70 }, 71 72 #[error("failed to list objects under {prefix:?}")] 73 List { 74 prefix: StorePath, 75 #[source] 76 source: object_store::Error, 77 }, 78 79 #[error("failed to fetch {key:?}")] 80 Fetch { 81 key: StorePath, 82 #[source] 83 source: object_store::Error, 84 }, 85 86 #[error("meta file for backup {backup_id} is not valid UTF-8")] 87 MetaEncoding { 88 backup_id: u64, 89 #[source] 90 source: FromUtf8Error, 91 }, 92 93 #[error("failed to parse meta file for backup {backup_id}")] 94 MetaParse { 95 backup_id: u64, 96 #[source] 97 source: meta::ParseError, 98 }, 99 100 #[error("no backups found")] 101 NoBackups, 102 103 #[error("backup contains {count} excluded file(s) (unsupported)")] 104 ExcludedFiles { count: usize }, 105 106 #[error("backup path has unrecognized prefix: {0:?}")] 107 UnrecognizedPathPrefix(String), 108 109 #[error("shared_checksum filename missing underscore: {0:?}")] 110 SharedChecksumNoUnderscore(String), 111 112 #[error("shared_checksum filename missing extension: {0:?}")] 113 SharedChecksumNoExtension(String), 114 115 #[error("private/ path has too few components: {0:?}")] 116 PrivatePathTooShort(String), 117 118 #[error("size mismatch on {path}: expected {expected} bytes, got {actual}")] 119 SizeMismatch { 120 path: String, 121 expected: u64, 122 actual: u64, 123 }, 124 125 #[error("crc32c mismatch on {path}: expected {expected:#010x}, got {actual:#010x}")] 126 ChecksumMismatch { 127 path: String, 128 expected: u32, 129 actual: u32, 130 }, 131 132 #[error("{}: {source}", path.display())] 133 Io { 134 path: PathBuf, 135 #[source] 136 source: io::Error, 137 }, 138}