feat(admin): complete site replication support (#2346)

This commit is contained in:
weisd
2026-03-31 13:01:38 +08:00
committed by GitHub
parent 6bf0c542a1
commit 15995aae14
22 changed files with 5429 additions and 101 deletions
@@ -777,6 +777,14 @@ impl<S: StorageAPI> ReplicationPool<S> {
Ok(status)
}
pub async fn cancel_bucket_resync(&self, opts: ResyncOpts) -> Result<(), EcstoreError> {
self.resyncer.cancel(&opts).await;
self.resyncer
.mark_status(ResyncStatusType::ResyncCanceled, opts, self.storage.clone())
.await?;
Ok(())
}
pub async fn start_bucket_resync(self: Arc<Self>, opts: ResyncOpts) -> Result<(), EcstoreError> {
let now = OffsetDateTime::now_utc();
let bucket_status = {
@@ -813,8 +821,14 @@ impl<S: StorageAPI> ReplicationPool<S> {
let resyncer = self.resyncer.clone();
let storage = self.storage.clone();
let cancel_token = CancellationToken::new();
resyncer.register_cancel_token(&opts, cancel_token.clone()).await;
tokio::spawn(async move {
resyncer.resync_bucket(CancellationToken::new(), storage, false, opts).await;
resyncer
.clone()
.resync_bucket(cancel_token, storage, false, opts.clone())
.await;
resyncer.clear_cancel_token(&opts).await;
});
Ok(())
@@ -852,8 +866,12 @@ impl<S: StorageAPI> ReplicationPool<S> {
}
/// Load bucket replication resync statuses into memory
#[instrument(skip(cancellation_token))]
async fn load_resync(self: Arc<Self>, buckets: &[String], cancellation_token: CancellationToken) -> Result<(), EcstoreError> {
#[instrument(skip(_cancellation_token))]
async fn load_resync(
self: Arc<Self>,
buckets: &[String],
_cancellation_token: CancellationToken,
) -> Result<(), EcstoreError> {
// TODO: add leader_lock
// Make sure only one node running resync on the cluster
// Note: Leader lock implementation would be needed here
@@ -884,24 +902,20 @@ impl<S: StorageAPI> ReplicationPool<S> {
// Note: This would spawn a resync task in a real implementation
// For now, we just log the resync request
let ctx = cancellation_token.clone();
let ctx = CancellationToken::new();
let bucket_clone = bucket.clone();
let resync = self.resyncer.clone();
let storage = self.storage.clone();
let opts = ResyncOpts {
bucket: bucket_clone,
arn,
resync_id: stats.resync_id,
resync_before: stats.resync_before_date,
};
tokio::spawn(async move {
resync
.resync_bucket(
ctx,
storage,
true,
ResyncOpts {
bucket: bucket_clone,
arn,
resync_id: stats.resync_id,
resync_before: stats.resync_before_date,
},
)
.await;
resync.register_cancel_token(&opts, ctx.clone()).await;
resync.clone().resync_bucket(ctx, storage, true, opts.clone()).await;
resync.clear_cancel_token(&opts).await;
});
}
_ => {}
@@ -949,6 +963,7 @@ pub trait ReplicationPoolTrait: std::fmt::Debug {
async fn queue_replica_delete_task(&self, ri: DeletedObjectReplicationInfo);
async fn resize(&self, priority: ReplicationPriority, max_workers: usize, max_l_workers: usize);
async fn get_bucket_resync_status(&self, bucket: &str) -> Result<BucketReplicationResyncStatus, EcstoreError>;
async fn cancel_bucket_resync(&self, opts: ResyncOpts) -> Result<(), EcstoreError>;
async fn start_bucket_resync(self: Arc<Self>, opts: ResyncOpts) -> Result<(), EcstoreError>;
async fn init_resync(
self: Arc<Self>,
@@ -976,6 +991,10 @@ impl<S: StorageAPI> ReplicationPoolTrait for ReplicationPool<S> {
self.get_bucket_resync_status(bucket).await
}
async fn cancel_bucket_resync(&self, opts: ResyncOpts) -> Result<(), EcstoreError> {
self.cancel_bucket_resync(opts).await
}
async fn start_bucket_resync(self: Arc<Self>, opts: ResyncOpts) -> Result<(), EcstoreError> {
self.start_bucket_resync(opts).await
}