use crate::pb::commit_service_client::CommitServiceClient; use crate::pb::*; use super::{GitksService, cache, into_status}; remote_client!( remote_commit_client, CommitServiceClient, "commit" ); #[tonic::async_trait] impl commit_service_server::CommitService for GitksService { async fn list_commits( &self, request: tonic::Request, ) -> Result, tonic::Status> { let m = crate::metrics::RequestMetrics::new("gitks.CommitService/ListCommits"); let inner = request.into_inner(); let _rate = self.acquire_rate_limit(inner.repository.as_ref()).await?; let repo = self.repo_label(inner.repository.as_ref()); let span = tracing::info_span!("commit.list_commits", %repo); let _enter = span.enter(); let gb = match self.resolve(inner.repository.as_ref()) { Ok(gb) => gb, Err(err) if err.code() == tonic::Code::NotFound => { if let Some(mut client) = remote_commit_client(self, inner.repository.as_ref(), false).await? { m.record("ok"); return client.list_commits(inner).await; } crate::metrics::record_rpc_error(&m, &err); return Err(err); } Err(err) => { crate::metrics::record_rpc_error(&m, &err); return Err(err); } }; let resp = if !inner.all && cache::selector_is_oid(&inner.revision) { cache::cached_response("commit.list_commits", &inner, || { gb.list_commits(inner.clone()).map_err(into_status) })? } else { gb.list_commits(inner).map_err(into_status)? }; tracing::info!(%repo, count = resp.commits.len(), total = resp.page_info.as_ref().map(|p| p.total_count).unwrap_or(0), "list_commits done"); m.record("ok"); Ok(tonic::Response::new(resp)) } async fn get_commit( &self, request: tonic::Request, ) -> Result, tonic::Status> { let m = crate::metrics::RequestMetrics::new("gitks.CommitService/GetCommit"); let inner = request.into_inner(); let _rate = self.acquire_rate_limit(inner.repository.as_ref()).await?; let repo = self.repo_label(inner.repository.as_ref()); let span = tracing::info_span!("commit.get_commit", %repo); let _enter = span.enter(); let gb = match self.resolve(inner.repository.as_ref()) { Ok(gb) => gb, Err(err) if err.code() == tonic::Code::NotFound => { if let Some(mut client) = remote_commit_client(self, inner.repository.as_ref(), false).await? { m.record("ok"); return client.get_commit(inner).await; } crate::metrics::record_rpc_error(&m, &err); return Err(err); } Err(err) => { crate::metrics::record_rpc_error(&m, &err); return Err(err); } }; let resp = if cache::selector_is_oid(&inner.revision) { cache::cached_response("commit.get_commit", &inner, || { gb.get_commit(inner.clone()).map_err(into_status) })? } else { gb.get_commit(inner).map_err(into_status)? }; m.record("ok"); Ok(tonic::Response::new(resp)) } async fn get_commit_ancestors( &self, request: tonic::Request, ) -> Result, tonic::Status> { let m = crate::metrics::RequestMetrics::new("gitks.CommitService/GetCommitAncestors"); let inner = request.into_inner(); let _rate = self.acquire_rate_limit(inner.repository.as_ref()).await?; let repo = self.repo_label(inner.repository.as_ref()); let span = tracing::info_span!("commit.get_commit_ancestors", %repo); let _enter = span.enter(); let gb = match self.resolve(inner.repository.as_ref()) { Ok(gb) => gb, Err(err) if err.code() == tonic::Code::NotFound => { if let Some(mut client) = remote_commit_client(self, inner.repository.as_ref(), false).await? { m.record("ok"); return client.get_commit_ancestors(inner).await; } crate::metrics::record_rpc_error(&m, &err); return Err(err); } Err(err) => { crate::metrics::record_rpc_error(&m, &err); return Err(err); } }; let resp = if cache::selector_is_oid(&inner.revision) { cache::cached_response("commit.get_commit_ancestors", &inner, || { gb.get_commit_ancestors(inner.clone()).map_err(into_status) })? } else { gb.get_commit_ancestors(inner).map_err(into_status)? }; tracing::info!(%repo, count = resp.commits.len(), "get_commit_ancestors done"); m.record("ok"); Ok(tonic::Response::new(resp)) } async fn create_commit( &self, request: tonic::Request, ) -> Result, tonic::Status> { let m = crate::metrics::RequestMetrics::new("gitks.CommitService/CreateCommit"); let inner = request.into_inner(); let _rate = self.acquire_rate_limit(inner.repository.as_ref()).await?; let repo = self.repo_label(inner.repository.as_ref()); let branch = inner.branch.clone(); let span = tracing::info_span!("commit.create_commit", %repo, %branch); let _enter = span.enter(); let gb = match self.resolve(inner.repository.as_ref()) { Ok(gb) => gb, Err(err) if err.code() == tonic::Code::NotFound => { if let Some(mut client) = remote_commit_client(self, inner.repository.as_ref(), true).await? { m.record("ok"); return client.create_commit(inner).await; } crate::metrics::record_rpc_error(&m, &err); return Err(err); } Err(err) => { crate::metrics::record_rpc_error(&m, &err); return Err(err); } }; let resp = gb.create_commit(inner).map_err(into_status)?; let commit_hex = resp .commit .as_ref() .and_then(|c| c.oid.as_ref().map(|o| o.hex.as_str()).or(Some("?"))) .unwrap_or("?"); tracing::info!(%repo, %branch, %commit_hex, "commit created"); self.notify_ref_update(&repo, &format!("refs/heads/{}", branch), "", ""); m.record("ok"); Ok(tonic::Response::new(resp)) } async fn revert_commit( &self, request: tonic::Request, ) -> Result, tonic::Status> { let m = crate::metrics::RequestMetrics::new("gitks.CommitService/RevertCommit"); let inner = request.into_inner(); let _rate = self.acquire_rate_limit(inner.repository.as_ref()).await?; let repo = self.repo_label(inner.repository.as_ref()); let branch = inner.branch.clone(); let span = tracing::info_span!("commit.revert_commit", %repo, %branch); let _enter = span.enter(); let gb = match self.resolve(inner.repository.as_ref()) { Ok(gb) => gb, Err(err) if err.code() == tonic::Code::NotFound => { if let Some(mut client) = remote_commit_client(self, inner.repository.as_ref(), true).await? { m.record("ok"); return client.revert_commit(inner).await; } crate::metrics::record_rpc_error(&m, &err); return Err(err); } Err(err) => { crate::metrics::record_rpc_error(&m, &err); return Err(err); } }; let resp = gb.revert_commit(inner).map_err(into_status)?; tracing::info!(%repo, %branch, "commit reverted"); self.notify_ref_update(&repo, &format!("refs/heads/{}", branch), "", ""); m.record("ok"); Ok(tonic::Response::new(resp)) } async fn cherry_pick_commit( &self, request: tonic::Request, ) -> Result, tonic::Status> { let m = crate::metrics::RequestMetrics::new("gitks.CommitService/CherryPickCommit"); let inner = request.into_inner(); let _rate = self.acquire_rate_limit(inner.repository.as_ref()).await?; let repo = self.repo_label(inner.repository.as_ref()); let branch = inner.branch.clone(); let span = tracing::info_span!("commit.cherry_pick_commit", %repo, %branch); let _enter = span.enter(); let gb = match self.resolve(inner.repository.as_ref()) { Ok(gb) => gb, Err(err) if err.code() == tonic::Code::NotFound => { if let Some(mut client) = remote_commit_client(self, inner.repository.as_ref(), true).await? { m.record("ok"); return client.cherry_pick_commit(inner).await; } crate::metrics::record_rpc_error(&m, &err); return Err(err); } Err(err) => { crate::metrics::record_rpc_error(&m, &err); return Err(err); } }; let resp = gb.cherry_pick_commit(inner).map_err(into_status)?; tracing::info!(%repo, %branch, "commit cherry-picked"); self.notify_ref_update(&repo, &format!("refs/heads/{}", branch), "", ""); m.record("ok"); Ok(tonic::Response::new(resp)) } async fn compare_commits( &self, request: tonic::Request, ) -> Result, tonic::Status> { let m = crate::metrics::RequestMetrics::new("gitks.CommitService/CompareCommits"); let inner = request.into_inner(); let _rate = self.acquire_rate_limit(inner.repository.as_ref()).await?; let repo = self.repo_label(inner.repository.as_ref()); let span = tracing::info_span!("commit.compare_commits", %repo); let _enter = span.enter(); let gb = match self.resolve(inner.repository.as_ref()) { Ok(gb) => gb, Err(err) if err.code() == tonic::Code::NotFound => { if let Some(mut client) = remote_commit_client(self, inner.repository.as_ref(), false).await? { m.record("ok"); return client.compare_commits(inner).await; } crate::metrics::record_rpc_error(&m, &err); return Err(err); } Err(err) => { crate::metrics::record_rpc_error(&m, &err); return Err(err); } }; let resp = if cache::selectors_are_oid(&inner.base, &inner.head) { cache::cached_response("commit.compare_commits", &inner, || { gb.compare_commits(inner.clone()).map_err(into_status) })? } else { gb.compare_commits(inner).map_err(into_status)? }; tracing::info!(%repo, count = resp.commits.len(), "compare_commits done"); m.record("ok"); Ok(tonic::Response::new(resp)) } async fn find_commit( &self, request: tonic::Request, ) -> Result, tonic::Status> { let m = crate::metrics::RequestMetrics::new("gitks.CommitService/FindCommit"); let inner = request.into_inner(); let _rate = self.acquire_rate_limit(inner.repository.as_ref()).await?; let gb = self.resolve(inner.repository.as_ref())?; let resp = gb.find_commit(inner).map_err(into_status)?; m.record("ok"); Ok(tonic::Response::new(resp)) } async fn list_commits_by_oid( &self, request: tonic::Request, ) -> Result, tonic::Status> { let m = crate::metrics::RequestMetrics::new("gitks.CommitService/ListCommitsByOid"); let inner = request.into_inner(); let _rate = self.acquire_rate_limit(inner.repository.as_ref()).await?; let gb = self.resolve(inner.repository.as_ref())?; let resp = gb.list_commits_by_oid(inner).map_err(into_status)?; m.record("ok"); Ok(tonic::Response::new(resp)) } async fn commit_is_ancestor( &self, request: tonic::Request, ) -> Result, tonic::Status> { let m = crate::metrics::RequestMetrics::new("gitks.CommitService/CommitIsAncestor"); let inner = request.into_inner(); let _rate = self.acquire_rate_limit(inner.repository.as_ref()).await?; let gb = self.resolve(inner.repository.as_ref())?; let resp = gb.commit_is_ancestor(inner).map_err(into_status)?; m.record("ok"); Ok(tonic::Response::new(resp)) } async fn check_objects_exist( &self, request: tonic::Request, ) -> Result, tonic::Status> { let m = crate::metrics::RequestMetrics::new("gitks.CommitService/CheckObjectsExist"); let inner = request.into_inner(); let _rate = self.acquire_rate_limit(inner.repository.as_ref()).await?; let gb = self.resolve(inner.repository.as_ref())?; let resp = gb.check_objects_exist(inner).map_err(into_status)?; m.record("ok"); Ok(tonic::Response::new(resp)) } async fn commits_by_message( &self, request: tonic::Request, ) -> Result, tonic::Status> { let m = crate::metrics::RequestMetrics::new("gitks.CommitService/CommitsByMessage"); let inner = request.into_inner(); let _rate = self.acquire_rate_limit(inner.repository.as_ref()).await?; let gb = self.resolve(inner.repository.as_ref())?; let resp = gb.commits_by_message(inner).map_err(into_status)?; m.record("ok"); Ok(tonic::Response::new(resp)) } async fn get_commit_stats( &self, request: tonic::Request, ) -> Result, tonic::Status> { let m = crate::metrics::RequestMetrics::new("gitks.CommitService/GetCommitStats"); let inner = request.into_inner(); let _rate = self.acquire_rate_limit(inner.repository.as_ref()).await?; let gb = self.resolve(inner.repository.as_ref())?; let resp = gb.get_commit_stats(inner).map_err(into_status)?; m.record("ok"); Ok(tonic::Response::new(resp)) } async fn last_commit_for_path( &self, request: tonic::Request, ) -> Result, tonic::Status> { let m = crate::metrics::RequestMetrics::new("gitks.CommitService/LastCommitForPath"); let inner = request.into_inner(); let _rate = self.acquire_rate_limit(inner.repository.as_ref()).await?; let gb = self.resolve(inner.repository.as_ref())?; let resp = gb.last_commit_for_path(inner).map_err(into_status)?; m.record("ok"); Ok(tonic::Response::new(resp)) } async fn count_commits( &self, request: tonic::Request, ) -> Result, tonic::Status> { let m = crate::metrics::RequestMetrics::new("gitks.CommitService/CountCommits"); let inner = request.into_inner(); let _rate = self.acquire_rate_limit(inner.repository.as_ref()).await?; let gb = self.resolve(inner.repository.as_ref())?; let resp = gb.count_commits(inner).map_err(into_status)?; m.record("ok"); Ok(tonic::Response::new(resp)) } async fn count_diverging_commits( &self, request: tonic::Request, ) -> Result, tonic::Status> { let m = crate::metrics::RequestMetrics::new("gitks.CommitService/CountDivergingCommits"); let inner = request.into_inner(); let _rate = self.acquire_rate_limit(inner.repository.as_ref()).await?; let gb = self.resolve(inner.repository.as_ref())?; let resp = gb.count_diverging_commits(inner).map_err(into_status)?; m.record("ok"); Ok(tonic::Response::new(resp)) } }