1use uuid::Uuid;
4
5use crate::api::tasks::{
6 LocationRefreshDefinition, TaskDefinition, TaskReadTarget, TaskReadTargetLatestOnBranch,
7};
8use crate::catalog_types::ProjectBranchId;
9use crate::{Error, Project, ResourceAddress, Run, Snapshot, TaskHandle};
10
11const LOCATION_KIND: &str = "location";
12
13#[derive(Clone)]
15pub struct Location {
16 project: Project,
17 branch_id: Option<ProjectBranchId>,
18 resource_id: Uuid,
19 version_id: Uuid,
20}
21
22impl Project {
23 pub async fn location(&self, branch: &str, path: &str) -> Result<Location, Error> {
25 self.branch(branch).await?.snapshot().location(path).await
26 }
27}
28
29impl Snapshot {
30 pub async fn location(&self, path: &str) -> Result<Location, Error> {
32 let address = path.parse::<ResourceAddress>()?;
33 if address.reference().is_some() {
34 return Err(Error::invalid(
35 "select the Location's branch with the snapshot, not an `@` reference",
36 ));
37 }
38 let resource = self.resource_at_path(address.path()).await?;
39 if resource.descriptor.kind.0 != LOCATION_KIND {
40 return Err(Error::invalid(format!("`{path}` is not a Location")));
41 }
42 Ok(Location {
43 project: self.project.clone(),
44 branch_id: self.branch_id,
45 resource_id: resource.descriptor.resource_id.as_uuid(),
46 version_id: resource.version_id.as_uuid(),
47 })
48 }
49}
50
51impl Location {
52 pub fn resource_id(&self) -> Uuid {
54 self.resource_id
55 }
56
57 pub fn version_id(&self) -> Uuid {
59 self.version_id
60 }
61
62 pub async fn refresh(&self, run: Run) -> Result<Option<TaskHandle>, Error> {
70 let branch_id = self.branch_id.ok_or_else(|| {
71 Error::invalid("refreshing a Location needs a branch snapshot, not an exact commit")
72 })?;
73 let definition = TaskDefinition::LocationRefresh(LocationRefreshDefinition {
74 read_target: TaskReadTarget::LatestOnBranch(TaskReadTargetLatestOnBranch {
75 branch_id: branch_id.as_uuid(),
76 }),
77 location_resource_id: self.resource_id,
78 });
79 self.project.submit_task(definition, None, run).await
80 }
81}