relay-knowledge 1.1.16

Graph-database-based knowledge graph project.
Documentation
use crate::{
    api::{ApiStreamEvent, CodeRepositoryIndexStartResponse, RequestContext, StreamEventKind},
    application::RelayKnowledgeService,
    domain::{CodeIndexTaskState, CodeRepositorySelector},
};

use super::{CliError, OutputFormat, serialize_line};

#[derive(serde::Serialize)]
pub(super) struct CodeIndexWorkerRunResponse {
    pub(super) claimed: bool,
    pub(super) task: Option<crate::domain::CodeIndexTaskRecord>,
    pub(super) maintenance_active: bool,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub(super) maintenance_error: Option<String>,
}

pub(super) fn render_index_worker_response(
    response: &CodeIndexWorkerRunResponse,
    format: OutputFormat,
) -> Result<String, CliError> {
    if format != OutputFormat::StreamingJson {
        return serialize_line(response);
    }
    let payload = serde_json::to_value(response)
        .map_err(|error| CliError::RenderFailed(error.to_string()))?;
    let events = [
        index_worker_event(StreamEventKind::Started, "index worker started", None),
        index_worker_event(StreamEventKind::Item, "index worker result", Some(payload)),
        index_worker_event(StreamEventKind::Completed, "index worker completed", None),
    ];
    let mut output = String::new();
    for event in events {
        output.push_str(&serialize_line(&event)?);
    }

    Ok(output)
}

pub(super) async fn finish_started_index_task(
    service: &RelayKnowledgeService,
    response: &mut CodeRepositoryIndexStartResponse,
    selector: CodeRepositorySelector,
    context: RequestContext,
    format: OutputFormat,
) -> Result<(), CliError> {
    let Some(task_id) = response.task.as_ref().map(|task| task.task_id.clone()) else {
        return Ok(());
    };
    if response.task.as_ref().map(|task| task.state) != Some(CodeIndexTaskState::Running) {
        let completed = service
            .run_code_index_task_once_with_response(Some(task_id), context.clone())
            .await
            .map_err(|error| CliError::api_failed(error, format))?;
        if let Some((task, indexed)) = completed {
            response.task = Some(task);
            response.summary = Some(indexed.summary);
        }
    }
    let requested_ref = selector.ref_selector.clone();
    let status = service
        .code_repository_status(selector.clone(), context)
        .await
        .map_err(|error| CliError::api_failed(error, format))?;
    response.status = status.status;
    response.scope = crate::api::CodeRepositoryScopeMetadata::from_status(
        &response.status,
        &selector,
        requested_ref,
    );
    response.checkpoint = status.checkpoint;

    Ok(())
}

fn index_worker_event(
    event: StreamEventKind,
    message: &str,
    payload: Option<serde_json::Value>,
) -> ApiStreamEvent {
    ApiStreamEvent {
        event,
        operation: "code.repo.index_worker".to_owned(),
        message: Some(message.to_owned()),
        project_name: None,
        runtime: None,
        payload,
        error_kind: None,
        metadata: None,
    }
}