Skip to content

Commit

Permalink
fix: use atomic writes for data store file operations
Browse files Browse the repository at this point in the history
  • Loading branch information
ascorbic committed Dec 11, 2024
1 parent d33c215 commit 8e9ecf0
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 5 deletions.
5 changes: 5 additions & 0 deletions .changeset/tame-bags-remember.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'astro': patch
---

Fixes a bug that caused errors in dev when editing sites with large numbers of MDX pages
24 changes: 19 additions & 5 deletions packages/astro/src/content/mutable-data-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,23 @@ import { AstroError, AstroErrorData } from '../core/errors/index.js';
import { IMAGE_IMPORT_PREFIX } from './consts.js';
import { type DataEntry, ImmutableDataStore } from './data-store.js';
import { contentModuleToId } from './utils.js';
import { tmpdir } from 'node:os';
import { join } from 'node:path';

const SAVE_DEBOUNCE_MS = 500;

// Write a file atomically, without triggering the file watcher
async function writeFileAtomic(filePath: PathLike, data: string) {
const dir = await fs.mkdtemp(tmpdir() + '/astro-');
const tempFile = join(dir, 'temp');
await fs.writeFile(tempFile, data);
try {
await fs.rename(tempFile, filePath);
} finally {
await fs.rmdir(dir).catch(() => {});
}
}

/**
* Extends the DataStore with the ability to change entries and write them to disk.
* This is kept as a separate class to avoid needing node builtins at runtime, when read-only access is all that is needed.
Expand Down Expand Up @@ -86,7 +100,7 @@ export class MutableDataStore extends ImmutableDataStore {

if (this.#assetImports.size === 0) {
try {
await fs.writeFile(filePath, 'export default new Map();');
await writeFileAtomic(filePath, 'export default new Map();');
} catch (err) {
throw new AstroError(AstroErrorData.UnknownFilesystemError, { cause: err });
}
Expand All @@ -110,7 +124,7 @@ ${imports.join('\n')}
export default new Map([${exports.join(', ')}]);
`;
try {
await fs.writeFile(filePath, code);
await writeFileAtomic(filePath, code);
} catch (err) {
throw new AstroError(AstroErrorData.UnknownFilesystemError, { cause: err });
}
Expand All @@ -122,7 +136,7 @@ export default new Map([${exports.join(', ')}]);

if (this.#moduleImports.size === 0) {
try {
await fs.writeFile(filePath, 'export default new Map();');
await writeFileAtomic(filePath, 'export default new Map();');
} catch (err) {
throw new AstroError(AstroErrorData.UnknownFilesystemError, { cause: err });
}
Expand All @@ -143,7 +157,7 @@ export default new Map([${exports.join(', ')}]);
export default new Map([\n${lines.join(',\n')}]);
`;
try {
await fs.writeFile(filePath, code);
await writeFileAtomic(filePath, code);
} catch (err) {
throw new AstroError(AstroErrorData.UnknownFilesystemError, { cause: err });
}
Expand Down Expand Up @@ -298,7 +312,7 @@ export default new Map([\n${lines.join(',\n')}]);
return;
}
try {
await fs.writeFile(filePath, this.toString());
await writeFileAtomic(filePath, this.toString());
this.#file = filePath;
this.#dirty = false;
} catch (err) {
Expand Down

0 comments on commit 8e9ecf0

Please sign in to comment.