فهرست منبع

Implement deleteExpiredThreads()

Shun Miyazawa 1 سال پیش
والد
کامیت
81b189e45a

+ 8 - 1
apps/app/src/features/openai/server/models/thread-relation.ts

@@ -21,7 +21,9 @@ interface ThreadRelationDocument extends ThreadRelation, Document {
   updateThreadExpiration(): Promise<void>;
 }
 
-type ThreadRelationModel = Model<ThreadRelationDocument>
+interface ThreadRelationModel extends Model<ThreadRelationDocument> {
+  getExpiredThreadRelations(limit?: number): Promise<ThreadRelationDocument[] | undefined>;
+}
 
 const schema = new Schema<ThreadRelationDocument, ThreadRelationModel>({
   userId: {
@@ -41,6 +43,11 @@ const schema = new Schema<ThreadRelationDocument, ThreadRelationModel>({
   },
 });
 
+schema.statics.getExpiredThreadRelations = async function(limit?: number): Promise<ThreadRelationDocument[] | undefined> {
+  const expiredThreadRelations = await this.find({ expiredAt: { $lte: new Date() } }).limit(limit ?? 100).exec();
+  return expiredThreadRelations;
+};
+
 schema.methods.updateThreadExpiration = async function(): Promise<void> {
   this.expiredAt = generateExpirationDate();
   await this.save();

+ 23 - 0
apps/app/src/features/openai/server/services/openai.ts

@@ -32,6 +32,7 @@ let isVectorStoreForPublicScopeExist = false;
 export interface IOpenaiService {
   getOrCreateThread(userId: string, threadId?: string): Promise<OpenAI.Beta.Threads.Thread | undefined>;
   getOrCreateVectorStoreForPublicScope(): Promise<VectorStoreDocument>;
+  deleteExpiredThreads(limit: number): Promise<void>;
   createVectorStoreFile(pages: PageDocument[]): Promise<void>;
   deleteVectorStoreFile(pageId: Types.ObjectId): Promise<void>;
   rebuildVectorStoreAll(): Promise<void>;
@@ -66,6 +67,28 @@ class OpenaiService implements IOpenaiService {
     return thread;
   }
 
+  public async deleteExpiredThreads(limit: number): Promise<void> {
+    const threadRelations = await ThreadRelationModel.getExpiredThreadRelations(limit);
+    if (threadRelations == null) {
+      return;
+    }
+
+    const deletedThreadIds: string[] = [];
+    for (const threadRelation of threadRelations) {
+      try {
+        // eslint-disable-next-line no-await-in-loop
+        const deleteThreadResponse = await this.client.deleteThread(threadRelation.threadId);
+        logger.debug('Delete thread', deleteThreadResponse);
+        deletedThreadIds.push(threadRelation.threadId);
+      }
+      catch (err) {
+        logger.error(err);
+      }
+    }
+
+    await ThreadRelationModel.deleteMany({ threadId: { $in: deletedThreadIds } });
+  }
+
   public async getOrCreateVectorStoreForPublicScope(): Promise<VectorStoreDocument> {
     const vectorStoreDocument = await VectorStoreModel.findOne({ scorpeType: VectorStoreScopeType.PUBLIC });
 

+ 4 - 4
apps/app/src/features/openai/server/services/thread-deletion-cron.ts

@@ -3,13 +3,13 @@ import nodeCron from 'node-cron';
 import { configManager } from '~/server/service/config-manager';
 import loggerFactory from '~/utils/logger';
 
-import ThreadRelationModel from '../models/thread-relation';
-
 import { getOpenaiService, type IOpenaiService } from './openai';
 
 
 const logger = loggerFactory('growi:service:thread-deletion-cron');
 
+const DELETE_LIMIT = 100;
+
 class ThreadDeletionCronService {
 
   cronJob: nodeCron.ScheduledTask;
@@ -43,13 +43,13 @@ class ThreadDeletionCronService {
   }
 
   async executeJob(): Promise<void> {
-    // important
+    await this.openaiService.deleteExpiredThreads(DELETE_LIMIT);
   }
 
   private generateCronJob(cronSchedule: string) {
     return nodeCron.schedule(cronSchedule, async() => {
       try {
-        this.executeJob();
+        await this.executeJob();
       }
       catch (e) {
         logger.error(e);