Skip to content

Latest commit

 

History

History
99 lines (76 loc) · 6.28 KB

shuttingtheprocess.russian.md

File metadata and controls

99 lines (76 loc) · 6.28 KB

Изящно выходите из процесса, когда неизвестное случается

Объяснение в один абзац

Где-то в вашем коде объект-обработчик ошибок отвечает за принятие решения о том, как действовать при возникновении ошибки - если ошибка является доверенной (т.е. операционная ошибка, см. дальнейшее объяснение в этих практиках № 3), тогда записи в файл журнала может быть достаточно. Ситуация становится неясной, если ошибка незнакома - это означает, что какой-то компонент может быть в неисправном состоянии, и все будущие запросы могут быть сбойными. Например, если предположить, что единственная служба выдачи токенов с состоянием, которая вызвала исключение и потеряла свое состояние, отныне может вести себя неожиданно и вызывать сбой всех запросов. В этом сценарии завершите процесс и используйте "инструмент перезапуска" (например, Forever, PM2 и т.д.), Чтобы начать заново с чистым состоянием.

Пример кода: решение о сбое

Javascript
// Assuming developers mark known operational errors with error.isOperational=true, read best practice #3
process.on('uncaughtException', (error) => {
  errorManagement.handler.handleError(error);
  if(!errorManagement.handler.isTrustedError(error))
    process.exit(1)
});

// centralized error handler encapsulates error-handling related logic
function errorHandler() {
  this.handleError = (error) => {
    return logger.logError(error)
      .then(sendMailToAdminIfCritical)
      .then(saveInOpsQueueIfCritical)
      .then(determineIfOperationalError);
  }

  this.isTrustedError = (error) => {
    return error.isOperational;
  }
}
Typescript
// Assuming developers mark known operational errors with error.isOperational=true, read best practice #3
process.on('uncaughtException', (error: Error) => {
  errorManagement.handler.handleError(error);
  if(!errorManagement.handler.isTrustedError(error))
    process.exit(1)
});

// centralized error object that derives from Node’s Error
export class AppError extends Error {
  public readonly isOperational: boolean;

  constructor(description: string, isOperational: boolean) {
    super(description);
    Object.setPrototypeOf(this, new.target.prototype); // restore prototype chain
    this.isOperational = isOperational;
    Error.captureStackTrace(this);
  }
}

// centralized error handler encapsulates error-handling related logic
class ErrorHandler {
  public async handleError(err: Error): Promise<void> {
    await logger.logError(err);
    await sendMailToAdminIfCritical();
    await saveInOpsQueueIfCritical();
    await determineIfOperationalError();
  };

  public isTrustedError(error: Error) {
    if (error instanceof AppError) {
      return error.isOperational;
    }
    return false;
  }
}

export const handler = new ErrorHandler();

Цитата из блога: "Лучший способ - это рухнуть"

Из блога Джойент

… Лучший способ исправить ошибки программиста - это сразу же аварийно завершить работу. Вы должны запустить свои программы, используя перезапуск, который автоматически перезапустит программу в случае сбоя. С перезапуском на месте сбой является самым быстрым способом восстановления надежного сервиса перед лицом временной ошибки программиста …

Цитата блога: "Есть три школы мысли об обработке ошибок"

Из блога: JS Recipes

… Существует три основных направления работы с ошибками:

  1. Дайте приложению упасть и перезапустите его.
  2. Обрабатывайте все возможные ошибоки и никогда не роняйте.
  3. Сбалансированный подход между двумя предыдущими.

Цитата из блога: "Нет безопасного способа уйти, не создав неопределенного хрупкого состояния"

Из официальной документации Node.js

… По самой природе того, как throw работает в JavaScript, почти никогда не существует способа безопасно "выбрать то, на чем остановился", без утечки ссылок или создания какого-либо другого неопределенного хрупкого состояния. Самый безопасный способ отреагировать на возникшую ошибку - завершить процесс. Конечно, на обычном веб-сервере у вас может быть открыто много подключений, и нет смысла внезапно закрывать их, потому что кто-то еще вызвал ошибку. Лучший подход - отправить ответ об ошибке на запрос, который вызвал ошибку, позволяя остальным завершить работу в обычное время, и прекратить прослушивание новых запросов этого работника.