use uuid::Uuid;
use crate::api::tasks::{
LocationRefreshDefinition, TaskDefinition, TaskReadTarget, TaskReadTargetLatestOnBranch,
};
use crate::catalog_types::ProjectBranchId;
use crate::{Error, Project, ResourceAddress, Run, Snapshot, TaskHandle};
const LOCATION_KIND: &str = "location";
#[derive(Clone)]
pub struct Location {
project: Project,
branch_id: Option<ProjectBranchId>,
resource_id: Uuid,
version_id: Uuid,
}
impl Project {
pub async fn location(&self, branch: &str, path: &str) -> Result<Location, Error> {
self.branch(branch).await?.snapshot().location(path).await
}
}
impl Snapshot {
pub async fn location(&self, path: &str) -> Result<Location, Error> {
let address = path.parse::<ResourceAddress>()?;
if address.reference().is_some() {
return Err(Error::invalid(
"select the Location's branch with the snapshot, not an `@` reference",
));
}
let resource = self.resource_at_path(address.path()).await?;
if resource.descriptor.kind.0 != LOCATION_KIND {
return Err(Error::invalid(format!("`{path}` is not a Location")));
}
Ok(Location {
project: self.project.clone(),
branch_id: self.branch_id,
resource_id: resource.descriptor.resource_id.as_uuid(),
version_id: resource.version_id.as_uuid(),
})
}
}
impl Location {
pub fn resource_id(&self) -> Uuid {
self.resource_id
}
pub fn version_id(&self) -> Uuid {
self.version_id
}
pub async fn refresh(&self, run: Run) -> Result<Option<TaskHandle>, Error> {
let branch_id = self.branch_id.ok_or_else(|| {
Error::invalid("refreshing a Location needs a branch snapshot, not an exact commit")
})?;
let definition = TaskDefinition::LocationRefresh(LocationRefreshDefinition {
read_target: TaskReadTarget::LatestOnBranch(TaskReadTargetLatestOnBranch {
branch_id: branch_id.as_uuid(),
}),
location_resource_id: self.resource_id,
});
self.project.submit_task(definition, None, run).await
}
}