Как использовать TypeORM с горячей перезагрузкой, не сталкиваясь с проблемами сравнения классов сущностей? - PullRequest
0 голосов
/ 15 апреля 2020

При использовании TypeORM с Next. js горячая перезагрузка на стороне сервера используется по умолчанию и удобна, за исключением одного: каждый раз, когда происходит горячая перезагрузка, код перезапускается, что приводит к перестройке классы сущностей, поэтому они не «совпадают» со старыми версиями, которые помнят TypeORM (они не имеют ссылочного равенства). Это приводит к ошибкам EntityMetadataNotFound, когда TypeORM сравнивает новую сущность User со старой сущностью User и обнаруживает, что они не совпадают. Подробнее об этой проблеме можно узнать здесь: EntityMetadataNotFound: Метаданные для «BusinessApplication» не найдены . Чтобы исправить это, я решил создать новое соединение при каждой горячей перезагрузке, например:

/**
 * Database manager class
 */
class Database {
  private connectionManager: ConnectionManager;

  /**
   * Keeps track of whether this Database instance remembers making a new connection. If it doesn't,
   * and an existing connection was found anyway, that means that the module was hot-reloaded.
   */
  private hasCreatedConnection = false;

  constructor() {
    this.connectionManager = getConnectionManager();
  }

  private async getConnection(): Promise<Connection> {
    const DEFAULT_CONNECTION_NAME = 'default';
    const currentConnection = this.connectionManager.has(DEFAULT_CONNECTION_NAME)
      ? this.connectionManager.get(DEFAULT_CONNECTION_NAME)
      : undefined;
    // if connection exists but we don't remember creating it, it's because of hot reloading
    // and that means a new connection needs to be created, or else entity metadata won't match
    // from the old session.
    // https://stackoverflow.com/questions/60677582/entitymetadatanotfound-no-metadata-for-businessapplication-was-found
    if (currentConnection && !this.hasCreatedConnection) {
      console.debug('recreating connection due to hot reloading');
      if (currentConnection.isConnected) {
        await currentConnection.close();
      }
      console.debug('done closing, making new connection..');
      return this.createConnectionWithName(DEFAULT_CONNECTION_NAME);
    }
    if (currentConnection) {
      if (!currentConnection.isConnected) {
        return currentConnection.connect();
      } else return currentConnection;
    } else {
      return this.createConnectionWithName(DEFAULT_CONNECTION_NAME);
    }
  }

  private createConnectionWithName(name: string): Promise<Connection> {
    this.hasCreatedConnection = true;
    return createConnection({
      name,
      type: 'postgres',
      url: process.env.DATABASE_URL,
      synchronize: true,
      entities: [Business, Qualification, Customer, BaseOffer, ProductOffer, ServiceOffer]
    });
  }

  public getManager(): Promise<EntityManager> {
    return this.getConnection().then(conn => conn.manager);
  }
}

К сожалению, подключение к базе данных невероятно медленно (~ 10 секунд) (и это может быть отдельной проблемой), поэтому каждый вызов API теперь занимает очень много времени. Как это можно исправить? Я также открыл вопрос о хранилище typeorm здесь: https://github.com/typeorm/typeorm/issues/5876

...