laburnum 1.17.2

An LSP framework for building language servers and compilers, powered by an incremental query tree with content-addressed storage, task-based dataflow, and parallel queries.
Documentation
// Copyright Two Neutron Stars Incorporated and contributors
// SPDX-License-Identifier: BlueOak-1.0.0

use {
  crate::{
    Ident,
    database::storage::Partitions,
    protocol::{
      jsonrpc,
      lsp::{
        LSPAny,
        LanguageServer,
      },
    },
    record::LaburnumRecordRef,
    scheduler::task::TaskContext,
  },
  otel::exception,
  serde_json::Value,
};

pub async fn handle_query_records<P: Partitions, T: LanguageServer<P>>(
  arguments: &[Value],
  ctx: &mut TaskContext<P, T>,
) -> jsonrpc::Result<Option<LSPAny>> {
  let arg = arguments.first().ok_or_else(|| {
    exception!(
      "invalid_params",
      jsonrpc::Error::invalid_params("Missing arguments object")
    )
  })?;

  let partition_key: Ident = arg
    .get("partitionKey")
    .and_then(|v| serde_json::from_value(v.clone()).ok())
    .ok_or_else(|| {
      exception!(
        "invalid_params",
        jsonrpc::Error::invalid_params(
          "Missing or invalid 'partitionKey' field"
        )
      )
    })?;

  let _get_latest_only = match arg.get("latest") {
    | None => false,
    | Some(v) => {
      v.as_bool().ok_or_else(|| {
        exception!(
          "invalid_params",
          jsonrpc::Error::invalid_params(
            "Invalid value for 'latest', accepts true or false"
          )
        )
      })?
    },
  };

  let _sort_key_type = if let Some(sort_key_param) = arg.get("sortKey") {
    if sort_key_param.is_string() {
      "exact"
    } else if sort_key_param.is_object() {
      "prefix"
    } else {
      "unknown"
    }
  } else {
    "all"
  };

  let query_client = ctx.query_client();

  let query_results = if arg.get("sortKey").is_some() {
    // ADR0011: typed sort keys cannot be reconstructed from arbitrary JSON
    // strings, so string-keyed exact/prefix filtering is no longer supported
    // here. Only the unfiltered listing remains.
    return Err(exception!(
      "invalid_params",
      jsonrpc::Error::invalid_params(
        "sortKey filtering is not supported for query_records with typed sort \
         keys (ADR0011); omit sortKey to list the whole partition"
      )
    ));
  } else {
    query_client.get_record_internal(partition_key, None).await
  };

  let resolver = ctx.source_cache_reader();
  let source_cache = ctx.source_cache();
  let source_cache_guard = source_cache.read();

  let records: Vec<Value> = query_results
    .iter_with_metadata()
    .filter_map(|(record_meta, record_ref)| {
      let record_ref = record_ref?;

      let serialized = serde_json::value::Serializer;
      let mut record_value = match record_ref
        .serialize_with_source_cache(&source_cache_guard, serialized)
      {
        | Ok(value) => value,
        | Err(_e) => {
          return None;
        },
      };

      if let Some(obj) = record_value.as_object_mut() {
        obj.insert(
          "partition_key".to_string(),
          serde_json::to_value(record_meta.partition_key)
            .unwrap_or(serde_json::Value::Null),
        );
        obj.insert(
          "sort_key".to_string(),
          serde_json::Value::String(
            crate::database::partitions::PartitionSortKey::resolve(
              &record_meta.sort_key,
              &resolver,
            ),
          ),
        );

        obj.insert(
          "content_hash".to_string(),
          serde_json::to_value(record_meta.content_hash)
            .unwrap_or(serde_json::Value::Null),
        );
      }

      Some(record_value)
    })
    .collect();

  Ok(Some(serde_json::json!(records)))
}