mirror of
https://github.com/atuinsh/atuin.git
synced 2026-10-16 04:26:53 +02:00
chore(octavo): feature-flag octavo (atuinsh/atuin#4428)
- Ensures `atuin-client` doesn't get any `octavo` code. - Disables `octavo` by default. - Ensures `octavo` isn't in the next release.
This commit is contained in:
1 parent
9d1b5868cd
commit
756cd80455
13 files changed
+53
-37
No files matched your search
@@ -66,6 +66,8 @@ commit_preprocessors = [
|
||||
]
|
||||
# regex for parsing and grouping commits
|
||||
commit_parsers = [
|
||||
# Octavo is compiled out of releases until it ships.
|
||||
{ message = "^\\w+\\(octavo\\)", skip = true },
|
||||
{ message = "^feat", group = "Features" },
|
||||
{ message = "^fix", group = "Bug Fixes" },
|
||||
{ message = "^doc", group = "Documentation" },
|
||||
|
||||
@@ -18,6 +18,7 @@ sync = ["reqwest", "dep:reqwest-middleware"]
|
||||
hub = ["reqwest"]
|
||||
daemon = []
|
||||
check-update = []
|
||||
octavo = []
|
||||
# Derive the protobuf enum traits on domain enums the daemon extern-paths into its codegen.
|
||||
proto = ["dep:prost"]
|
||||
# Statically link (vendor) OpenSSL for native-tls instead of using the system
|
||||
|
||||
@@ -538,6 +538,7 @@ pub struct PtyProxy {
|
||||
pub enabled: bool,
|
||||
}
|
||||
|
||||
#[cfg(feature = "octavo")]
|
||||
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
|
||||
pub struct Octavo {
|
||||
pub enabled: bool,
|
||||
@@ -1130,6 +1131,7 @@ pub struct Settings {
|
||||
#[serde(default)]
|
||||
pub output: OutputCapture,
|
||||
|
||||
#[cfg(feature = "octavo")]
|
||||
#[serde(default)]
|
||||
pub octavo: Octavo,
|
||||
|
||||
@@ -1219,6 +1221,7 @@ impl Settings {
|
||||
self.data_dir.join("threads.db")
|
||||
}
|
||||
|
||||
#[cfg(feature = "octavo")]
|
||||
#[must_use]
|
||||
pub fn octavo_queue_path(&self) -> PathBuf {
|
||||
self.data_dir.join("octavo.db")
|
||||
@@ -1527,7 +1530,7 @@ impl Settings {
|
||||
|
||||
let output = OutputCaptureConfig::default();
|
||||
|
||||
Ok(Config::builder()
|
||||
let builder = Config::builder()
|
||||
.set_default("history_format", "{time}\t{command}\t{duration}")?
|
||||
.set_default("data_dir", data_dir.to_str())?
|
||||
.set_default("db_path", db_path.to_str())?
|
||||
@@ -1634,9 +1637,13 @@ impl Settings {
|
||||
atuin_common::env::var_os("NO_MOTION").is_some(),
|
||||
)?
|
||||
.set_default("no_mouse", false)?
|
||||
.set_default("pty_proxy.enabled", false)?
|
||||
.set_default("pty_proxy.enabled", false)?;
|
||||
#[cfg(feature = "octavo")]
|
||||
let builder = builder
|
||||
.set_default("octavo.enabled", false)?
|
||||
.set_default("octavo.upload_output", false)?
|
||||
.set_default("octavo.upload_output", false)?;
|
||||
|
||||
Ok(builder
|
||||
.add_source(Environment::with_prefix("atuin").prefix_separator("_").separator("__")))
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ rust-version.workspace = true
|
||||
version.workspace = true
|
||||
|
||||
[features]
|
||||
octavo = ["dep:atuin-octavo"]
|
||||
octavo = ["dep:atuin-octavo", "atuin-client/octavo"]
|
||||
|
||||
[dependencies]
|
||||
async-stream = { workspace = true }
|
||||
|
||||
@@ -99,6 +99,7 @@ use tokio_stream::wrappers::BroadcastStream;
|
||||
use tracing::field::Empty;
|
||||
use tracing::{Instrument, Span};
|
||||
|
||||
#[cfg(feature = "octavo")]
|
||||
use crate::octavo::Octavo;
|
||||
use crate::output_capture::{CaptureError, GetOutputError, OutputCaptureEngine};
|
||||
use crate::search::SearchIndex;
|
||||
@@ -238,6 +239,7 @@ pub struct HistoryJournal {
|
||||
/// Durable store for captured command output.
|
||||
output_capture: OutputCaptureEngine,
|
||||
|
||||
#[cfg(feature = "octavo")]
|
||||
octavo: Octavo,
|
||||
|
||||
/// Ids a [`Self::delete`] is currently tearing down, reference-counted across concurrent
|
||||
@@ -310,7 +312,6 @@ impl HistoryJournal {
|
||||
history_db: HistoryDatabase,
|
||||
search_index: Arc<tokio::sync::RwLock<SearchIndex>>,
|
||||
output_capture: OutputCaptureEngine,
|
||||
octavo: Octavo,
|
||||
) -> Self {
|
||||
const DEFAULT_LIFECYCLE_SHARDS: NonZeroUsize = NonZeroUsize::new(64).unwrap();
|
||||
|
||||
@@ -324,12 +325,19 @@ impl HistoryJournal {
|
||||
search_index,
|
||||
broadcast,
|
||||
output_capture,
|
||||
octavo,
|
||||
#[cfg(feature = "octavo")]
|
||||
octavo: Octavo::nop(),
|
||||
deleting: DashMap::new(),
|
||||
lifecycle_mutex: AsyncShardedMutex::new(DEFAULT_LIFECYCLE_SHARDS),
|
||||
}
|
||||
}
|
||||
|
||||
/// Sends what this journal records to `octavo`, which [`Self::new`] leaves as a nop.
|
||||
#[cfg(feature = "octavo")]
|
||||
pub(crate) fn with_octavo(self, octavo: Octavo) -> Self {
|
||||
Self { octavo, ..self }
|
||||
}
|
||||
|
||||
/// Notify the registry that a command has been started.
|
||||
///
|
||||
/// Returns the [`HistoryId`] identifying the in-flight command, which is later used to
|
||||
@@ -449,6 +457,7 @@ impl HistoryJournal {
|
||||
// .read() and the subsequent .write() are completely discarded from the new
|
||||
// index.
|
||||
self.search_index.read().await.add_history(&history);
|
||||
#[cfg(feature = "octavo")]
|
||||
self.octavo.push_history(&history, history_record_id).await;
|
||||
|
||||
if self.broadcast.receiver_count() > 0 {
|
||||
@@ -582,6 +591,7 @@ impl HistoryJournal {
|
||||
}
|
||||
|
||||
// The tombstones commit the deletion, so Octavo hears of it even if a chunk below fails.
|
||||
#[cfg(feature = "octavo")]
|
||||
self.octavo.delete_history(&to_delete).await;
|
||||
|
||||
// The tombstones were just written above, so replaying them through
|
||||
@@ -713,6 +723,7 @@ impl HistoryJournal {
|
||||
|
||||
self.output_capture.capture(id, capture).await?;
|
||||
// Only once stored, since the upload reads the output back from the store.
|
||||
#[cfg(feature = "octavo")]
|
||||
self.octavo.push_output(id).await;
|
||||
Ok(())
|
||||
}
|
||||
@@ -757,14 +768,8 @@ mod tests {
|
||||
let history_store = HistoryStore::new(store, HostId(uuid_v7()), paseto_v4::Key::generate());
|
||||
let search_index = Arc::new(RwLock::new(SearchIndex::new(OrFilter::all())));
|
||||
let caps = CapClient::new("http://127.0.0.1:1".parse().unwrap(), reqwest::Client::new());
|
||||
let journal = HistoryJournal::new(
|
||||
caps,
|
||||
history_store,
|
||||
history_db,
|
||||
search_index,
|
||||
output_capture,
|
||||
Octavo::nop(),
|
||||
);
|
||||
let journal =
|
||||
HistoryJournal::new(caps, history_store, history_db, search_index, output_capture);
|
||||
(journal, tmp)
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ pub mod daemon;
|
||||
pub mod events;
|
||||
pub mod grpc;
|
||||
pub(crate) mod history_journal;
|
||||
#[cfg(feature = "octavo")]
|
||||
mod octavo;
|
||||
mod output_capture;
|
||||
pub mod pidfile;
|
||||
@@ -39,7 +40,6 @@ pub use history_journal::{
|
||||
CmdCancelError, CmdDeleteError, CmdEvent, CmdFinishError, CmdRebuildError, FinishedCmd,
|
||||
GetCmdInFlightError, HistoryJournal, RegisterOutputError,
|
||||
};
|
||||
pub use octavo::Octavo;
|
||||
pub use output_capture::{
|
||||
CaptureError, DeleteOutputError, GetOutputError, OutputCaptureEngine, OutputLine, OutputMatch,
|
||||
};
|
||||
@@ -352,15 +352,19 @@ pub async fn boot(
|
||||
|
||||
let history_store =
|
||||
HistoryStore::new(handle.store().clone(), host_id, handle.encryption_key().clone());
|
||||
#[cfg(feature = "octavo")]
|
||||
let outputs = output_capture.store();
|
||||
let journal = Arc::new(HistoryJournal::new(
|
||||
let journal = HistoryJournal::new(
|
||||
handle.caps().clone(),
|
||||
history_store,
|
||||
handle.history_db().clone(),
|
||||
search_index,
|
||||
output_capture,
|
||||
Octavo::open(&settings, handle.clone(), outputs).await,
|
||||
));
|
||||
);
|
||||
#[cfg(feature = "octavo")]
|
||||
let journal =
|
||||
journal.with_octavo(octavo::Octavo::open(&settings, handle.clone(), outputs).await);
|
||||
let journal = Arc::new(journal);
|
||||
let history_service = HistoryServer::new(grpc::HistoryService::new(journal, handle.clone()));
|
||||
let ai_session_service =
|
||||
AiSessionServer::new(grpc::AiSessionService::new(ai_session_capture.clone()));
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
#[cfg(feature = "octavo")]
|
||||
mod active;
|
||||
mod nop;
|
||||
|
||||
#[cfg(feature = "octavo")]
|
||||
pub use active::ActiveOctavoClient;
|
||||
use atuin_client::history::{History, HistoryId};
|
||||
use atuin_domain::record::RecordId;
|
||||
@@ -20,7 +18,6 @@ pub trait OctavoClient {
|
||||
#[enum_dispatch(OctavoClient)]
|
||||
#[derive(Debug)]
|
||||
pub enum AnyOctavoClient {
|
||||
#[cfg(feature = "octavo")]
|
||||
Active(ActiveOctavoClient),
|
||||
Nop(NopOctavoClient),
|
||||
}
|
||||
@@ -16,7 +16,6 @@ pub struct Octavo {
|
||||
}
|
||||
|
||||
impl Octavo {
|
||||
#[cfg(feature = "octavo")]
|
||||
pub async fn open(
|
||||
settings: &Settings,
|
||||
handle: DaemonHandle,
|
||||
@@ -39,16 +38,6 @@ impl Octavo {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "octavo"))]
|
||||
#[allow(clippy::unused_async)]
|
||||
pub async fn open(
|
||||
_settings: &Settings,
|
||||
_handle: DaemonHandle,
|
||||
_outputs: Arc<OutputStore>,
|
||||
) -> Self {
|
||||
Self::nop()
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn nop() -> Self {
|
||||
Self {
|
||||
|
||||
@@ -30,7 +30,7 @@ use atuin_daemon::grpc::history::pb;
|
||||
use atuin_daemon::grpc::history::pb::history_server::HistoryServer;
|
||||
use atuin_daemon::search::{IndexFilterMode, SearchIndex};
|
||||
use atuin_daemon::{
|
||||
Daemon, DaemonEvent, DaemonHandle, HistoryJournal, Octavo, OutputCaptureEngine, SearchComponent,
|
||||
Daemon, DaemonEvent, DaemonHandle, HistoryJournal, OutputCaptureEngine, SearchComponent,
|
||||
};
|
||||
use atuin_domain::record::{CmdOrigin, HostId, RecordTag};
|
||||
use corpus::{HistoryGen, Seeded};
|
||||
@@ -166,7 +166,6 @@ impl TestEnvBuilder {
|
||||
history_db.clone(),
|
||||
index.clone(),
|
||||
output_capture,
|
||||
Octavo::nop(),
|
||||
));
|
||||
let history_service =
|
||||
HistoryServer::new(HistoryService::new(journal.clone(), handle.clone()));
|
||||
|
||||
@@ -41,6 +41,7 @@ xxhash-rust = { workspace = true }
|
||||
[features]
|
||||
# Feature-gated axum integration for the server-side capability handlers (`caps::axum`).
|
||||
axum = ["dep:axum"]
|
||||
octavo = []
|
||||
|
||||
[dev-dependencies]
|
||||
pretty_assertions = { workspace = true }
|
||||
|
||||
@@ -50,11 +50,13 @@ impl Capability for PackfileCap {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "octavo")]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct OctavoCap {
|
||||
pub version: u32,
|
||||
}
|
||||
|
||||
#[cfg(feature = "octavo")]
|
||||
impl Capability for OctavoCap {
|
||||
fn static_name() -> &'static str {
|
||||
"sh.atuin.server/octavo"
|
||||
|
||||
@@ -57,7 +57,9 @@ mod client;
|
||||
mod middleware;
|
||||
mod server;
|
||||
|
||||
pub use all::{CapabilitiesCap, OctavoCap, PackfileCap, PageSizeCap};
|
||||
#[cfg(feature = "octavo")]
|
||||
pub use all::OctavoCap;
|
||||
pub use all::{CapabilitiesCap, PackfileCap, PageSizeCap};
|
||||
pub use client::{AuthHeaderProvider, CapClient, ServerSupportError};
|
||||
pub use middleware::{CapMiddleware, CapMismatch, CapabilitiesExt};
|
||||
pub use server::{CapServer, Negotiation};
|
||||
|
||||
@@ -48,14 +48,21 @@ default = [
|
||||
"daemon",
|
||||
"ai",
|
||||
"pty-proxy",
|
||||
"octavo",
|
||||
]
|
||||
client = ["atuin-client"]
|
||||
sync = ["atuin-client/sync"]
|
||||
daemon = ["dep:async-stream", "atuin-client/daemon", "atuin-daemon", "atuin-ai?/daemon"]
|
||||
ai = ["atuin-ai"]
|
||||
pty-proxy = ["dep:atuin-pty-proxy"]
|
||||
octavo = ["sync", "daemon", "atuin-daemon/octavo", "dep:atuin-octavo"]
|
||||
# Not a default feature until Octavo ships; release artifacts build without it.
|
||||
octavo = [
|
||||
"sync",
|
||||
"daemon",
|
||||
"atuin-client/octavo",
|
||||
"atuin-daemon/octavo",
|
||||
"atuin-domain/octavo",
|
||||
"dep:atuin-octavo",
|
||||
]
|
||||
hex = ["pty-proxy"]
|
||||
clipboard = ["dep:arboard", "atuin-ai?/clipboard"]
|
||||
check-update = ["atuin-client/check-update"]
|
||||
|
||||
Reference in new issue
Block a user