feat: config history — auto-snapshot on update, list/pin/restore endpoints
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::entities::Channel;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::entities::{Channel, ChannelConfigSnapshot, ScheduleConfig};
|
||||
use crate::errors::{DomainError, DomainResult};
|
||||
use crate::repositories::ChannelRepository;
|
||||
use crate::value_objects::{ChannelId, UserId};
|
||||
@@ -42,10 +44,73 @@ impl ChannelService {
|
||||
}
|
||||
|
||||
pub async fn update(&self, channel: Channel) -> DomainResult<Channel> {
|
||||
// Auto-snapshot the config being replaced
|
||||
self.channel_repo
|
||||
.save_config_snapshot(channel.id, &channel.schedule_config, None)
|
||||
.await?;
|
||||
self.channel_repo.save(&channel).await?;
|
||||
Ok(channel)
|
||||
}
|
||||
|
||||
pub async fn list_config_snapshots(
|
||||
&self,
|
||||
channel_id: ChannelId,
|
||||
) -> DomainResult<Vec<ChannelConfigSnapshot>> {
|
||||
self.channel_repo.list_config_snapshots(channel_id).await
|
||||
}
|
||||
|
||||
pub async fn get_config_snapshot(
|
||||
&self,
|
||||
channel_id: ChannelId,
|
||||
snapshot_id: Uuid,
|
||||
) -> DomainResult<Option<ChannelConfigSnapshot>> {
|
||||
self.channel_repo.get_config_snapshot(channel_id, snapshot_id).await
|
||||
}
|
||||
|
||||
pub async fn patch_config_snapshot_label(
|
||||
&self,
|
||||
channel_id: ChannelId,
|
||||
snapshot_id: Uuid,
|
||||
label: Option<String>,
|
||||
) -> DomainResult<Option<ChannelConfigSnapshot>> {
|
||||
self.channel_repo.patch_config_snapshot_label(channel_id, snapshot_id, label).await
|
||||
}
|
||||
|
||||
/// Restore a snapshot: auto-snapshot current config, then apply the snapshot's config.
|
||||
pub async fn restore_config_snapshot(
|
||||
&self,
|
||||
channel_id: ChannelId,
|
||||
snapshot_id: Uuid,
|
||||
) -> DomainResult<Channel> {
|
||||
let snapshot = self
|
||||
.channel_repo
|
||||
.get_config_snapshot(channel_id, snapshot_id)
|
||||
.await?
|
||||
.ok_or(DomainError::ChannelNotFound(channel_id))?;
|
||||
let mut channel = self
|
||||
.channel_repo
|
||||
.find_by_id(channel_id)
|
||||
.await?
|
||||
.ok_or(DomainError::ChannelNotFound(channel_id))?;
|
||||
// Snapshot current config before overwriting
|
||||
self.channel_repo
|
||||
.save_config_snapshot(channel_id, &channel.schedule_config, None)
|
||||
.await?;
|
||||
channel.schedule_config = snapshot.config;
|
||||
channel.updated_at = chrono::Utc::now();
|
||||
self.channel_repo.save(&channel).await?;
|
||||
Ok(channel)
|
||||
}
|
||||
|
||||
pub async fn save_config_snapshot(
|
||||
&self,
|
||||
channel_id: ChannelId,
|
||||
config: &ScheduleConfig,
|
||||
label: Option<String>,
|
||||
) -> DomainResult<ChannelConfigSnapshot> {
|
||||
self.channel_repo.save_config_snapshot(channel_id, config, label).await
|
||||
}
|
||||
|
||||
/// Delete a channel, enforcing that `requester_id` is the owner.
|
||||
pub async fn delete(&self, id: ChannelId, requester_id: UserId) -> DomainResult<()> {
|
||||
let channel = self.find_by_id(id).await?;
|
||||
|
||||
Reference in New Issue
Block a user