|
1 | | -import { QdrantClient } from "@qdrant/js-client-rest" |
| 1 | +import { QdrantClient, Schemas } from "@qdrant/js-client-rest" |
2 | 2 | import { createHash } from "crypto" |
3 | 3 | import * as path from "path" |
4 | 4 | import { getWorkspacePath } from "../../../utils/path" |
@@ -37,74 +37,83 @@ export class QdrantVectorStore implements IVectorStore { |
37 | 37 | this.collectionName = `ws-${hash.substring(0, 16)}` |
38 | 38 | } |
39 | 39 |
|
| 40 | + private async getCollectionInfo(): Promise<Schemas["CollectionInfo"] | null> { |
| 41 | + try { |
| 42 | + const collectionInfo = await this.client.getCollection(this.collectionName) |
| 43 | + return collectionInfo |
| 44 | + } catch (error: unknown) { |
| 45 | + if (error instanceof Error) { |
| 46 | + console.warn( |
| 47 | + `[QdrantVectorStore] Warning during getCollectionInfo for "${this.collectionName}". Collection may not exist or another error occurred:`, |
| 48 | + error.message, |
| 49 | + ) |
| 50 | + } |
| 51 | + return null |
| 52 | + } |
| 53 | + } |
| 54 | + |
40 | 55 | /** |
41 | 56 | * Initializes the vector store |
42 | 57 | * @returns Promise resolving to boolean indicating if a new collection was created |
43 | 58 | */ |
44 | 59 | async initialize(): Promise<boolean> { |
| 60 | + let created = false |
45 | 61 | try { |
46 | | - let created = false |
47 | | - |
48 | | - try { |
49 | | - // Directly attempt to fetch the specific collection |
50 | | - const collectionInfo = await this.client.getCollection(this.collectionName) |
| 62 | + const collectionInfo = await this.getCollectionInfo() |
51 | 63 |
|
52 | | - // Collection exists - check if vector size matches |
| 64 | + if (collectionInfo === null) { |
| 65 | + // Collection info not retrieved (assume not found or inaccessible), create it |
| 66 | + await this.client.createCollection(this.collectionName, { |
| 67 | + vectors: { |
| 68 | + size: this.vectorSize, |
| 69 | + distance: this.DISTANCE_METRIC, |
| 70 | + }, |
| 71 | + }) |
| 72 | + created = true |
| 73 | + } else { |
| 74 | + // Collection exists, check vector size |
53 | 75 | const existingVectorSize = collectionInfo.config?.params?.vectors?.size |
54 | | - |
55 | 76 | if (existingVectorSize === this.vectorSize) { |
56 | | - // Collection exists and has correct vector size |
57 | | - created = false |
| 77 | + created = false // Exists and correct |
58 | 78 | } else { |
59 | | - // Collection exists but has wrong vector size - recreate it |
| 79 | + // Exists but wrong vector size, recreate |
60 | 80 | console.warn( |
61 | 81 | `[QdrantVectorStore] Collection ${this.collectionName} exists with vector size ${existingVectorSize}, but expected ${this.vectorSize}. Recreating collection.`, |
62 | 82 | ) |
63 | | - await this.client.deleteCollection(this.collectionName) |
64 | | - await this.client.createCollection(this.collectionName, { |
65 | | - vectors: { |
66 | | - size: this.vectorSize, |
67 | | - distance: this.DISTANCE_METRIC, |
68 | | - }, |
69 | | - }) |
70 | | - created = true |
71 | | - } |
72 | | - } catch (error: any) { |
73 | | - // Check if this is a "Not Found" error (collection doesn't exist) |
74 | | - if (error?.response?.status === 404) { |
75 | | - // Collection doesn't exist - create it |
| 83 | + await this.client.deleteCollection(this.collectionName) // Known to exist |
76 | 84 | await this.client.createCollection(this.collectionName, { |
77 | 85 | vectors: { |
78 | 86 | size: this.vectorSize, |
79 | 87 | distance: this.DISTANCE_METRIC, |
80 | 88 | }, |
81 | 89 | }) |
82 | 90 | created = true |
83 | | - } else { |
84 | | - // Other error - log and re-throw |
85 | | - console.error(`[QdrantVectorStore] Error checking collection ${this.collectionName}:`, error) |
86 | | - throw error |
87 | 91 | } |
88 | 92 | } |
89 | 93 |
|
90 | | - // Create payload indexes for pathSegments up to depth 5 |
| 94 | + // Create payload indexes |
91 | 95 | for (let i = 0; i <= 4; i++) { |
92 | 96 | try { |
93 | 97 | await this.client.createPayloadIndex(this.collectionName, { |
94 | 98 | field_name: `pathSegments.${i}`, |
95 | 99 | field_schema: "keyword", |
96 | 100 | }) |
97 | | - } catch (indexError) { |
98 | | - console.warn( |
99 | | - `[QdrantVectorStore] Could not create payload index for pathSegments.${i} on ${this.collectionName}. It might already exist or there was an issue.`, |
100 | | - indexError, |
101 | | - ) |
| 101 | + } catch (indexError: any) { |
| 102 | + const errorMessage = (indexError?.message || "").toLowerCase() |
| 103 | + if (!errorMessage.includes("already exists")) { |
| 104 | + console.warn( |
| 105 | + `[QdrantVectorStore] Could not create payload index for pathSegments.${i} on ${this.collectionName}. Details:`, |
| 106 | + indexError?.message || indexError, |
| 107 | + ) |
| 108 | + } |
102 | 109 | } |
103 | 110 | } |
104 | | - |
105 | 111 | return created |
106 | | - } catch (error) { |
107 | | - console.error("Failed to initialize Qdrant collection:", error) |
| 112 | + } catch (error: any) { |
| 113 | + console.error( |
| 114 | + `[QdrantVectorStore] Failed to initialize Qdrant collection "${this.collectionName}":`, |
| 115 | + error?.message || error, |
| 116 | + ) |
108 | 117 | throw error |
109 | 118 | } |
110 | 119 | } |
@@ -295,16 +304,7 @@ export class QdrantVectorStore implements IVectorStore { |
295 | 304 | * @returns Promise resolving to boolean indicating if the collection exists |
296 | 305 | */ |
297 | 306 | async collectionExists(): Promise<boolean> { |
298 | | - try { |
299 | | - // Prefer direct API call if supported |
300 | | - await this.client.getCollection(this.collectionName) |
301 | | - return true |
302 | | - } catch (error: any) { |
303 | | - if (error?.response?.status === 404) { |
304 | | - return false |
305 | | - } |
306 | | - console.error("Error checking collection existence:", error) |
307 | | - return false |
308 | | - } |
| 307 | + const collectionInfo = await this.getCollectionInfo() |
| 308 | + return collectionInfo !== null |
309 | 309 | } |
310 | 310 | } |
0 commit comments