# SearchLibrarySemanticallyQuery

- File ID: file:qbybjm:searchlibrarysemanticallyquery-cs
- Path: NexusReader.Application/Queries/Library/SearchLibrarySemanticallyQuery.cs
- Role: handler
- Layer: application

## Purpose

Provides a MediatR query and handler that performs a semantic search over a tenant-scoped semantic knowledge cache: it generates an embedding for the input query (with retry), runs a vector similarity DB query, maps results to DTOs, and returns them.

## Key Details

Uses a resilience pipeline named "ai-retry" to wrap embedding generation, computes cosine distance using Pgvector and orders DB results by similarity, then maps entities to SemanticSearchResultDto and returns a FluentResults.Result.

## Symbols

- SearchLibrarySemanticallyQueryHandler: Provides a MediatR query and handler that performs a semantic search over a tenant-scoped semantic knowledge cache: it generates an embedding for the input query (with retry), runs a vector similarity DB query, maps results to DTOs, and returns them.
- SearchLibrarySemanticallyQueryHandler(): Constructor that stores injected services and obtains a named resilience pipeline for retries.
- Handle(): Executes a semantic search: validates input, obtains an embedding with retry, queries the DB for nearest cached vectors for the tenant, maps to DTOs and returns a Result.
- SearchLibrarySemanticallyQuery: CQRS request record carrying query text, tenant id and optional limit for semantic search.
- SearchLibrarySemanticallyQueryHandler: MediatR handler that orchestrates embedding generation, resilient execution, DB similarity query and mapping to DTOs.

## Dependencies

- No resolved dependencies.

## Calls

- No resolved calls.

## Unresolved References

- dependency-target: NexusReader.Data.Persistence (imported at line 15)
- dependency-target: Mapster/MapsterMapper (imported at lines 12-13)
- dependency-target: MediatR (imported line 2)
- dependency-target: Pgvector (imported lines 3-4)
- dependency-target: Microsoft.Extensions.Resilience / Polly (lines 9-11)
- call-target: unknown
- call-target: unknown
- call-target: unknown
- call-target: unknown
- call-target: unknown
- interaction-target: .Where(c => c.TenantId == request.TenantId && c.Embedding != null)
- interaction-target: pipelineProvider.GetPipeline("ai-retry") used to set _retryPipeline
- interaction-target: _embeddingGenerator.GenerateAsync called with request.QueryText

## Coverage

- Symbols: 5
- Executable symbols: 2
- Executable symbols with control flow: 2
- Grounded edges: 5
- Unresolved references: 13
- Control-flow fragments: 2
- Unresolved jumps: 5
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 2
- Generated diagrams: 4

## Control Flow Fragments

- SearchLibrarySemanticallyQueryHandler: 5 nodes, 4 edges, 1 jumps, 0 unsupported constructs
- Handle: 27 nodes, 29 edges, 4 jumps, 0 unsupported constructs

## Diagrams

### SearchLibrarySemanticallyQuery Neighborhood

```mermaid
flowchart LR
    class_1x3939l_searchlibrarysemanticallyqueryhandler("SearchLibrarySemanticallyQueryHandler")
    file_qbybjm_searchlibrarysemanticallyquery_cs("SearchLibrarySemanticallyQuery")
    method_17jd9c8_searchlibrarysemanticallyqueryhandler[["SearchLibrarySemanticallyQueryHandler()"]]
    method_1bus1hn_handle[["Handle()"]]
    type_165f8vd_searchlibrarysemanticallyqueryhandler[/"SearchLibrarySemanticallyQueryHandler"/]
    type_17161bt_searchlibrarysemanticallyquery[/"SearchLibrarySemanticallyQuery"/]
```

### SearchLibrarySemanticallyQuery Execution Overview

```mermaid
flowchart TD
    class_1x3939l_searchlibrarysemanticallyqueryhandler("SearchLibrarySemanticallyQueryHandler")
    method_17jd9c8_searchlibrarysemanticallyqueryhandler[["SearchLibrarySemanticallyQueryHandler()"]]
    method_1bus1hn_handle[["Handle()"]]
    unresolved_unresolved_1gdzso6_interaction_target{"Unresolved: _embeddingGenerator.GenerateAsync called with request.QueryText"}
    unresolved_unresolved_1nh5es3_call_target{"Unresolved: GetPipeline"}
    unresolved_unresolved_1oqa70v_call_target{"Unresolved: CreateDbContextAsync"}
    unresolved_unresolved_1ubjsmz_interaction_target{"Unresolved: pipelineProvider.GetPipeline(\\"ai-retry\\") used to set _retryPipeline"}
    unresolved_unresolved_1ywu2kl_call_target{"Unresolved: ExecuteAsync"}
    unresolved_unresolved_2r3zjw_interaction_target{"Unresolved: .Where(c => c.TenantId == request.TenantId && c.Embedding != null)"}
    unresolved_unresolved_8t3u5h_call_target{"Unresolved: GenerateAsync"}
    unresolved_unresolved_rglo3u_call_target{"Unresolved: Map"}
    class_1x3939l_searchlibrarysemanticallyqueryhandler -->|contains| method_17jd9c8_searchlibrarysemanticallyqueryhandler
    class_1x3939l_searchlibrarysemanticallyqueryhandler -->|contains| method_1bus1hn_handle
    class_1x3939l_searchlibrarysemanticallyqueryhandler -->|unresolved interaction| unresolved_unresolved_1gdzso6_interaction_target
    class_1x3939l_searchlibrarysemanticallyqueryhandler -->|unresolved interaction| unresolved_unresolved_1ubjsmz_interaction_target
    class_1x3939l_searchlibrarysemanticallyqueryhandler -->|unresolved interaction| unresolved_unresolved_2r3zjw_interaction_target
    method_17jd9c8_searchlibrarysemanticallyqueryhandler -->|unresolved call| unresolved_unresolved_1nh5es3_call_target
    method_1bus1hn_handle -->|unresolved call| unresolved_unresolved_1oqa70v_call_target
    method_1bus1hn_handle -->|unresolved call| unresolved_unresolved_1ywu2kl_call_target
    method_1bus1hn_handle -->|unresolved call| unresolved_unresolved_8t3u5h_call_target
    method_1bus1hn_handle -->|unresolved call| unresolved_unresolved_rglo3u_call_target
```

### SearchLibrarySemanticallyQueryHandler() Control Flow

```mermaid
flowchart TD
    method_17jd9c8_searchlibrarysemanticallyqueryhandler__call_37_GetPipeline[["GetPipeline"]]
    method_17jd9c8_searchlibrarysemanticallyqueryhandler__action_35_field_assignment_35__linear("Assigns injected dependencies")
    method_17jd9c8_searchlibrarysemanticallyqueryhandler__entry(["SearchLibrarySemanticallyQueryHandler entry"])
    method_17jd9c8_searchlibrarysemanticallyqueryhandler__action_37_external_call_37__linear("Resilience pipeline lookup")
    method_17jd9c8_searchlibrarysemanticallyqueryhandler__implicit_return(["return"])
    method_17jd9c8_searchlibrarysemanticallyqueryhandler__action_35_field_assignment_35__linear -->|next| method_17jd9c8_searchlibrarysemanticallyqueryhandler__action_37_external_call_37__linear
    method_17jd9c8_searchlibrarysemanticallyqueryhandler__action_37_external_call_37__linear -->|string ai-retry| method_17jd9c8_searchlibrarysemanticallyqueryhandler__call_37_GetPipeline
    method_17jd9c8_searchlibrarysemanticallyqueryhandler__call_37_GetPipeline -->|return| method_17jd9c8_searchlibrarysemanticallyqueryhandler__implicit_return
    method_17jd9c8_searchlibrarysemanticallyqueryhandler__entry -->|next| method_17jd9c8_searchlibrarysemanticallyqueryhandler__action_35_field_assignment_35__linear
```

### Handle() Control Flow

_Warnings: diagram method_1bus1hn_handle__fragment_diagram exceeds preferred complexity thresholds (27 nodes, 29 edges)._

```mermaid
---
config:
  flowchart:
    defaultRenderer: "elk"
---
flowchart TD
    method_1bus1hn_handle__call_49_ExecuteAsync[["ExecuteAsync"]]
    method_1bus1hn_handle__call_50_GenerateAsync[["GenerateAsync"]]
    method_1bus1hn_handle__call_53_CreateDbContextAsync[["CreateDbContextAsync"]]
    method_1bus1hn_handle__call_60_Map[["Map"]]
    method_1bus1hn_handle__action_43_guard_clause_43__condition{"string.IsNullOrWhiteSpace(request.QueryText)"}
    method_1bus1hn_handle__action_43_guard_clause_43__false("continue")
    method_1bus1hn_handle__action_43_guard_clause_43__merge("merge")
    method_1bus1hn_handle__action_43_guard_clause_43__true("invalid")
    method_1bus1hn_handle__action_43_handle_branch_43_0__condition{"string.IsNullOrWhiteSpace(request.QueryText)"}
    method_1bus1hn_handle__action_43_handle_branch_43_0__false("false")
    method_1bus1hn_handle__action_43_handle_branch_43_0__merge("merge")
    method_1bus1hn_handle__action_43_handle_branch_43_0__true("true")
    method_1bus1hn_handle__action_49_handle_await_49_2__await[["Waits for async work"]]
    method_1bus1hn_handle__action_49_retry_49__loop_body[["_retryPipeline.ExecuteAsync wraps _embeddingGenerator.GenerateAsync to obtain embedding"]]
    method_1bus1hn_handle__action_49_retry_49__loop_entry("Generate embedding with resilience pipeline")
    method_1bus1hn_handle__action_49_retry_49__loop_exit("exit loop")
    method_1bus1hn_handle__action_50_handle_await_50_3__await[["Waits for async work"]]
    method_1bus1hn_handle__action_53_handle_await_53_4__await[["Waits for async work"]]
    method_1bus1hn_handle__action_54_handle_await_54_5__await[["Waits for async work"]]
    method_1bus1hn_handle__action_54_persistence_read_54__linear("Query SemanticKnowledgeCache for tenant and compute cosine distance")
    method_1bus1hn_handle__action_60_mapping_60__linear("Map entities to DTOs")
    method_1bus1hn_handle__entry(["Handle entry"])
    method_1bus1hn_handle__action_50_external_call_50__linear("Embedding generation")
    method_1bus1hn_handle__action_55_handle_repository_read_55_6__linear[("Reads repository or persistence state")]
    method_1bus1hn_handle__action_45_handle_return_45_1__return(["Returns result"])
    method_1bus1hn_handle__action_61_handle_return_61_7__return(["Returns result"])
    method_1bus1hn_handle__action_61_return_61__return(["Return successful Result with mapped DTOs"])
    method_1bus1hn_handle__action_43_guard_clause_43__condition -->|continue| method_1bus1hn_handle__action_43_guard_clause_43__false
    method_1bus1hn_handle__action_43_guard_clause_43__condition -->|invalid| method_1bus1hn_handle__action_43_guard_clause_43__true
    method_1bus1hn_handle__action_43_guard_clause_43__false -->|next| method_1bus1hn_handle__action_43_guard_clause_43__merge
    method_1bus1hn_handle__action_43_guard_clause_43__merge -->|next| method_1bus1hn_handle__action_43_handle_branch_43_0__condition
    method_1bus1hn_handle__action_43_guard_clause_43__true -->|next| method_1bus1hn_handle__action_43_guard_clause_43__merge
    method_1bus1hn_handle__action_43_handle_branch_43_0__condition -->|false| method_1bus1hn_handle__action_43_handle_branch_43_0__false
    method_1bus1hn_handle__action_43_handle_branch_43_0__condition -->|true| method_1bus1hn_handle__action_43_handle_branch_43_0__true
    method_1bus1hn_handle__action_43_handle_branch_43_0__false -->|next| method_1bus1hn_handle__action_43_handle_branch_43_0__merge
    method_1bus1hn_handle__action_43_handle_branch_43_0__merge -->|return| method_1bus1hn_handle__action_45_handle_return_45_1__return
    method_1bus1hn_handle__action_43_handle_branch_43_0__true -->|next| method_1bus1hn_handle__action_43_handle_branch_43_0__merge
    method_1bus1hn_handle__action_45_handle_return_45_1__return -->|next| method_1bus1hn_handle__action_49_handle_await_49_2__await
    method_1bus1hn_handle__action_49_handle_await_49_2__await -->|next| method_1bus1hn_handle__action_49_retry_49__loop_entry
    method_1bus1hn_handle__action_49_retry_49__loop_body -->|retry| method_1bus1hn_handle__action_49_retry_49__loop_entry
    method_1bus1hn_handle__action_49_retry_49__loop_entry -->|iterate| method_1bus1hn_handle__action_49_retry_49__loop_body
    method_1bus1hn_handle__action_49_retry_49__loop_entry -->|exit| method_1bus1hn_handle__action_49_retry_49__loop_exit
    method_1bus1hn_handle__action_49_retry_49__loop_exit -->|Func CancellationToken, Task Embedding >> that calls _embeddingGenerator.GenerateAsync| method_1bus1hn_handle__call_49_ExecuteAsync
    method_1bus1hn_handle__action_50_external_call_50__linear -->|string request.QueryText cancellation token forwarded| method_1bus1hn_handle__call_50_GenerateAsync
    method_1bus1hn_handle__action_50_handle_await_50_3__await -->|next| method_1bus1hn_handle__action_50_external_call_50__linear
    method_1bus1hn_handle__action_53_handle_await_53_4__await -->|cancellationToken| method_1bus1hn_handle__call_53_CreateDbContextAsync
    method_1bus1hn_handle__action_54_handle_await_54_5__await -->|next| method_1bus1hn_handle__action_54_persistence_read_54__linear
    method_1bus1hn_handle__action_54_persistence_read_54__linear -->|next| method_1bus1hn_handle__action_55_handle_repository_read_55_6__linear
    method_1bus1hn_handle__action_55_handle_repository_read_55_6__linear -->|next| method_1bus1hn_handle__action_60_mapping_60__linear
    method_1bus1hn_handle__action_60_mapping_60__linear -->|List SemanticKnowledgeCache> -> List SemanticSearchResultDto>| method_1bus1hn_handle__call_60_Map
    method_1bus1hn_handle__action_61_handle_return_61_7__return -->|return| method_1bus1hn_handle__action_61_return_61__return
    method_1bus1hn_handle__call_49_ExecuteAsync -->|next| method_1bus1hn_handle__action_50_handle_await_50_3__await
    method_1bus1hn_handle__call_50_GenerateAsync -->|next| method_1bus1hn_handle__action_53_handle_await_53_4__await
    method_1bus1hn_handle__call_53_CreateDbContextAsync -->|next| method_1bus1hn_handle__action_54_handle_await_54_5__await
    method_1bus1hn_handle__call_60_Map -->|return| method_1bus1hn_handle__action_61_handle_return_61_7__return
    method_1bus1hn_handle__entry -->|next| method_1bus1hn_handle__action_43_guard_clause_43__condition
```

## Diagram Validation

- Status: warn
- Warning: Control-flow extraction left 5 unresolved jumps.
- Warning: control-flow: diagram method_1bus1hn_handle__fragment_diagram exceeds preferred complexity thresholds (27 nodes, 29 edges).
