#142

Файлы следует сохранять атомарно

Допустим, ты пишешь простенький кеш для скачивания файлов, чтобы твой код не качал одно и то же по несколько раз:

function download(file) {
  if (exists(file)) {
    return file;
  }

  const data = download(file);
  save(file, data);

  return file;
}

// было:

function save(filename, data) {
  write(filename, data);
}

В таком коде может произойти ситуация, когда файл еще не дописался внутри save(), но уже кому-то отдался неполный. Потому что exists(file) станет true сразу после открытия файла на запись, еще задолго до того, как был записан первый байт.

Чтобы такого не происходило — файл следует писать атомарно:

// стало: 

function save(filename, data) {
  // придумай временное имя
  const tmpFilename = filename + '.tmp';

  // если рядом кто-то уже пишет во временный файл —
  // это означает что он точно закончит запись
  // и целевой файл скоро появится.
  if (exists(tmpFilename)) {
    return;
  }

  // неспешно пишем во временный файл
  write(tmpFilename, data);

  // если целевой файл появился, пока мы писали временный —
    // это означает что кто-то быстрее нас скачал и записал.
  if (exists(filename)) {
    return;
  }

  // переименовали временный файл в целевой.
  // одна операция, файл сразу появится целиком!
  rename(tmpFilename, filename);
}

Обрати внимание: в таком коде на любом этапе исключены проблемы с целостностью данных.