ಐದು ಸೆಕೆಂಡುಗಳ ಹಿಂದೆ ಸರಿಯಾಗಿ ಕೆಲಸ ಮಾಡುತ್ತಿದ್ದ ಕಾನ್ಫಿಗರೇಶನ್ ಫೈಲ್ ಈಗ 347-ಬೈಟ್‌ನ ಹರಿದುಹೋದ JSON ತುಣುಕಾಗಿದೆ. ನಿಮ್ಮ CLI ಟೂಲ್ ಪ್ರಾರಂಭವಾಗುವುದಿಲ್ಲ. ಅಪ್‌ಡೇಟ್ ನಿರೀಕ್ಷಿತ ಸಮಯಕ್ಕಿಂತ ಹೆಚ್ಚು ತೆಗೆದುಕೊಳ್ಳುತ್ತಿರುವುದರಿಂದ ಕೇವಲ Ctrl-C ಒತ್ತಿದ ಬಳಕೆದಾರರು, ಈಗ ತಮಗೆ ಬೇಡದ ಎರರ್ ಸ್ಟ್ಯಾಕ್ ಟ್ರೇಸ್ (error stack trace) ಅನ್ನು ನೋಡುತ್ತಾ ಕುಳಿತಿದ್ದಾರೆ. ಬರೆಯುವ ಮೊದಲು ಇದ್ದ ಎರಡು ಕಿಲೋಬೈಟ್‌ಗಳ ಮಾನ್ಯ ಕಾನ್ಫಿಗರೇಶನ್ ಈಗ ಮಾಯವಾಗಿದೆ, ಅದರ ಬದಲಿಗೆ ಅರ್ಧದಷ್ಟು ಮುದ್ರಿತವಾದ ರಸೀದಿಯಂತಹ ಡಿಜಿಟಲ್ ಅವಶೇಷ ಉಳಿದಿದೆ.

ಇದು writeFile ಅಟಾಮಿಕ್ (atomic) ಅಲ್ಲದ ಕಾರಣ ಸಂಭವಿಸುತ್ತದೆ. ಇದು ಅಸ್ತಿತ್ವದಲ್ಲಿರುವ ಪಾತ್ ಅನ್ನು ತೆರೆಯುತ್ತದೆ, ಅದನ್ನು ಟ್ರಂಕೇಟ್ (truncate) ಮಾಡುತ್ತದೆ, Node ನಿಂದ ಡೇಟಾವನ್ನು ಕರ್ನಲ್‌ನ ಪೇಜ್ ಕ್ಯಾಶ್ (kernel’s page cache) ಗೆ ಸ್ಟ್ರೀಮ್ ಮಾಡುತ್ತದೆ ಮತ್ತು ಅಂತಿಮವಾಗಿ ಫೈಲ್ ಡಿಸ್ಕ್ರಿಪ್ಟರ್ ಅನ್ನು ಮುಚ್ಚುತ್ತದೆ. ಟ್ರಂಕೇಶನ್ ನಡೆದ ಕ್ಷಣವೇ, ಹಳೆಯ ಕಂಟೆಂಟ್ ಮಾಯವಾಗುತ್ತದೆ. ಆ ಟ್ರಂಕೇಶನ್ ಮತ್ತು ಅಂತಿಮ close ನಡುವಿನ ಸಮಯವು ಒಂದು ಅಸುರಕ್ಷಿತ ಕಾಲಾವಧಿಯಾಗಿದೆ (window of vulnerability). ಆ ಸಮಯದಲ್ಲಿ SIGINT, ವಿದ್ಯುತ್ ವ್ಯತ್ಯಯ ಅಥವಾ ಲ್ಯಾಪ್‌ಟಾಪ್ ಮುಚ್ಚಲ್ಪಟ್ಟರೆ, ಫೈಲ್‌ಸಿಸ್ಟಮ್‌ನಲ್ಲಿ ಕೇವಲ ಅರ್ಧಂಬರ್ಧವಾದ ಡೇಟಾ ಉಳಿಯುತ್ತದೆ. Node ಪ್ರಾಮಿಸ್ (Promise) ಅನ್ನು 'resolved' ಎಂದು ವರದಿ ಮಾಡಿದರೂ ಸಹ, ಆಪರೇಟಿಂಗ್ ಸಿಸ್ಟಮ್ ಇನ್ನೂ ಮೆಮೊರಿಯಲ್ಲಿ ಬೈಟ್‌ಗಳನ್ನು ಬಫರ್ ಮಾಡುತ್ತಿರಬಹುದು. ಕನ್ವೀನಿಯನ್ಸ್ ಮೆಥಡ್‌ಗಳು (Convenience methods) ಆ ಅಂತರವನ್ನು ಮರೆಮಾಚಬಹುದು, ಆದರೆ ಅದನ್ನು ತೆಗೆದುಹಾಕಲಾರವು.

ಪರಿಹಾರವು ಅಸ್ತಿತ್ವದಲ್ಲಿರುವ ಫೈಲ್‌ನಲ್ಲೇ ಬರೆಯುವುದಲ್ಲ. ಬರೆಯುವ ಪ್ರಕ್ರಿಯೆಯನ್ನು ಪ್ರಕಟಿಸುವ (publishing) ಪ್ರಕ್ರಿಯೆಯಿಂದ ಪ್ರತ್ಯೇಕಿಸುವುದೇ ನಿಜವಾದ ಪರಿಹಾರ.

ಪಕ್ಕದ ಫೈಲ್‌ಗೆ ಬರೆಯಿರಿ, ನಂತರ ಬದಲಾಯಿಸಿ

ಈ ವಿಶ್ವಾಸಾರ್ಹ ಮಾದರಿಯು ಐದು ಹಂತಗಳನ್ನು ಹೊಂದಿದೆ. ಇವುಗಳಲ್ಲಿ ಯಾವುದೂ ಸಂಕೀರ್ಣವಾಗಿಲ್ಲ, ಆದರೆ ಇವೆಲ್ಲವೂ ಒಟ್ಟಾಗಿ ವಿಫಲತೆಯ ಕಾಲಾವಧಿಯನ್ನು (failure window) ಇಡೀ ಸ್ಟ್ರೀಮಿಂಗ್ ಬರವಣಿಗೆಯಿಂದ ಕೇವಲ ಒಂದು ಫೈಲ್‌ಸಿಸ್ಟಮ್ ಮೆಟಾಡೇಟಾ ಕಾರ್ಯಾಚರಣೆಯವರೆಗೆ ಕಡಿಮೆ ಮಾಡುತ್ತವೆ.

ಮೊದಲನೆಯದಾಗಿ, ಇಡೀ ಪೇಲೋಡ್ ಅನ್ನು ಮೆಮೊರಿಯಲ್ಲಿ ಸೀರಿಯಲೈಸ್ (serialize) ಮಾಡಿ. ಯಾವುದೇ ತಾತ್ಕಾಲಿಕ ಫೈಲ್ ರಚಿಸುವ ಮೊದಲು ಇದನ್ನು ಮಾಡಿ. ಯಾರಾದರೂ ಸರ್ಕ್ಯುಲರ್ ಆಬ್ಜೆಕ್ಟ್ (circular object) ಅನ್ನು ನೀಡಿದ್ದರಿಂದ JSON.stringify ಎಕ್ಸೆಪ್ಶನ್ (exception) ಎಸೆಯುತ್ತಿದ್ದರೆ, ಡಿಸ್ಕ್ ಅನ್ನು ಸ್ಪರ್ಶಿಸುವ ಮೊದಲೇ ಆ ಎಕ್ಸೆಪ್ಶನ್ ಹೊರಬರಲಿ ಎಂಬುದು ನಿಮ್ಮ ಉದ್ದೇಶವಾಗಿರಲಿ.

ಎರಡನೆಯದಾಗಿ, ಸೀರಿಯಲೈಸ್ ಮಾಡಿದ ಡೇಟಾವನ್ನು ಗುರಿ (target) ಫೈಲ್ ಇರುವ ಅದೇ ಡೈರೆಕ್ಟರಿಯಲ್ಲಿರುವ ತಾತ್ಕಾಲಿಕ ಫೈಲ್‌ಗೆ ಬರೆಯಿರಿ. ಏಕಕಾಲದಲ್ಲಿ ಎರಡು ಪ್ರಕ್ರಿಯೆಗಳು ಸಂಘರ್ಷಕ್ಕೀಡಾಗದಂತೆ (collide) ರ್ಯಾಂಡಮ್ ಹೆಸರನ್ನು ಬಳಸಿ. ತಾತ್ಕಾಲಿಕ ಫೈಲ್ ಅನ್ನು ಅದೇ ಡೈರೆಕ್ಟರಿಯಲ್ಲಿ ಇಡುವುದು ಮುಖ್ಯ, ಏಕೆಂದರೆ rename ಕಾರ್ಯಾಚರಣೆಯು ಒಂದೇ ಫೈಲ್‌ಸಿಸ್ಟಮ್‌ನೊಳಗೆ ಮಾತ್ರ ಅಟಾಮಿಕ್ ಆಗಿರುತ್ತದೆ. ನಿಮ್ಮ ತಾತ್ಕಾಲಿಕ ಫೈಲ್ ಬೇರೆ ಪಾರ್ಟಿಶನ್‌ನಲ್ಲಿ ಇದ್ದರೆ, ಆಪರೇಟಿಂಗ್ ಸಿಸ್ಟಮ್ 'ಕಾಪಿ-ಅಂಡ್-ಡಿಲೀಟ್' (copy-and-delete) ಕ್ರಮವನ್ನು ಅನುಸರಿಸುತ್ತದೆ, ಇದು ತನ್ನದೇ ಆದ ವಿಫಲತೆಗಳನ್ನು ಉಂಟುಮಾಡಬಹುದು ಮತ್ತು ಇದು ಅಟಾಮಿಕ್ ಆಗಿರುವುದಿಲ್ಲ.

ಮೂರನೆಯದಾಗಿ, ಆ ತಾತ್ಕಾಲಿಕ ಫೈಲ್ ಅನ್ನು ಫಿಸಿಕಲ್ ಸ್ಟೋರೇಜ್‌ಗೆ ಫ್ಲಶ್ (flush) ಮಾಡಲು ಕರ್ನಲ್ ಅನ್ನು ಕೇಳಿ. Node ನ fsync (ಇಲ್ಲಿ ಫೈಲ್‌ಹ್ಯಾಂಡಲ್‌ನಲ್ಲಿನ sync ಮೆಥಡ್ ಆಗಿ ನೀಡಲಾಗಿದೆ), ಬಫರ್‌ಗಳು ಸಂಪೂರ್ಣವಾಗಿ ಬರೆಯಲ್ಪಡುವವರೆಗೆ ಬ್ಲಾಕ್ ಆಗುತ್ತದೆ. ಇದು ನಿಧಾನವಾಗಿದ್ದರೂ, ಕಾನ್ಫಿಗರೇಶನ್ ಬರವಣಿಗೆಗಳು ಅಪರೂಪವಾಗಿ ನಡೆಯುವುದರಿಂದ, ಈ ಕೆಲವು ಮಿಲಿಸೆಕೆಂಡುಗಳ ವಿಳಂಬವು ಡೇಟಾ ಸುರಕ್ಷತೆಗೆ (durability) ಯೋಗ್ಯವಾಗಿದೆ.

ನಾಲ್ಕನೆಯದಾಗಿ, ತಾತ್ಕಾಲಿಕ ಫೈಲ್ ಅನ್ನು ಮೂಲ ಪಾತ್ (original path) ಮೇಲೆ ಮರುನಾಮಕರಣ (rename) ಮಾಡಿ. POSIX ಸಿಸ್ಟಮ್‌ಗಳು ಮತ್ತು ವಿಂಡೋಸ್ ಎರಡರಲ್ಲೂ, ಇದು ಕಮಿಟ್ ಪಾಯಿಂಟ್ (commit point). ಮೂಲ ಪಾತ್ ಅನ್ನು ತೆರೆಯುವ ಓದುಗರು (readers) કા soit ಹಳೆಯ ಫೈಲ್ ಅನ್ನು ಪೂರ್ಣವಾಗಿ ನೋಡುತ್ತಾರೆ ಅಥವಾ ಹೊಸ ಫೈಲ್ ಅನ್ನು ಪೂರ್ಣವಾಗಿ ನೋಡುತ್ತಾರೆ. ಓದುಗರು ಪಾತ್ ಅನ್ನು ತೆರೆದಾಗ ಅರ್ಧಬರೆದ ಬಫರ್ ಅನ್ನು ನೋಡುವ ಯಾವುದೇ ಕ್ಷಣ ಇರುವುದಿಲ್ಲ.

ಐದನೆಯದಾಗಿ, ಪೇರೆಂಟ್ ಡೈರೆಕ್ಟರಿಯನ್ನು ಸಿಂಕ್ (sync) ಮಾಡಿ. ಇದು ಒಂದು ಸೂಕ್ಷ್ಮವಾದ ಎಡ್ಜ್ ಕೇಸ್ ಅನ್ನು (edge case) ನಿವಾರಿಸುತ್ತದೆ. ಮರುನಾಮಕರಣವು ಡೈರೆಕ್ಟರಿ ಎಂಟ್ರಿಯನ್ನು ಅಪ್‌ಡೇಟ್ ಮಾಡುತ್ತದೆ, ಆದರೆ ಡೈರೆಕ್ಟರಿ ಮೆಟಾಡೇಟಿಯೇ ಕರ್ನಲ್‌ನ ಪೇಜ್ ಕ್ಯಾಶ್‌ನಲ್ಲಿ ಇರಬಹುದು. ಯಶಸ್ವಿ ಮರುನಾಮಕರಣದ ನಂತರ ಇದ್ದಕ್ಕಿದ್ದಂತೆ ವಿದ್ಯುತ್ ವ್ಯತ್ಯಯವಾದರೆ, ಹೊಸ inode ರೆಫರೆನ್ಸ್ ಎಂದಿಗೂ ಶಾಶ್ವತವಾಗಿ ದಾಖಲಿಸಲ್ಪಡದ ಸ್ಥಿತಿಯಲ್ಲಿ ಫೈಲ್‌ಸಿಸ್ಟಮ್ ಉಳಿಯಬಹುದು. ಡೈರೆಕ್ಟರಿಯನ್ನು ಸಿಂಕ್ ಮಾಡುವುದು ಆ ಮೆಟಾಡೇಟಾ ಅಪ್‌ಡೇಟ್ ಅನ್ನು ಡಿಸ್ಕ್‌ಗೆ ಬಲವಂತವಾಗಿ ದಾಖಲಿಸುತ್ತದೆ ಮತ್ತು ಟ್ರಾನ್ಸಾಕ್ಷನ್ ಅನ್ನು ಪೂರ್ಣಗೊಳಿಸುತ್ತದೆ.

ಒಂದು ಪ್ರಾಯೋಗಿಕ Node.js ಅನುಷ್ಠಾನ

Node.js ಸ್ಟ್ಯಾಂಡರ್ಡ್ ಲೈಬ್ರರಿಯನ್ನು ಮಾತ್ರ ಬಳಸಿ ಆ ಮಾದರಿಯು ಪ್ರಾಯೋಗಿಕವಾಗಿ ಹೇಗಿರುತ್ತದೆ ಎಂಬುದು ಇಲ್ಲಿದೆ:

import { open, rename, rm } from "node:fs/promises";
import { dirname, basename, join } from "node:path";
import { randomUUID } from "node:crypto";

export async function writeJsonAtomic(path, value) {
  const directory = dirname(path);
  const temporary = join(directory, `.${basename(path)}.${randomUUID()}.tmp`);
  const body = `${JSON.stringify(value, null, 2)}\n`;
  let handle;

  try {
    handle = await open(temporary, "wx", 0o600);
    await handle.writeFile(body, "utf8");
    await handle.sync();
    await handle.close();
    handle = undefined;

    await rename(temporary, path);

    const directoryHandle = await open(directory, "r");
    try {
      await directoryHandle.sync();
    } finally {
      await directoryHandle.close();
    }
  } catch (error) {
    if (handle) await handle.close().catch(() => {});
    await rm(temporary, { force: true }).catch(() => {});
    throw error;
  }
}

ಈ ಕೋಡ್‌ನಲ್ಲಿ ಗಮನಿಸಬೇಕಾದ ಕೆಲವು ವಿವರಗಳು ಇಲ್ಲಿವೆ.

wx ಫ್ಲಾಗ್ ಎಂದರೆ "ಬರೆಯಿರಿ, ಆದರೆ ಫೈಲ್ ಈಗಾಗಲೇ ಅಸ್ತಿತ್ವದಲ್ಲಿದ್ದರೆ ವಿಫಲಗೊಳಿಸಿ" ಎಂದರ್ಥ. ಇದು UUID ಸಂಘರ್ಷ ಅಥವಾ ಹಿಂದಿನ ಕ್ರ್ಯಾಶ್ ಆದ ಪ್ರಕ್ರಿಯೆಯಿಂದ ಉಳಿದಿರುವ ತಾತ್ಕಾಲಿಕ ಫೈಲ್‌ನಿಂದ ರಕ್ಷಿಸುತ್ತದೆ. ನಿಮ್ಮ ತಾತ್ಕಾಲಿಕ ಫೈಲ್ ಇರಬೇಕಾದ ಜಾಗದಲ್ಲಿ ಯಾರಾದರೂ ದುರುದ್ದೇಶಪೂರಿತ ಫೈಲ್ ಇಟ್ಟಿದ್ದರೆ, ಅಲ್ಲಿರುವ ಫೈಲ್ ಅನ್ನು ಓವರ್‌ರೈಟ್ ಮಾಡುವ ಬದಲು ನೀವು ತಕ್ಷಣವೇ ಅದನ್ನು ತಿಳಿಯುವಿರಿ.

0o600 ಪರ್ಮಿಷನ್ ಮಾಸ್ಕ್ ತಾತ್ಕಾಲಿಕ ಫೈಲ್ ಅನ್ನು ಕೇವಲ ಮಾಲೀಕನ ಓದುವಿಕೆ (owner-read) ಮತ್ತು ಮಾ

catch block ನಲ್ಲಿನ ಕ್ಲೀನಪ್ (cleanup) ಉದ್ದೇಶಪೂರ್ವಕವಾಗಿ ರಕ್ಷಣಾತ್ಮಕವಾಗಿದೆ. ಫೈಲ್‌ಹ್ಯಾಂಡಲ್ (filehandle) ತೆರೆದ ನಂತರ ಏನಾದರೂ ಎಸೆತ (throw) ಉಂಟಾದರೆ, ಕೋಡ್ ಹ್ಯಾಂಡಲ್ ಅನ್ನು ಮುಚ್ಚಲು ಮತ್ತು ತಾತ್ಕಾಲಿಕ ಫೈಲ್ ಅನ್ನು ತೆಗೆದುಹಾಕಲು ಪ್ರಯತ್ನಿಸುತ್ತದೆ. ಇಲ್ಲಿ ಎರಡನೇ ದೋಷಗಳು (secondary errors) ಉಂಟಾದರೂ ಅವುಗಳನ್ನು ನಿರ್ಲಕ್ಷಿಸಲಾಗುತ್ತದೆ, ಇದರಿಂದ ಮೂಲ exception ಯಾವುದೇ ಅಡೆತಡೆಯಿಲ್ಲದೆ ಮುಂದುವರಿಯುತ್ತದೆ. ಕ್ಲೀನಪ್ ಮಾಡುವಾಗ ಉಂಟಾಗುವ permission error, ವೈಫಲ್ಯಕ್ಕೆ ಕಾರಣವಾದ ನಿಜವಾದ ಬಗ್ ಅನ್ನು (bug) ಮರೆಮಾಚಬಾರದು ಎಂಬುದು ಇದರ ಉದ್ದೇಶ.

ಈ ಮಾದರಿಯು ಎಲ್ಲಿ ಸಹಾಯ ಮಾಡುವುದನ್ನು ನಿಲ್ಲಿಸುತ್ತದೆ

Atomic file replacement ಎಂಬುದು 'torn writes' ಅನ್ನು ತಡೆಯುತ್ತದೆ. ಆದರೆ ಇದು 'lost updates' ಅನ್ನು ತಡೆಯಲಾರದು. ನಿಮ್ಮ CLI ನ ಎರಡು ಇನ್‌ಸ್ಟೆನ್ಸ್ (instances) ಏಕಕಾಲದಲ್ಲಿ ಒಂದೇ config ಅನ್ನು ಓದಿದರೆ, ಎರಡೂ ತಮ್ಮ ಎಡಿಟ್‌ಗಳನ್ನು ಮೆಮೊರಿಯಲ್ಲಿ ಮಾಡುತ್ತವೆ, ಎರಡೂ ಹೊಸ ತಾತ್ಕಾಲಿಕ ಫೈಲ್‌ಗಳನ್ನು ಬರೆಯುತ್ತವೆ ಮತ್ತು ಎರಡೂ ತಮ್ಮ rename ಪ್ರಕ್ರಿಯೆಗಳನ್ನು ನಿರ್ವಹಿಸಿದರೆ, ಎರಡನೇ rename ಗೆ ಜಯ ಸಿಗುತ್ತದೆ. ಮೊದಲ ಪ್ರಕ್ರಿಯೆಯು (process) ಎರಡನೇ ಪ್ರಕ್ರಿಯೆಯ ಬದಲಾವಣೆಗಳನ್ನು ಗಮನಿಸುವುದಿಲ್ಲ. ನಿಮ್ಮ ಅಪ್ಲಿಕೇಶನ್ ಮೇಲೆ ಅವಲಂಬಿತವಾಗಿ, ಇದರರ್ಥ ಒಬ್ಬ ಬಳಕೆದಾರರು ಒಂದು ಟರ್ಮಿನಲ್‌ನಲ್ಲಿ ಸೆಟ್ಟಿಂಗ್ ಅನ್ನು ಸೇರಿಸಬಹುದು ಮತ್ತು ಇನ್ನೊಬ್ಬ ಬಳಕೆದಾರರು ಅದನ್ನು ಮತ್ತೊಂದು ಟರ್ಮಿನಲ್‌ನಲ್ಲಿ ತೆಗೆದುಹಾಕಬಹುದು, ಆಗ ಅಂತಿಮ ಫೈಲ್ ಕೇವಲ ಕೊನೆಯ ಬರೆದವರ (last writer) ಬದಲಾವಣೆಗಳನ್ನು ಮಾತ್ರ ಪ್ರತಿಬಿಂಬಿಸುತ್ತದೆ.

ನಿಮ್ಮ ಟೂಲ್ (tool) ಏಕಕಾಲಿಕ ಬದಲಾವಣೆಗಳನ್ನು (concurrent mutators) ಬೆಂಬಲಿಸಬೇಕಾದರೆ, atomic write ನ ಮೇಲೆ ಒಂದು coordination mechanism ಅಗತ್ಯವಿದೆ. ಸರಳ ಸಂದರ್ಭಗಳಲ್ಲಿ advisory lock file ಕೆಲಸ ಮಾಡುತ್ತದೆ. Version vectors ಅಥವಾ config ಒಳಗಿರುವ monotonic revision number ಮೂಲಕ ಘರ್ಷಣೆಗಳನ್ನು (collisions) ಪತ್ತೆಹಚ್ಚಬಹುದು, ಇದರಿಂದ ಎರಡನೇ ಬರೆಯುವವರು (writer) ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಬಹುದು (retry). ಇವು ಸಂಕೀರ್ಣತೆಯನ್ನು (complexity) ಹೆಚ್ಚಿಸುತ್ತವೆ, ಮತ್ತು ಸಂಕೀರ್ಣತೆಯಲ್ಲೇ ಬಗ್‌ಗಳು ಅಡಗಿರುತ್ತವೆ.

ಅದಕ್ಕಾಗಿಯೇ ಈ ಮಿತಿ ಮುಖ್ಯವಾಗುತ್ತದೆ. ಒಂದು ಪ್ರಕ್ರಿಯೆಯು ಕಾಲಕಾಲಕ್ಕೆ ಅಪ್‌ಡೇಟ್ ಮಾಡುವ ಏಕೈಕ JSON blob, atomic file write ಗೆ ಉತ್ತಮವಾದ ಆಯ್ಕೆಯಾಗಿದೆ. ಒಮ್ಮೆ ನೀವು ಹಲವಾರು ರೆಕಾರ್ಡ್‌ಗಳನ್ನು ನಿರ್ವಹಿಸಲು, schemas ಜಾರಿಗೆ ತರಲು ಅಥವಾ concurrent mutations ಬಗ್ಗೆ ಚಿಂತಿಸಲು ಪ್ರಾರಂಭಿಸಿದರೆ, ನೀವು filesystem ನ ಮಿತಿಯನ್ನು ಮೀರಿ ಬೆಳೆದಿರುತ್ತೀರಿ ಎಂದರ್ಥ. SQLite ಇದೇ ಕಾರಣಕ್ಕಾಗಿ ಅಸ್ತಿತ್ವದಲ್ಲಿದೆ. ಇದು ನಿಮಗೆ atomic transactions, rollback journals ಮತ್ತು ಏಕಕಾಲಿಕ ಓದುಗರು (readers) ಹಾಗೂ ಬರೆಯುವವರನ್ನು (writers) ಸರಿಯಾಗಿ ನಿರ್ವಹಿಸುವ ವ್ಯವಸ್ಥೆಯನ್ನು ಒಂದೇ host-local ಫೈಲ್‌ನಲ್ಲಿ ನೀಡುತ್ತದೆ. ಒಂದು ಚತುರ file protocol ಎಂಬುದು ಡೇಟಾಬೇಸ್ ಅಲ್ಲ, ಮತ್ತು ನೀವು ಅದನ್ನು ಡೇಟಾಬೇಸ್ ಎಂದು ನಟಿಸಲು ನಿಮ್ಮ ನಿರ್ವಹಣಾ ಬಜೆಟ್ ಅನ್ನು ವ್ಯರ್ಥ ಮಾಡಬಾರದು.

ನಿಜವಾದ ಸಾರಾಂಶ

ಮುಂದಿನ ಬಾರಿ ನೀವು CLI tool ಒಳಗೆ writeFile ಅನ್ನು ಬಳಸುವಾಗ, ಒಂದು ಕ್ಷಣ ನಿಲ್ಲಿಸಿ. Serialization ಕಷ್ಟದ ಭಾಗವಲ್ಲ. Durability ಕಷ್ಟದ ಭಾಗ. Config ಫೈಲ್‌ಗಳು stream ಮಾಡಲು ತುಂಬಾ ಚಿಕ್ಕದಾಗಿವೆ ಮತ್ತು truncate ಮಾಡಲು ತುಂಬಾ ಪ್ರಮುಖವಾಗಿವೆ. ಇಡೀ payload ಅನ್ನು ಒಂದು ಗುಪ್ತ (hidden) sibling ಫೈಲ್‌ಗೆ ಬರೆಯಿರಿ, ಅದನ್ನು flush ಮಾಡಿ, rename ಮೂಲಕ commit ಮಾಡಿ ಮತ್ತು ಡೈರೆಕ್ಟರಿಯನ್ನು (directory) ಅದರ ಬಗ್ಗೆ ತಿಳಿಸಿ. ನಿಮ್ಮ ಬಳಕೆದಾರರು Ctrl-C ಒತ್ತಬಹುದು, ಪವರ್ ಕಾರ್ಡ್ ಅನ್ನು ಎಳೆಯಬಹುದು ಅಥವಾ ತಮ್ಮ ಲ್ಯಾಪ್‌ಟಾಪ್ ಮುಚ್ಚಬಹುದು. ಯಂತ್ರವು ಮತ್ತೆ ಚಾಲನೆಯಾದಾಗ, ಫೈಲ್‌ನಲ್ಲಿ ಹಳೆಯ ಸ್ಥಿತಿಯಿರುತ್ತದೆ ಅಥವಾ ಹೊಸ ಸ್ಥಿತಿಯಿರುತ್ತದೆ. ಎರಡರ ಮಧ್ಯದ ಸ್ಥಿತಿ ಇರುವುದಿಲ್ಲ.