Skip to main content

IndexCoordinator

Struct IndexCoordinator 

Source
pub struct IndexCoordinator { /* private fields */ }
Expand description

Coordinates index lifecycle, state transitions, and handler queries

The IndexCoordinator wraps WorkspaceIndex with explicit state management, enabling LSP handlers to query the index readiness and implement appropriate fallback behavior when the index is not fully ready.

§Architecture

LspServer
  └── IndexCoordinator
        ├── state: Arc<RwLock<IndexState>>
        ├── index: Arc<WorkspaceIndex>
        ├── limits: IndexResourceLimits
        ├── caps: IndexPerformanceCaps
        ├── metrics: IndexMetrics
        └── instrumentation: IndexInstrumentation

§State Management

The coordinator manages three states:

  • Building: Initial scan or recovery in progress
  • Ready: Fully indexed and available for queries
  • Degraded: Available but with reduced functionality

§Performance Characteristics

  • State checks are lock-free reads (cloned state, <100ns)
  • State transitions use write locks (rare, <1μs)
  • Query dispatch has zero overhead in Ready state
  • Degradation detection is atomic (<10ns per check)

§Usage

use perl_parser::workspace_index::{IndexCoordinator, IndexState};

let coordinator = IndexCoordinator::new();
assert!(matches!(coordinator.state(), IndexState::Building { .. }));

// Transition to ready after indexing
coordinator.transition_to_ready(100, 5000);
assert!(matches!(coordinator.state(), IndexState::Ready { .. }));

// Query with degradation handling
let _result = coordinator.query(
    |index| index.find_definition("my_function"), // full query
    |_index| None                                 // partial fallback
);

Implementations§

Source§

impl IndexCoordinator

Source

pub fn new() -> IndexCoordinator

Create a new coordinator in Building state

Initializes the coordinator with default resource limits and an empty workspace index ready for initial scan.

§Returns

A coordinator initialized in IndexState::Building.

§Examples
use perl_parser::workspace_index::IndexCoordinator;

let coordinator = IndexCoordinator::new();
Source

pub fn with_limits(limits: IndexResourceLimits) -> IndexCoordinator

Create a coordinator with custom resource limits

§Arguments
  • limits - Custom resource limits for this workspace
§Returns

A coordinator configured with the provided resource limits.

§Examples
use perl_parser::workspace_index::{IndexCoordinator, IndexResourceLimits};

let limits = IndexResourceLimits::default();
let coordinator = IndexCoordinator::with_limits(limits);
Source

pub fn with_limits_and_caps( limits: IndexResourceLimits, caps: IndexPerformanceCaps, ) -> IndexCoordinator

Create a coordinator with custom limits and performance caps

§Arguments
  • limits - Resource limits for this workspace
  • caps - Performance caps for indexing budgets
Source

pub fn state(&self) -> IndexState

Get current state (lock-free read via clone)

Returns a cloned copy of the current state for lock-free access in hot path LSP handlers.

§Returns

The current IndexState snapshot.

§Examples
use perl_parser::workspace_index::{IndexCoordinator, IndexState};

let coordinator = IndexCoordinator::new();
match coordinator.state() {
    IndexState::Ready { .. } => {
        // Full query path
    }
    _ => {
        // Degraded/building fallback
    }
}
Source

pub fn index(&self) -> &Arc<WorkspaceIndex>

Get reference to the underlying workspace index

Provides direct access to the WorkspaceIndex for operations that don’t require state checking (e.g., document store access).

§Returns

A shared reference to the underlying workspace index.

§Examples
use perl_parser::workspace_index::IndexCoordinator;

let coordinator = IndexCoordinator::new();
let _index = coordinator.index();
Source

pub fn limits(&self) -> &IndexResourceLimits

Access the configured resource limits

Source

pub fn performance_caps(&self) -> &IndexPerformanceCaps

Access the configured performance caps

Source

pub fn instrumentation_snapshot(&self) -> IndexInstrumentationSnapshot

Snapshot lifecycle instrumentation (durations, transitions, early exits)

Source

pub fn notify_change(&self, _uri: &str)

Notify of file change (may trigger state transition)

Increments the pending parse count and may transition to degraded state if a parse storm is detected.

§Arguments
  • _uri - URI of the changed file (reserved for future use).
§Returns

Nothing. Updates coordinator metrics and state for the LSP workflow.

§Examples
use perl_parser::workspace_index::IndexCoordinator;

let coordinator = IndexCoordinator::new();
coordinator.notify_change("file:///example.pl");
Source

pub fn notify_parse_complete(&self, _uri: &str)

Notify parse completion for the Index/Analyze workflow stages.

Decrements the pending parse count, enforces resource limits, and may attempt recovery when parse storms clear.

§Arguments
  • _uri - URI of the parsed file (reserved for future use).
§Returns

Nothing. Updates coordinator metrics and state for the LSP workflow.

§Examples
use perl_parser::workspace_index::IndexCoordinator;

let coordinator = IndexCoordinator::new();
coordinator.notify_parse_complete("file:///example.pl");
Source

pub fn transition_to_ready(&self, file_count: usize, symbol_count: usize)

Transition to Ready state

Marks the index as fully ready for queries after successful workspace scan. Records the file count, symbol count, and completion timestamp. Enforces resource limits after transition.

§State Transition Guards

Only valid transitions:

  • BuildingReady (normal completion)
  • DegradedReady (recovery after fix)
§Arguments
  • file_count - Total number of files indexed
  • symbol_count - Total number of symbols extracted
§Returns

Nothing. The coordinator state is updated in-place.

§Examples
use perl_parser::workspace_index::IndexCoordinator;

let coordinator = IndexCoordinator::new();
coordinator.transition_to_ready(100, 5000);
Source

pub fn transition_to_scanning(&self)

Transition to Scanning phase (Idle → Scanning)

Resets build counters and marks the index as scanning workspace folders.

Source

pub fn update_scan_progress(&self, total_count: usize)

Update scanning progress with the latest discovered file count

Source

pub fn transition_to_indexing(&self, total_count: usize)

Transition to Indexing phase (Scanning → Indexing)

Uses the discovered file count as the total index target.

Source

pub fn transition_to_building(&self, total_count: usize)

Transition to Building state (Indexing phase)

Marks the index as indexing with a known total file count.

Source

pub fn update_building_progress(&self, indexed_count: usize)

Update Building state progress for the Index/Analyze workflow stages.

Increments the indexed file count and checks for scan timeouts.

§Arguments
  • indexed_count - Number of files indexed so far.
§Returns

Nothing. Updates coordinator state and may transition to Degraded.

§Examples
use perl_parser::workspace_index::IndexCoordinator;

let coordinator = IndexCoordinator::new();
coordinator.transition_to_building(100);
coordinator.update_building_progress(1);
Source

pub fn transition_to_degraded(&self, reason: DegradationReason)

Transition to Degraded state

Marks the index as degraded with the specified reason. Preserves the current symbol count (if available) to indicate partial functionality remains.

§Arguments
  • reason - Why the index degraded (ParseStorm, IoError, etc.)
§Returns

Nothing. The coordinator state is updated in-place.

§Examples
use perl_parser::workspace_index::{DegradationReason, IndexCoordinator, ResourceKind};

let coordinator = IndexCoordinator::new();
coordinator.transition_to_degraded(DegradationReason::ResourceLimit {
    kind: ResourceKind::MaxFiles,
});
Source

pub fn check_limits(&self) -> Option<DegradationReason>

Check resource limits and return degradation reason if exceeded

Examines current workspace index state against configured resource limits. Returns the first exceeded limit found, enabling targeted degradation.

§Returns
  • Some(DegradationReason) - Resource limit exceeded, contains specific limit type
  • None - All limits within acceptable bounds
§Checked Limits
  • max_files: Total number of indexed files
  • max_total_symbols: Aggregate symbol count across workspace
§Performance
  • Lock-free read of index state (<100ns)
  • Symbol counting is O(n) where n is number of files

Returns: Some(DegradationReason) when a limit is exceeded, otherwise None.

§Examples
use perl_parser::workspace_index::IndexCoordinator;

let coordinator = IndexCoordinator::new();
let _reason = coordinator.check_limits();
Source

pub fn enforce_limits(&self)

Enforce resource limits and trigger degradation if exceeded

Checks current resource usage against configured limits and automatically transitions to Degraded state if any limit is exceeded. This method should be called after operations that modify index size (file additions, parse completions, etc.).

§State Transitions
  • ReadyDegraded(ResourceLimit) if limits exceeded
  • BuildingDegraded(ResourceLimit) if limits exceeded
§Returns

Nothing. The coordinator state is updated in-place when limits are exceeded.

§Examples
use perl_parser::workspace_index::IndexCoordinator;

let coordinator = IndexCoordinator::new();
// ... index some files ...
coordinator.enforce_limits();  // Check and degrade if needed
Source

pub fn record_early_exit( &self, reason: EarlyExitReason, elapsed_ms: u64, indexed_files: usize, total_files: usize, )

Record an early-exit event for indexing instrumentation

Source

pub fn query<T, F1, F2>(&self, full_query: F1, partial_query: F2) -> T
where F1: FnOnce(&WorkspaceIndex) -> T, F2: FnOnce(&WorkspaceIndex) -> T,

Query with automatic degradation handling

Dispatches to full query if index is Ready, or partial query otherwise. This pattern enables LSP handlers to provide appropriate responses based on index state without explicit state checking.

§Type Parameters
  • T - Return type of the query functions
  • F1 - Full query function type accepting &WorkspaceIndex and returning T
  • F2 - Partial query function type accepting &WorkspaceIndex and returning T
§Arguments
  • full_query - Function to execute when index is Ready
  • partial_query - Function to execute when index is Building/Degraded
§Returns

The value returned by the selected query function.

§Examples
use perl_parser::workspace_index::IndexCoordinator;

let coordinator = IndexCoordinator::new();
let locations = coordinator.query(
    |index| index.find_references("my_function"),  // Full workspace search
    |index| vec![]                                 // Empty fallback
);

Trait Implementations§

Source§

impl Debug for IndexCoordinator

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
Source§

impl Default for IndexCoordinator

Source§

fn default() -> IndexCoordinator

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more