All files / src/utils reindex.ts

100% Statements 17/17
100% Branches 8/8
100% Functions 5/5
100% Lines 14/14

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67                                                    197x 13x 13x         175x 175x               240x 175x 175x               29x 29x 29x               18x 18x 18x    
import { Notice } from "obsidian";
import type { ConfigUpdateResponse, SetModelResponse, SyncOptions } from "../types";
import type { Result } from "../result";
import { MESSAGES } from "../locales/en";
 
/** The slice of the plugin a forced rebuild needs. */
export interface RebuildPlugin {
    triggerSync: (options?: SyncOptions) => void | Promise<void>;
}
 
/** The slice of the plugin a server write that can invalidate the index needs. */
export interface ServerWritePlugin extends RebuildPlugin {
    api: {
        setEmbeddingModel: (model: string) => Promise<Result<SetModelResponse, Error>>;
        updateConfig: (updates: Record<string, unknown>) => Promise<ConfigUpdateResponse>;
    };
}
 
/** An embedding swap and the sync it needs, for a caller that runs the sync later. */
export interface DeferredEmbeddingSwap {
    result: Result<SetModelResponse, Error>;
    syncOptions: SyncOptions | undefined;
}
 
/** The sync a model or chunking change needs: a forced rebuild, announced, or nothing at all. */
function announceRebuildIfNeeded(reindexRequired: boolean): SyncOptions | undefined {
    if (!reindexRequired) return undefined;
    new Notice(MESSAGES.NOTICE_REINDEX_REQUIRED);
    return { forceRebuild: true };
}
 
/** Raise the notice and run that sync now; an index that still matches runs no sync at all. */
export function startReindexSync(plugin: RebuildPlugin, reindexRequired: boolean): void {
    const options = announceRebuildIfNeeded(reindexRequired);
    if (options) void plugin.triggerSync(options);
}
 
/** Write server config, and rebuild the index when the server says the change invalidated it. */
export async function applyConfig(
    plugin: ServerWritePlugin,
    updates: Record<string, unknown>,
): Promise<ConfigUpdateResponse> {
    const response = await plugin.api.updateConfig(updates);
    startReindexSync(plugin, response.reindex_required);
    return response;
}
 
/** Swap the embedding model and hand back the sync the swap needs; the caller runs it. */
export async function applyEmbeddingModelDeferred(
    plugin: ServerWritePlugin,
    ref: string,
): Promise<DeferredEmbeddingSwap> {
    const result = await plugin.api.setEmbeddingModel(ref);
    const syncOptions = result.isOk() ? announceRebuildIfNeeded(result.value.reindex_required) : undefined;
    return { result, syncOptions };
}
 
/** Swap the embedding model and rebuild the index now when the old vectors no longer match. */
export async function applyEmbeddingModel(
    plugin: ServerWritePlugin,
    ref: string,
): Promise<Result<SetModelResponse, Error>> {
    const { result, syncOptions } = await applyEmbeddingModelDeferred(plugin, ref);
    if (syncOptions) void plugin.triggerSync(syncOptions);
    return result;
}