Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 39 additions & 17 deletions src/connections.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::sdk::{Api, ApiError, block, none_if_404};
use crate::sdk::{Api, ApiError, block, block_with_wakeup, none_if_404};
use serde::{Deserialize, Serialize};

#[derive(Deserialize, Serialize)]
Expand Down Expand Up @@ -99,7 +99,12 @@ struct ConnectionTypeDetail {

pub fn types_list(workspace_id: &str, format: &str) {
let api = Api::new(Some(workspace_id));
let resp = block(api.client().connection_types().list()).unwrap_or_else(|e| e.exit());
let resp = block_with_wakeup(
&api,
"Loading connection types…",
api.client().connection_types().list(),
)
.unwrap_or_else(|e| e.exit());
let body = ListConnectionTypesResponse {
connection_types: resp
.connection_types
Expand Down Expand Up @@ -136,7 +141,12 @@ pub fn types_list(workspace_id: &str, format: &str) {

pub fn types_get(workspace_id: &str, name: &str, format: &str) {
let api = Api::new(Some(workspace_id));
let resp = block(api.client().connection_types().get(name)).unwrap_or_else(|e| e.exit());
let resp = block_with_wakeup(
&api,
"Loading connection type…",
api.client().connection_types().get(name),
)
.unwrap_or_else(|e| e.exit());
// The SDK models nullable fields as `Option<Option<Value>>`; flatten and
// drop an explicit JSON `null` to match the old behavior (the old struct
// deserialized a missing/`null` field to `None`).
Expand Down Expand Up @@ -243,11 +253,18 @@ pub fn get(workspace_id: &str, connection_id: &str, format: &str) {
let api = Api::new(Some(workspace_id));
let is_table = format == "table";

let spinner = is_table.then(|| crate::util::spinner("Fetching connection..."));
let resp = block(api.client().connections().get(connection_id)).unwrap_or_else(|e| e.exit());
if let Some(s) = spinner {
s.finish_and_clear();
// Keep the spinner table-only (scripting output stays clean), but route the
// interactive path through the wakeup hint so a cold KEDA start is explained.
let resp = if is_table {
block_with_wakeup(
&api,
"Fetching connection...",
api.client().connections().get(connection_id),
)
} else {
block(api.client().connections().get(connection_id))
}
.unwrap_or_else(|e| e.exit());
let detail = ConnectionDetail {
id: resp.id,
name: resp.name,
Expand Down Expand Up @@ -327,16 +344,16 @@ pub fn create(workspace_id: &str, name: &str, source_type: &str, config: &str, f
source_type.to_string(),
);

let spinner = is_table.then(|| crate::util::spinner("Creating connection..."));
let resp = block(api.client().connections().create(request)).unwrap_or_else(|e| {
if let Some(s) = &spinner {
s.finish_and_clear();
}
e.exit()
});
if let Some(s) = &spinner {
s.finish_and_clear();
let resp = if is_table {
block_with_wakeup(
&api,
"Creating connection...",
api.client().connections().create(request),
)
} else {
block(api.client().connections().create(request))
}
.unwrap_or_else(|e| e.exit());

let result = CreateResponse {
id: resp.id,
Expand Down Expand Up @@ -404,7 +421,12 @@ pub fn create(workspace_id: &str, name: &str, source_type: &str, config: &str, f

pub fn list(workspace_id: &str, format: &str) {
let api = Api::new(Some(workspace_id));
let resp = block(api.client().connections().list()).unwrap_or_else(|e| e.exit());
let resp = block_with_wakeup(
&api,
"Loading connections…",
api.client().connections().list(),
)
.unwrap_or_else(|e| e.exit());
let body = ListResponse {
connections: resp
.connections
Expand Down
10 changes: 6 additions & 4 deletions src/connections_new.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use inquire::validator::Validation;
use inquire::{Confirm, Password, Select, Text};
use serde_json::{Map, Number, Value};

use crate::sdk::{Api, ApiError, block};
use crate::sdk::{Api, ApiError, block, block_with_wakeup};

// ── SDK helpers ─────────────────────────────────────────────────────────────

Expand Down Expand Up @@ -326,9 +326,11 @@ pub fn run(workspace_id: &str) {
}
}

let create_spinner = crate::util::spinner("Creating connection...");
let result = block(api.client().connections().create(request));
create_spinner.finish_and_clear();
let result = block_with_wakeup(
&api,
"Creating connection...",
api.client().connections().create(request),
);

use crossterm::style::Stylize;
let result = match result {
Expand Down
15 changes: 11 additions & 4 deletions src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,8 +131,12 @@ fn fetch_context(api: &Api, database_id: &str, name: &str) -> Option<DatabaseCon

pub fn list(workspace_id: &str, database_id: &str, prefix: Option<&str>, format: &str) {
let api = Api::new(Some(workspace_id));
let body = crate::sdk::block(api.client().database_context().list(database_id))
.unwrap_or_else(|e| e.exit());
let body = crate::sdk::block_with_wakeup(
&api,
"Loading context…",
api.client().database_context().list(database_id),
)
.unwrap_or_else(|e| e.exit());

let mut rows: Vec<ContextRow> = body.contexts.into_iter().map(ContextRow::from).collect();
if let Some(p) = prefix {
Expand Down Expand Up @@ -295,8 +299,11 @@ pub fn push(workspace_id: &str, database_id: &str, name: &str, dry_run: bool) {

let api = Api::new(Some(workspace_id));
let request = UpsertDatabaseContextRequest::new(content, name.clone());
let resp = match crate::sdk::block(api.client().database_context().upsert(database_id, request))
{
let resp = match crate::sdk::block_with_wakeup(
&api,
"Pushing context…",
api.client().database_context().upsert(database_id, request),
) {
Ok(resp) => resp,
Err(ApiError::Status { status: _, body }) => {
let msg = crate::util::api_error(body);
Expand Down
33 changes: 21 additions & 12 deletions src/databases.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::sdk::{Api, ApiError, block, none_if_404};
use crate::sdk::{Api, ApiError, block, block_with_wakeup, none_if_404};
use indicatif::{ProgressBar, ProgressStyle};
use serde::{Deserialize, Serialize};
use std::path::Path;
Expand Down Expand Up @@ -139,8 +139,12 @@ pub(crate) fn get_database(api: &Api, id: &str) -> Result<Database, ApiError> {

/// List databases through the SDK's typed `databases().list` handle, mapped
/// into the CLI's summary rows.
///
/// Routed through [`block_with_wakeup`] so a cold KEDA start surfaces a "waking
/// up worker" hint instead of an unexplained pause — `databases list` is a
/// common first command against an idle workspace.
fn list_database_summaries(api: &Api) -> Result<Vec<DatabaseSummary>, ApiError> {
block(api.client().databases().list())
block_with_wakeup(api, "Loading databases…", api.client().databases().list())
.map(|r| r.databases.into_iter().map(DatabaseSummary::from).collect())
}

Expand Down Expand Up @@ -678,16 +682,16 @@ pub fn create(
let request = create_database_typed_request(name, catalog, schema, tables, expires_at);

let api = Api::new(Some(workspace_id));
let spinner = (format == "table").then(|| crate::util::spinner("Creating database..."));
let resp = block(api.client().databases().create(request)).unwrap_or_else(|e| {
if let Some(s) = &spinner {
s.finish_and_clear();
}
e.exit()
});
if let Some(s) = &spinner {
s.finish_and_clear();
let resp = if format == "table" {
block_with_wakeup(
&api,
"Creating database...",
api.client().databases().create(request),
)
} else {
block(api.client().databases().create(request))
}
.unwrap_or_else(|e| e.exit());

let result = CreateDatabaseResponse {
id: resp.id,
Expand Down Expand Up @@ -794,7 +798,12 @@ pub fn delete(workspace_id: &str, id_or_name: &str) {

let api = Api::new(Some(workspace_id));
let db = resolve_database(&api, id_or_name);
block(api.client().databases().delete(&db.id)).unwrap_or_else(|e| e.exit());
block_with_wakeup(
&api,
"Deleting database…",
api.client().databases().delete(&db.id),
)
.unwrap_or_else(|e| e.exit());

// If the deleted database was the current one, clear it so subsequent
// commands don't silently send a stale X-Database-Id header.
Expand Down
29 changes: 21 additions & 8 deletions src/datasets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,9 @@ pub fn create_from_saved_query(
pub fn list(workspace_id: &str, limit: Option<u32>, offset: Option<u32>, format: &str) {
let api = Api::new(Some(workspace_id));

let body = crate::sdk::block(
let body = crate::sdk::block_with_wakeup(
&api,
"Loading datasets…",
api.client()
.datasets()
.list(limit.map(|l| l as i32), offset.map(|o| o as i32)),
Expand Down Expand Up @@ -219,8 +221,12 @@ pub fn list(workspace_id: &str, limit: Option<u32>, offset: Option<u32>, format:
pub fn get(dataset_id: &str, workspace_id: &str, format: &str) {
let api = Api::new(Some(workspace_id));

let resp: GetDatasetResponse =
crate::sdk::block(api.client().datasets().get(dataset_id)).unwrap_or_else(|e| e.exit());
let resp: GetDatasetResponse = crate::sdk::block_with_wakeup(
&api,
"Loading dataset…",
api.client().datasets().get(dataset_id),
)
.unwrap_or_else(|e| e.exit());

let d = DatasetDetail {
id: resp.id,
Expand Down Expand Up @@ -295,9 +301,12 @@ pub fn update(
request.table_name = Some(Some(n.to_string()));
}

let resp: UpdateDatasetResponse =
crate::sdk::block(api.client().datasets().update(dataset_id, request))
.unwrap_or_else(|e| e.exit());
let resp: UpdateDatasetResponse = crate::sdk::block_with_wakeup(
&api,
"Updating dataset…",
api.client().datasets().update(dataset_id, request),
)
.unwrap_or_else(|e| e.exit());
let d = UpdateView::from(resp);

use crossterm::style::Stylize;
Expand Down Expand Up @@ -341,8 +350,12 @@ pub fn refresh(workspace_id: &str, dataset_id: &str, async_mode: bool) {
request.r#async = Some(true);
}

let resp =
crate::sdk::block(api.client().refresh().refresh(request)).unwrap_or_else(|e| e.exit());
let resp = crate::sdk::block_with_wakeup(
&api,
"Refreshing dataset…",
api.client().refresh().refresh(request),
)
.unwrap_or_else(|e| e.exit());

if async_mode {
let job_id = match &resp {
Expand Down
49 changes: 35 additions & 14 deletions src/embedding_providers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,16 @@ fn parse_config(raw: Option<&str>) -> Option<serde_json::Value> {

pub fn list(workspace_id: &str, format: &str) {
let api = Api::new(Some(workspace_id));
let providers: Vec<Provider> = crate::sdk::block(api.client().embedding_providers().list())
.unwrap_or_else(|e| e.exit())
.embedding_providers
.into_iter()
.map(Provider::from)
.collect();
let providers: Vec<Provider> = crate::sdk::block_with_wakeup(
&api,
"Loading embedding providers…",
api.client().embedding_providers().list(),
)
.unwrap_or_else(|e| e.exit())
.embedding_providers
.into_iter()
.map(Provider::from)
.collect();

use crossterm::style::Stylize;
match format {
Expand Down Expand Up @@ -80,9 +84,13 @@ pub fn list(workspace_id: &str, format: &str) {

pub fn get(workspace_id: &str, id: &str, format: &str) {
let api = Api::new(Some(workspace_id));
let p: Provider = crate::sdk::block(api.client().embedding_providers().get(id))
.unwrap_or_else(|e| e.exit())
.into();
let p: Provider = crate::sdk::block_with_wakeup(
&api,
"Loading embedding provider…",
api.client().embedding_providers().get(id),
)
.unwrap_or_else(|e| e.exit())
.into();

match format {
"json" => println!("{}", serde_json::to_string_pretty(&p).unwrap()),
Expand Down Expand Up @@ -128,8 +136,12 @@ pub fn create(
req.secret_name = Some(Some(s.to_string()));
}

let resp = crate::sdk::block(api.client().embedding_providers().create(req))
.unwrap_or_else(|e| e.exit());
let resp = crate::sdk::block_with_wakeup(
&api,
"Creating embedding provider…",
api.client().embedding_providers().create(req),
)
.unwrap_or_else(|e| e.exit());
let parsed = serde_json::to_value(&resp).unwrap_or_default();

eprintln!("{}", "Embedding provider created.".green());
Expand Down Expand Up @@ -180,8 +192,12 @@ pub fn update(
req.secret_name = Some(Some(s.to_string()));
}

let resp = crate::sdk::block(api.client().embedding_providers().update(id, req))
.unwrap_or_else(|e| e.exit());
let resp = crate::sdk::block_with_wakeup(
&api,
"Updating embedding provider…",
api.client().embedding_providers().update(id, req),
)
.unwrap_or_else(|e| e.exit());
let resp = serde_json::to_value(&resp).unwrap_or_default();

eprintln!("{}", "Embedding provider updated.".green());
Expand All @@ -202,7 +218,12 @@ pub fn update(
pub fn delete(workspace_id: &str, id: &str) {
use crossterm::style::Stylize;
let api = Api::new(Some(workspace_id));
crate::sdk::block(api.client().embedding_providers().delete(id)).unwrap_or_else(|e| e.exit());
crate::sdk::block_with_wakeup(
&api,
"Deleting embedding provider…",
api.client().embedding_providers().delete(id),
)
.unwrap_or_else(|e| e.exit());
println!("{}", format!("Embedding provider '{id}' deleted.").green());
}

Expand Down
10 changes: 7 additions & 3 deletions src/indexes.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::sdk::{Api, block, none_if_404};
use crate::sdk::{Api, block, block_with_wakeup, none_if_404};
use rayon::prelude::*;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
Expand Down Expand Up @@ -548,12 +548,16 @@ pub fn delete(workspace_id: &str, scope: IndexScope<'_>, index_name: &str) {
connection_id,
schema,
table,
} => block(
} => block_with_wakeup(
&api,
"Deleting index…",
api.client()
.indexes()
.delete_index(connection_id, schema, table, index_name),
),
IndexScope::Dataset { dataset_id } => block(
IndexScope::Dataset { dataset_id } => block_with_wakeup(
&api,
"Deleting index…",
api.client()
.indexes()
.delete_dataset_index(dataset_id, index_name),
Expand Down
7 changes: 4 additions & 3 deletions src/jobs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,10 @@ fn parse_job_type(s: &str) -> Option<JobType> {

pub fn get(job_id: &str, workspace_id: &str, format: &str) {
let api = Api::new(Some(workspace_id));
let job: Job = crate::sdk::block(api.client().jobs().get(job_id))
.unwrap_or_else(|e| e.exit())
.into();
let job: Job =
crate::sdk::block_with_wakeup(&api, "Loading job…", api.client().jobs().get(job_id))
.unwrap_or_else(|e| e.exit())
.into();

match format {
"json" => println!("{}", serde_json::to_string_pretty(&job).unwrap()),
Expand Down
Loading
Loading