aboutsummaryrefslogtreecommitdiffstats
path: root/crates/daemon/src/api
diff options
context:
space:
mode:
authorBenedikt Peetz <benedikt.peetz@b-peetz.de>2026-07-24 17:56:36 +0200
committerBenedikt Peetz <benedikt.peetz@b-peetz.de>2026-07-24 17:56:36 +0200
commit9cdc575666faad4c162f4b4cf519bfdd1fd528dc (patch)
tree9287963ad11e237ca74edbd54161c03f3309927b /crates/daemon/src/api
parentchore: Last big refactoring (diff)
downloadatuin-9cdc575666faad4c162f4b4cf519bfdd1fd528dc.zip
feat: Finalize design for fish-shell integration
Diffstat (limited to '')
-rw-r--r--crates/daemon/src/api/control.rs33
-rw-r--r--crates/daemon/src/api/history.rs80
2 files changed, 85 insertions, 28 deletions
diff --git a/crates/daemon/src/api/control.rs b/crates/daemon/src/api/control.rs
index ff19f593..8277f434 100644
--- a/crates/daemon/src/api/control.rs
+++ b/crates/daemon/src/api/control.rs
@@ -6,7 +6,7 @@ use tokio::time::{self, MissedTickBehavior};
use tonic::{Request, Response, Status};
use tracing::{Level, instrument};
-use turtle::generated::{
+use turtle_api::generated::{
DAEMON_PROTOCOL_VERSION,
control::{
ForceSyncReply, ForceSyncRequest, PathsReply, PathsRequest, StatusReply, StatusRequest,
@@ -91,9 +91,36 @@ impl Control for ControlService {
&self,
_request: Request<ForceSyncRequest>,
) -> Result<Response<ForceSyncReply>, Status> {
- let reply = ForceSyncReply { accepted: true };
-
self.handle.emit(DaemonEvent::ForceSync);
+ let event = self
+ .handle
+ .wait_for(|e| {
+ matches!(
+ e,
+ DaemonEvent::SyncFailed { .. } | DaemonEvent::SyncCompleted { .. }
+ )
+ })
+ .await
+ .map_err(|e| {
+ Status::internal(format!("failed to wait for sync response event: {e:?}"))
+ })?;
+
+ let reply = match event {
+ DaemonEvent::SyncCompleted {
+ uploaded,
+ downloaded,
+ } => ForceSyncReply {
+ error: None,
+ uploaded: uploaded as u32,
+ downloaded: downloaded as u32,
+ },
+ DaemonEvent::SyncFailed { error } => ForceSyncReply {
+ error: Some(error),
+ uploaded: 0,
+ downloaded: 0,
+ },
+ _ => unreachable!(),
+ };
Ok(Response::new(reply))
}
diff --git a/crates/daemon/src/api/history.rs b/crates/daemon/src/api/history.rs
index 6165464d..0b373604 100644
--- a/crates/daemon/src/api/history.rs
+++ b/crates/daemon/src/api/history.rs
@@ -1,10 +1,10 @@
-use std::pin::Pin;
+use std::{pin::Pin, time::Duration};
use dashmap::DashMap;
use eyre::Result;
use time::OffsetDateTime;
use tokio_stream::Stream;
-use tonic::{Request, Response, Status};
+use tonic::{IntoRequest, Request, Response, Status};
use tracing::{Level, instrument};
use crate::{
@@ -12,12 +12,16 @@ use crate::{
daemon::DaemonHandle,
events::DaemonEvent,
};
-use turtle::{
+use turtle_api::{
+ client::{
+ proto_duration_to_std, proto_timestamp_to_time, std_to_proto_duration,
+ time_to_proto_timestamp,
+ },
generated::{
DAEMON_PROTOCOL_VERSION,
history::{
- EndHistoryReply, EndHistoryRequest, HistoryEntry, HistoryEventKind, HistoryReply,
- HistoryRequest, StartHistoryReply, StartHistoryRequest, TailHistoryReply,
+ AddHistoryRequest, EndHistoryReply, EndHistoryRequest, HistoryEntry, HistoryEventKind,
+ HistoryReply, HistoryRequest, StartHistoryReply, StartHistoryRequest, TailHistoryReply,
TailHistoryRequest,
history_server::{History as HistorySvc, HistoryServer},
},
@@ -60,8 +64,8 @@ impl HistoryService {
fn history_to_reply(history: History) -> HistoryEntry {
HistoryEntry {
- timestamp: history.timestamp.unix_timestamp_nanos() as u64,
- id: history.id.0,
+ timestamp: time_to_proto_timestamp(history.timestamp),
+ id: history.id.to_string(),
command: history.command,
cwd: history.cwd,
session: history.session,
@@ -69,7 +73,7 @@ fn history_to_reply(history: History) -> HistoryEntry {
author: history.author,
intent: history.intent.unwrap_or_default(),
exit: history.exit,
- duration: history.duration,
+ duration: std_to_proto_duration(history.duration),
}
}
@@ -85,8 +89,8 @@ impl HistorySvc for HistoryService {
let req = request.into_inner();
let entries = if let Some(range) = req.range {
- let from = OffsetDateTime::from_unix_timestamp(range.start as i64).unwrap();
- let to = OffsetDateTime::from_unix_timestamp(range.end as i64).unwrap();
+ let from = proto_timestamp_to_time(range.start);
+ let to = proto_timestamp_to_time(range.end);
self.handle.history_db().range(from, to).await
} else {
@@ -101,18 +105,41 @@ impl HistorySvc for HistoryService {
}
#[instrument(skip_all, level = Level::INFO)]
+ async fn add_history(
+ &self,
+ request: Request<AddHistoryRequest>,
+ ) -> Result<Response<EndHistoryReply>, Status> {
+ let req = request.into_inner();
+ let start_req = req.start.expect("is some");
+
+ let start_response = self
+ .start_history(start_req.into_request())
+ .await?
+ .into_inner();
+ let end_responnse = self
+ .end_history(
+ EndHistoryRequest {
+ id: start_response.id,
+ exit: req.exit,
+ duration: req.duration,
+ }
+ .into_request(),
+ )
+ .await?;
+
+ Ok(end_responnse)
+ }
+
+ #[instrument(skip_all, level = Level::INFO)]
async fn start_history(
&self,
request: Request<StartHistoryRequest>,
) -> Result<Response<StartHistoryReply>, Status> {
+ tokio::time::sleep(Duration::from_secs(5)).await;
+
let req = request.into_inner();
- let timestamp = OffsetDateTime::from_unix_timestamp_nanos(i128::from(req.timestamp))
- .map_err(|_| {
- Status::invalid_argument(
- "failed to parse timestamp as unix time (expected nanos since epoch)",
- )
- })?;
+ let timestamp = proto_timestamp_to_time(req.timestamp);
let h: History = History::daemon()
.timestamp(timestamp)
@@ -121,7 +148,7 @@ impl HistorySvc for HistoryService {
.session(req.session)
.hostname(req.hostname)
.author(req.author)
- .intent(req.intent)
+ .intent(req.intent.unwrap_or_default())
.build()
.into();
@@ -146,16 +173,15 @@ impl HistorySvc for HistoryService {
request: Request<EndHistoryRequest>,
) -> Result<Response<EndHistoryReply>, Status> {
let req = request.into_inner();
- let id = HistoryId(req.id);
+ let id = HistoryId::from(req.id);
if let Some((_, mut history)) = self.running.remove(&id) {
history.exit = req.exit;
- history.duration = match req.duration {
- 0 => i64::try_from(
- (OffsetDateTime::now_utc() - history.timestamp).whole_nanoseconds(),
- )
- .expect("failed to convert calculated duration to i64"),
- value => i64::try_from(value).expect("failed to get i64 duration"),
+ history.duration = match proto_duration_to_std(req.duration) {
+ Duration::ZERO => Duration::from_nanos_u128(
+ (OffsetDateTime::now_utc() - history.timestamp).whole_nanoseconds() as u128,
+ ),
+ value => value,
};
self.handle
@@ -164,7 +190,11 @@ impl HistorySvc for HistoryService {
.await
.map_err(|e| Status::internal(format!("failed to write to db: {e:?}")))?;
- tracing::info!(id = id.0, duration = history.duration, "end history");
+ tracing::info!(
+ id = id.to_string(),
+ duration = history.duration.as_nanos(),
+ "end history"
+ );
let (record_id, idx) = self
.history_store