Untitled

mail@pastecode.io avatar
unknown
javascript
a year ago
3.5 kB
1
Indexable
Never
class OrderService {
  constructor(orderRepository, orderFactory) {
    this.orderRepository = orderRepository;
    this.orderFactory = orderFactory;
    this.batchSize = 1000;
    this.batchProcessor = new BatchProcessor(this.batchSize);
  }

  async createAndSaveOrders(numberOfOrders) {
    const unitOfWork = new UnitOfWork();
    const batchIndexes = this.batchProcessor.generateBatchIndexes(numberOfOrders);

    for (const { startIndex, endIndex } of batchIndexes) {
      const currentBatch = [];
      for (let i = startIndex; i < endIndex; i++) {
        const orderId = i + 1;
        const customerName = `Customer ${orderId}`;

        const order = this.orderFactory.createOrder(orderId, customerName);
        order.addOrderItem("product1", 2);
        order.addOrderItem("product2", 3);

        currentBatch.push(order);
      }

      // Вызываем метод репозитория для сохранения пакета заказов в рамках транзакции
      await this.orderRepository.saveBatchTransactional(currentBatch, unitOfWork);
    }
    await this.orderRepository.commitUnitOfWork(unitOfWorkId);
  }
}

// Уровень инфраструктуры

class OrderRepository {
  async saveBatchTransactional(orders, unitOfWork, unitOfWorkId) {
    unitOfWork.addTransaction(async () => {
      await this.saveBatch(orders);
    });
  }

  async commitUnitOfWork(unitOfWork) {
     await unitOfWork.commit();
  }

  async rollbackUnitOfWork(unitOfWorkId) {
     await unitOfWork.rollback();
  }
  
  async saveBatch(order) {}
}

class UnitOfWork {
  constructor() {
    this.transactions = [];
  }

  createTransaction() {
    // Возвращает новую транзакцию или ее эквивалент для вашей базы данных
  }

  addTransaction(transaction) {
    this.transactions.push(transaction);
  }

  async commit() {
    const mainTransaction = this.createTransaction(); // Создаем главную транзакцию
    try {
      for (const transaction of this.transactions) {
        await transaction(); // Выполняем каждую транзакцию в рамках главной транзакции
      }
      await this.commitTransaction(mainTransaction); // Завершаем главную транзакцию
    } catch (error) {
      console.error("Error while committing transaction:", error);
      await this.rollback();
      throw error;
    }
  }

  async rollback() {
    for (const transaction of this.transactions) {
      try {
        await this.rollbackTransaction(transaction);
      } catch (error) {
        console.error("Error while rolling back transaction:", error);
      }
    }
  }

  async commitTransaction(transaction) {
    // Ваш код для завершения транзакции
  }

  async rollbackTransaction(transaction) {
    // Ваш код для отката транзакции
  }
}

class BatchProcessor {
  constructor(batchSize) {
    this.batchSize = batchSize;
  }

  // Генерация индексов для текущего пакета
  generateBatchIndexes(totalItems) {
    const batchIndexes = [];
    let startIndex = 0;

    while (startIndex < totalItems) {
      const endIndex = Math.min(startIndex + this.batchSize, totalItems);
      batchIndexes.push({ startIndex, endIndex });
      startIndex = endIndex;
    }

    return batchIndexes;
  }
}