1use shardline_fsck::run_fsck_with_stores;
2use shardline_index::{LocalIndexStore, LocalRecordStore, PostgresIndexStore, PostgresRecordStore};
3
4use crate::{
5 ServerConfig, ServerError,
6 error::{IndexError, ObjectStoreError},
7 object_store::object_store_from_config,
8 postgres_backend::connect_postgres_metadata_pool,
9};
10
11pub use shardline_fsck::{
12 FsckError, FsckIssueDetail, FsckIssueKind, FsckReconstructionPlanDetail, LocalFsckIssue,
13 LocalFsckIssueKind, LocalFsckReport, ProviderRepositoryStateTimestampField, run_local_fsck,
14};
15
16pub async fn run_fsck(config: ServerConfig) -> Result<LocalFsckReport, ServerError> {
23 let object_root = config.root_dir().join("chunks");
24 let object_store = object_store_from_config(&config)?;
25 if let Some(index_postgres_url) = config.index_postgres_url() {
26 let pool = connect_postgres_metadata_pool(index_postgres_url, 4)?;
27 let index_store = PostgresIndexStore::new(pool.clone());
28 let record_store = PostgresRecordStore::new(pool);
29 return run_fsck_with_stores(
30 &record_store,
31 &index_store,
32 &object_root,
33 &object_store,
34 config.shard_metadata_limits(),
35 )
36 .await
37 .map_err(ServerError::from);
38 }
39
40 let index_store = LocalIndexStore::open(config.root_dir().to_path_buf());
41 let record_store = LocalRecordStore::open(config.root_dir().to_path_buf());
42 run_fsck_with_stores(
43 &record_store,
44 &index_store,
45 &object_root,
46 &object_store,
47 config.shard_metadata_limits(),
48 )
49 .await
50 .map_err(ServerError::from)
51}
52
53impl From<FsckError> for ServerError {
54 fn from(value: FsckError) -> Self {
55 match value {
56 FsckError::Io(e) => Self::Io(e),
57 FsckError::Json(e) => Self::Json(e),
58 FsckError::NumericConversion(e) => Self::NumericConversion(e),
59 FsckError::Overflow => Self::Overflow,
60 FsckError::LocalObjectStore(e) => Self::ObjectStore(ObjectStoreError::Local(e)),
61 FsckError::S3ObjectStore(e) => Self::ObjectStore(ObjectStoreError::S3(e)),
62 FsckError::ObjectStore(e) => match e {
63 shardline_server_core::ServerObjectStoreError::NotFound => Self::NotFound,
64 shardline_server_core::ServerObjectStoreError::Overflow => Self::Overflow,
65 shardline_server_core::ServerObjectStoreError::InvalidContentHash => {
66 Self::InvalidContentHash
67 }
68 shardline_server_core::ServerObjectStoreError::StoredObjectLengthMismatch => {
69 Self::ObjectStore(ObjectStoreError::StoredLengthMismatch)
70 }
71 shardline_server_core::ServerObjectStoreError::Local(e) => {
72 Self::ObjectStore(ObjectStoreError::Local(e))
73 }
74 shardline_server_core::ServerObjectStoreError::S3(e) => {
75 Self::ObjectStore(ObjectStoreError::S3(e))
76 }
77 shardline_server_core::ServerObjectStoreError::Io(e) => Self::Io(e),
78 shardline_server_core::ServerObjectStoreError::NumericConversion(e) => {
79 Self::NumericConversion(e)
80 }
81 },
82 FsckError::XetAdapter(e) => Self::from(e),
83 FsckError::LocalIndexStore(e) => Self::Index(IndexError::Local(e)),
84 FsckError::MemoryIndexStore(e) => Self::Index(IndexError::MemoryIndex(e)),
85 FsckError::MemoryRecordStore(e) => Self::Index(IndexError::MemoryRecord(e)),
86 FsckError::PostgresMetadata(e) => Self::Index(IndexError::PostgresMetadata(e)),
87 FsckError::StoredFileMetadataTooLarge {
88 observed_bytes,
89 maximum_bytes,
90 } => Self::StoredFileMetadataTooLarge {
91 observed_bytes,
92 maximum_bytes,
93 },
94 }
95 }
96}