При использовании 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