How `query_coco_fusion` Integrates Multiple Backend Services: The Complete Pattern

query_coco_fusion unifies searches across heterogeneous backend services through a trait-based registry pattern that executes queries in parallel with timeout isolation and merges results using fair distribution algorithms.

The query_coco_fusion command serves as the central orchestration point in the infinilabs/coco-app repository, enabling a Rust-based desktop application to aggregate search results from remote HTTP APIs, local filesystems, and OS-level services through a single interface. This integration pattern relies on a plugin architecture that allows new backends to register at runtime without modifying core query logic, providing resilience against service failures while ensuring equitable result distribution.

The SearchSource Trait Registration Pattern

Every searchable backend in Coco implements the SearchSource trait defined in src-tauri/src/common/traits.rs. This contract standardizes how the system interacts with diverse data sources, requiring implementers to provide a get_type method identifying the source and a search method handling the actual query execution.

Registration occurs through the SearchSourceRegistry in src-tauri/src/common/register.rs, which maintains a runtime collection of available sources. During application initialization, concrete implementations—such as CocoSearchSource for remote servers or filesystem-based extensions—register themselves with the global registry, making them immediately available to the fusion engine without recompilation.

Entry Point and Dispatch Logic

The frontend initiates searches through platformAdapter.commands("query_coco_fusion", payload), handled by the Rust command in src-tauri/src/search/mod.rs (lines 40-84). This entry point receives:

  • Pagination controls (from, size)
  • A map of query_strings containing search terms
  • A query_timeout value in milliseconds

Single vs. Multi-Source Routing

The dispatcher examines the presence of a querysource parameter to determine execution strategy:

  • Single-source mode: Routes to query_coco_fusion_single_query_source when querying one specific backend by ID
  • Multi-source mode: Invokes query_coco_fusion_multi_query_sources to query all registered sources simultaneously

This branching allows the same command interface to serve both targeted queries and broad aggregation use cases.

Parallel Execution with Timeout Isolation

In multi-source mode, the system executes searches concurrently using FuturesUnordered collections wrapped with tokio::time::timeout (lines 20-38 in src-tauri/src/search/mod.rs). Each registered SearchSource spawns as an async future, allowing true parallel execution rather than sequential polling.

If a backend exceeds its timeout threshold, the system logs a warning and invokes query_coco_fusion_handle_failed_request to record the failure in the response's failed array without aborting the entire request. This pattern ensures that slow or unresponsive services cannot block results from healthy backends.

Concrete Backend Implementation Examples

Coco Server HTTP Source

The primary remote backend, implemented in src-tauri/src/server/search.rs, demonstrates HTTP integration. CocoSearchSource constructs POST requests to the /_search endpoint, converting query parameters into URL-encoded strings:

let url = "/query/_search";
let mut query_params = vec![
    format!("from={}", query.from),
    format!("size={}", query.size),
];
for (k, v) in query.query_strings {
    if let Some(p) = convert_query_string(&k, &v) {
        query_params.push(p);
    }
}
let response = HttpClient::post(&self.server.id, url, Some(query_params), Some(body))
    .await
    .context(HttpSnafu)?;

Extension and Local Sources

Additional backends in src-tauri/src/extension/** handle window management queries, filesystem search, calculator functions, and third-party extensions. Each implements the search method using its specific data retrieval mechanism while returning standardized QueryResponse objects containing hits, total_hits, and optional aggregations.

Result Aggregation and Fair Distribution

The fusion algorithm prevents single-source dominance through a two-phase distribution strategy in src-tauri/src/search/mod.rs (lines 29-45):

  1. Minimum allocation: First collects max_hits_per_source hits from each contributing backend
  2. Merit-based remainder: Fills remaining slots with highest-scoring hits from the pruned results across all sources

After collection, re_score_hits normalizes relevance scores across different ranking systems, ensuring the final MultiSourceQueryResponse presents coherent ordering despite originating from heterogeneous sources. The system merges facet aggregations via merge_aggregations (lines 57-61).

Frontend Integration Pattern

Consumer code interacts with this architecture through a consistent command interface:

// src/hooks/useSearch.ts
const response = await platformAdapter.commands("query_coco_fusion", {
  from: 0,
  size: 20,
  query_strings: { 
    query: searchText,
    // Optional: querysource: "coco-servers" to target specific backend
  },
  query_timeout: 3000,
});

The function returns a MultiSourceQueryResponse containing the merged hits array, a failed array listing any sources that errored or timed out, total_hits, and optional aggregation data.

Implementing a Custom Backend

Developers extend the system by implementing the SearchSource trait and registering during app initialization:

use crate::common::traits::SearchSource;
use crate::common::search::{SearchQuery, QueryResponse};

pub struct MyCustomSearchSource;

#[async_trait::async_trait]
impl SearchSource for MyCustomSearchSource {
    fn get_type(&self) -> QuerySource {
        QuerySource {
            r#type: "my-custom".into(),
            name: "My Custom Service".into(),
            id: "my_custom".into(),
        }
    }

    async fn search(
        &self,
        _app: AppHandle,
        query: SearchQuery,
    ) -> Result<QueryResponse, SearchError> {
        // Backend-specific query logic here
        Ok(QueryResponse {
            hits: vec![],
            total_hits: 0,
            // ... other fields
        })
    }
}

Registration code:

let registry = app_handle.state::<SearchSourceRegistry>();
registry.register_source(MyCustomSearchSource::new()).await;

Summary

  • query_coco_fusion in src-tauri/src/search/mod.rs serves as the unified entry point for all search operations, handling both single-source and multi-source queries
  • The SearchSource trait and SearchSourceRegistry enable runtime extensibility without requiring modifications to core fusion logic
  • Parallel execution via FuturesUnordered with tokio::time::timeout ensures resilience against slow or failing backends while collecting partial results
  • Fair distribution algorithms prevent result flooding from any single source, and re_score_hits provides unified ranking across heterogeneous backends
  • The pattern exposes a consistent API to frontend consumers while abstracting the complexity of coordinating multiple disparate data sources

Frequently Asked Questions

How does query_coco_fusion handle timeouts from slow backend services?

The system wraps each backend query in a tokio::time::timeout future according to the query_timeout parameter. When a source exceeds this limit, the error is caught and passed to query_coco_fusion_handle_failed_request, which records the failure in the response's failed array while allowing other sources to complete normally. This ensures that a single slow backend cannot block the entire search operation.

Can I query only specific backend services instead of all registered sources?

Yes. By including a querysource field in the query payload, the command routes to query_coco_fusion_single_query_source rather than the multi-source variant. This targets a specific backend by its registered ID, bypassing the parallel execution and aggregation logic to return results from only that source.

What prevents one backend from dominating the search results?

The query_coco_fusion_multi_query_sources function implements an even hit distribution algorithm that first allocates a minimum slice (max_hits_per_source) from every responding backend before filling remaining slots with the highest-scoring documents from the pooled results. This guarantees that every functional source contributes at least some results, preventing scenarios where a high-volume backend overwhelms narrower, more specific sources.

How do I add a new backend service to the Coco app?

Create a struct implementing the SearchSource trait from src-tauri/src/common/traits.rs, defining the get_type metadata and search execution logic. Register the implementation during app initialization using SearchSourceRegistry from src-tauri/src/common/register.rs. Once registered, query_coco_fusion automatically includes your backend in multi-source queries without additional configuration.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →