From d7018665ab6aef2d3db51eaa6ba4141c5980feb5 Mon Sep 17 00:00:00 2001 From: Julian Date: Thu, 12 Mar 2026 22:42:47 -0700 Subject: [PATCH] fix: cache VectorSearchClient across Client calls --- Sources/XCDocs/Client.swift | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/Sources/XCDocs/Client.swift b/Sources/XCDocs/Client.swift index 01eb733..6ca2af3 100644 --- a/Sources/XCDocs/Client.swift +++ b/Sources/XCDocs/Client.swift @@ -9,6 +9,8 @@ import XCDocsSupport /// resolves search results into stable Swift value types. @available(macOS 26, *) public final class Client { + private var cachedSearchClient: VectorSearchClient? + /// Creates a client for interacting with the local documentation asset. public init() {} @@ -36,11 +38,9 @@ public final class Client { limit: Int = 10, omitContent: Bool = true ) async throws -> [SearchResult] { - let databaseDirectoryURL = try DocumentationAssetLocator().locateDatabaseDirectoryURL() + let searchClient = try await searchClient() let vector = try await embeddingVector(for: query) - let searchClient = try await VectorSearchClient(databaseDirectoryURL: databaseDirectoryURL, readOnly: true) - let hits = try await searchClient.search( vector: vector, frameworks: frameworks, @@ -74,10 +74,7 @@ public final class Client { /// - Throws: An error if the documentation asset cannot be found, if the identifier does /// not exist, or if the underlying storage backend fails to load the entry. public func fetch(_ identifier: String) async throws -> DocumentationEntry { - let databaseDirectoryURL = try DocumentationAssetLocator().locateDatabaseDirectoryURL() - - let searchClient = try await VectorSearchClient(databaseDirectoryURL: databaseDirectoryURL, readOnly: true) - + let searchClient = try await searchClient() let result = try await searchClient.fetch(identifier: identifier) return DocumentationEntry( @@ -91,6 +88,15 @@ public final class Client { // MARK: Private + private func searchClient() async throws -> VectorSearchClient { + if let cachedSearchClient { return cachedSearchClient } + + let databaseDirectoryURL = try DocumentationAssetLocator().locateDatabaseDirectoryURL() + let client = try await VectorSearchClient(databaseDirectoryURL: databaseDirectoryURL, readOnly: true) + cachedSearchClient = client + return client + } + private func embeddingVector(for text: String) async throws -> Data { let service = try await MADServiceObject() let request = try await MADTextEmbeddingRequestObject()