|
|
@@ -1120,60 +1120,66 @@ export class QdrantEndpoint extends BaseEndpointComponent {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- // Get all latest content for this shop
|
|
|
- const latestContent = this.db.getLatestContentByType(shop.id);
|
|
|
-
|
|
|
- // Prepare batch of content items to sync
|
|
|
- const embeddingBatch: any[] = [];
|
|
|
-
|
|
|
- // Process all content types using array iteration to avoid duplication
|
|
|
- const contentTypes: Array<{ type: 'shipping' | 'contacts' | 'terms' | 'faq', items: any[] }> = [
|
|
|
- { type: 'shipping', items: latestContent.shipping },
|
|
|
- { type: 'contacts', items: latestContent.contacts },
|
|
|
- { type: 'terms', items: latestContent.terms },
|
|
|
- { type: 'faq', items: latestContent.faq }
|
|
|
- ];
|
|
|
-
|
|
|
- for (const { type, items } of contentTypes) {
|
|
|
- for (const content of items) {
|
|
|
- embeddingBatch.push({
|
|
|
- contentId: content.id,
|
|
|
- contentType: type,
|
|
|
- url: content.url,
|
|
|
- content: content.content,
|
|
|
- title: content.title,
|
|
|
- contentHash: content.content_hash,
|
|
|
- contentChanged: true // Force re-sync
|
|
|
- });
|
|
|
- }
|
|
|
- }
|
|
|
+ // Optimized: Process content in chunks to avoid loading everything into memory
|
|
|
+ const CHUNK_SIZE = 50;
|
|
|
+ const contentTypes: Array<'shipping' | 'contacts' | 'terms' | 'faq'> = ['shipping', 'contacts', 'terms', 'faq'];
|
|
|
+ let totalItemsQueued = 0;
|
|
|
|
|
|
- if (embeddingBatch.length === 0) {
|
|
|
- res.status(200).json({
|
|
|
- message: 'No content available to sync',
|
|
|
- items_queued: 0,
|
|
|
- shop_id: shop.id
|
|
|
- });
|
|
|
- return;
|
|
|
- }
|
|
|
+ // Start background processing without blocking the response
|
|
|
+ (async () => {
|
|
|
+ try {
|
|
|
+ for (const contentType of contentTypes) {
|
|
|
+ let offset = 0;
|
|
|
+ let hasMore = true;
|
|
|
+
|
|
|
+ while (hasMore) {
|
|
|
+ // Fetch chunk of content
|
|
|
+ const chunk = this.db.getAllContent(shop.id, {
|
|
|
+ contentType,
|
|
|
+ limit: CHUNK_SIZE,
|
|
|
+ offset
|
|
|
+ });
|
|
|
+
|
|
|
+ if (chunk.length === 0) {
|
|
|
+ break;
|
|
|
+ }
|
|
|
|
|
|
- // Start the sync process in background
|
|
|
- logger.info(`Force syncing ${embeddingBatch.length} items to Qdrant for shop ${shop.id}`);
|
|
|
-
|
|
|
- // Process the batch asynchronously (don't await)
|
|
|
- this.embeddingWorkflow.processContentBatch(shop.id, embeddingBatch)
|
|
|
- .then(results => {
|
|
|
- const successCount = results.filter(r => r.embedded).length;
|
|
|
- const failCount = results.filter(r => !r.embedded).length;
|
|
|
- logger.info(`Qdrant sync completed for shop ${shop.id}: ${successCount} success, ${failCount} failed`);
|
|
|
- })
|
|
|
- .catch(error => {
|
|
|
+ // Convert to embedding batch format
|
|
|
+ const embeddingBatch = chunk.map(content => ({
|
|
|
+ contentId: content.id,
|
|
|
+ contentType,
|
|
|
+ url: content.url,
|
|
|
+ content: content.content,
|
|
|
+ title: content.title,
|
|
|
+ contentHash: content.content_hash,
|
|
|
+ contentChanged: true // Force re-sync
|
|
|
+ }));
|
|
|
+
|
|
|
+ // Process this chunk
|
|
|
+ const results = await this.embeddingWorkflow!.processContentBatch(shop.id, embeddingBatch);
|
|
|
+ const successCount = results.filter(r => r.embedded).length;
|
|
|
+ const failCount = results.filter(r => !r.embedded).length;
|
|
|
+
|
|
|
+ logger.info(`Processed chunk for shop ${shop.id} (${contentType}): ${successCount} success, ${failCount} failed`);
|
|
|
+
|
|
|
+ totalItemsQueued += chunk.length;
|
|
|
+ hasMore = chunk.length === CHUNK_SIZE;
|
|
|
+ offset += CHUNK_SIZE;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ logger.info(`Qdrant sync completed for shop ${shop.id}: ${totalItemsQueued} items processed`);
|
|
|
+ } catch (error) {
|
|
|
logger.error(`Qdrant sync failed for shop ${shop.id}:`, error);
|
|
|
- });
|
|
|
+ }
|
|
|
+ })();
|
|
|
+
|
|
|
+ // Estimate total items (quick count without loading all data)
|
|
|
+ const estimatedTotal = this.db.getAllContent(shop.id, { limit: 1 }).length > 0 ? 'processing' : 0;
|
|
|
|
|
|
res.status(202).json({
|
|
|
- message: 'Qdrant sync started',
|
|
|
- items_queued: embeddingBatch.length,
|
|
|
+ message: 'Qdrant sync started in background with chunked processing',
|
|
|
+ items_queued: estimatedTotal,
|
|
|
shop_id: shop.id
|
|
|
});
|
|
|
|