Skip to content

列表事务管理器(待验证)

在后端实践中,对列表进行操作时,经常碰到一种场景,即需要保证整个列表的处理逻辑成功,而一旦其中一个以上的子任务执行失败,就需要撤销前面已经成功的子任务,以保证消除影响,最典型的就是文件列表上传。

对此,我们可以将其抽象为一个通用的列表处理管理器,可以处理各种类型的列表操作,包括文件上传、数据导入等。以下是一个通用列表处理管理器的示例:

列表事务管理器(ListManager)

typescript
import { provide, scope, ScopeEnum } from '@midwayjs/core';

@provide()
@scope(ScopeEnum.Singleton)
export class ListManager {
  
  private items: any[] = [];
  private transactionInProgress: boolean = false;

  async startTransaction() {
    if (this.transactionInProgress) {
      throw new Error('Transaction is already in progress');
    }

    // 实际的开始事务操作
    console.log('Transaction started');
    this.transactionInProgress = true;
  }

  async addItem(item: any) {
    // 模拟添加操作
    console.log(`Adding item: ${item}`);
    
    // 模拟添加成功
    this.items.push(item);
  }

  async commitTransaction() {
    if (!this.transactionInProgress) {
      throw new Error('No transaction in progress to commit');
    }

    // 实际的提交事务操作
    console.log('Transaction committed');
    this.transactionInProgress = false;
  }

  async rollbackTransaction() {
    if (!this.transactionInProgress) {
      throw new Error('No transaction in progress to rollback');
    }

    // 模拟回滚已添加的项
    for (const item of this.items) {
      console.log(`Rolling back item: ${item}`);
      // 实际的回滚操作
    }
    
    this.items = [];
    this.transactionInProgress = false;
  }
}

在这个示例中,ListManager 类可以处理各种类型的列表操作,包括添加项、提交事务和回滚事务等。你可以使用这个通用的列表处理管理器来管理不同类型的列表操作,确保操作的一致性和完整性。

当需要处理文件上传时,你可以将文件作为项添加到列表中;当需要处理其他类型的列表操作时,你可以将相应的项添加到列表中。然后根据具体需求调用 startTransactionaddItemcommitTransactionrollbackTransaction 方法来管理整体操作过程。

这种通用的列表处理管理器的设计可以使你的代码更具通用性和灵活性,适用于各种类型的列表操作需求。希望这个改造后的示例能满足你的需求。

文件上传实例(FileUploader)

为了结合 ListManager 类和 @midwayjs/upload@3 库实现一个文件列表上传的示例,我们可以创建一个新的类 FileUploader,该类将利用 ListManager 类来管理文件上传过程中的事务。以下是一个示例代码:

安装依赖

npm i @midwayjs/upload@3 --save
typescript
import { ListManager } from './ListManager';
import { Inject, Provide } from '@midwayjs/decorator';
import { UploadService } from '@midwayjs/upload';

@Provide()
export class FileUploader {
  @Inject()
  uploadService: UploadService;

  @Inject()
  listManager: ListManager;

  async uploadFiles(fileList: any[]) {
    try {
      await this.listManager.startTransaction();

      for (const file of fileList) {
        await this.uploadFile(file);
      }

      await this.listManager.commitTransaction();
      console.log('All files uploaded successfully');
    } catch (error) {
      console.error('File upload failed:', error);
      await this.listManager.rollbackTransaction();
    }
  }

  private async uploadFile(file: any) {
    try {
      const result = await this.uploadService.uploadFile(file);
      console.log(`File ${result.filename} uploaded successfully`);
      await this.listManager.addItem(result.filename);
    } catch (error) {
      console.error(`Failed to upload file: ${file.name}`, error);
      throw new Error('File upload failed');
    }
  }
}

// 使用示例
const fileList = [file1, file2, file3]; // 从前端获取的文件列表
const fileUploader = new FileUploader();

fileUploader.uploadFiles(fileList);

在这个示例中,我们创建了一个 FileUploader 类,其中包含 uploadFiles 方法用于上传文件列表。在 uploadFiles 方法中,我们利用 ListManager 类来管理文件上传事务,确保所有文件上传成功或者全部失败时的操作一致性。在 uploadFile 方法中,我们利用 @midwayjs/uploadUploadService 来上传单个文件,并在上传成功后将文件名添加到事务列表中。

通过这种方式,我们结合了 ListManager 类和 @midwayjs/upload@3 库,实现了一个文件列表上传的示例,同时保证了文件上传过程中的事务一致性。这样的设计可以帮助简化文件上传逻辑,提高代码的可维护性和可扩展性。