Skip to content

⚡ Bolt: Use EAFP pattern in writeFile to reduce syscalls#2782

Merged
srod merged 1 commit intodevelopfrom
bolt/optimize-writefile-eafp-13295786206695180100
Jan 16, 2026
Merged

⚡ Bolt: Use EAFP pattern in writeFile to reduce syscalls#2782
srod merged 1 commit intodevelopfrom
bolt/optimize-writefile-eafp-13295786206695180100

Conversation

@google-labs-jules
Copy link
Contributor

@google-labs-jules google-labs-jules bot commented Jan 14, 2026

⚡ Bolt: Use EAFP pattern in writeFile to reduce syscalls

💡 What: Removed the explicit lstat check (isDirectory) before writing files in packages/utils.
🎯 Why: Checking for existence/directory before writing ("Look Before You Leap") adds an unnecessary system call. By just attempting the write ("Easier to Ask for Forgiveness than Permission"), we save one syscall in the happy path (writing to a file).
📊 Impact: Reduces overhead for every file write operation by 1 syscall. In scenarios with many small file writes, this reduces I/O latency.
🔬 Measurement: Verified that writing to a directory still throws an error (EISDIR) and is correctly handled/wrapped by the existing error handling logic. Existing tests passed.


PR created automatically by Jules for task 13295786206695180100 started by @srod


Summary by cubic

Switch writeFile and writeFileAsync to EAFP by removing pre-write lstat checks and letting fs writes fail if the target is a directory. This saves one syscall per write and reduces I/O overhead while keeping error behavior the same.

  • Refactors
    • Removed isDirectory/isDirectoryAsync and lstat usage.
    • Rely on fs to throw (e.g., EISDIR) and wrap via FileOperationError.
    • No behavior change for consumers; existing tests pass.

Written for commit 4c922b4. Summary will update on new commits.

Summary by CodeRabbit

  • Refactor
    • Removed directory path validation checks from writeFile and writeFileAsync functions to streamline implementation and reduce code complexity
    • Eliminated directory detection helper functions and their associated imports
    • Maintained all existing write operations and error handling while simplifying internal logic

✏️ Tip: You can customize this high-level summary in your review settings.

@google-labs-jules
Copy link
Contributor Author

👋 Jules, reporting for duty! I'm here to lend a hand with this pull request.

When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down.

I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job!

For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!

New to Jules? Learn more at jules.google/docs.


For security, I will only act on instructions from the user who triggered this task.

@changeset-bot
Copy link

changeset-bot bot commented Jan 14, 2026

⚠️ No Changeset found

Latest commit: 4c922b4

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 14, 2026

📝 Walkthrough

Walkthrough

Removes runtime checks that prevented writing to directory paths in writeFile and writeFileAsync functions. Eliminates directory-detection helper functions (isDirectory and isDirectoryAsync) and their associated imports, including lstat-related dependencies. Core write operations remain unchanged.

Changes

Cohort / File(s) Summary
Directory validation removal
packages/utils/src/writeFile.ts
Removed isDirectory and isDirectoryAsync helper functions; eliminated pre-write directory checks from both sync and async write operations; cleaned up lstat imports

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

Poem

🐰 A hop, a skip, through files we go,
Directory checks? They had to go!
Simpler paths, no guards in sight,
Writing files feels oh-so-right!

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: adopting EAFP pattern in writeFile to reduce syscalls by removing lstat-based directory checks.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

srod pushed a commit that referenced this pull request Jan 15, 2026
Acknowledging duplicate status.
Stopping work on this task.
@srod srod force-pushed the bolt/optimize-writefile-eafp-13295786206695180100 branch 3 times, most recently from 8fbe4d7 to 89f9aa5 Compare January 16, 2026 16:40
Optimizes `writeFile` and `writeFileAsync` in `packages/utils` by removing the explicit `lstat` check for directories before writing. Instead, it relies on the underlying `fs` write operation to throw `EISDIR` if the target is a directory. This saves one syscall per write operation.

- Removes `isDirectory` and `isDirectoryAsync` checks.
- Updates `writeFile` to catch filesystem errors naturally.
- Maintains backward compatibility by ensuring errors are still wrapped in `FileOperationError` (via `handleWriteError`).
- Verified with existing tests.
@srod srod force-pushed the bolt/optimize-writefile-eafp-13295786206695180100 branch from 89f9aa5 to 4c922b4 Compare January 16, 2026 21:12
@srod srod marked this pull request as ready for review January 16, 2026 21:13
Copy link

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 1 file

@srod
Copy link
Owner

srod commented Jan 16, 2026

@greptile

@greptile-apps
Copy link

greptile-apps bot commented Jan 16, 2026

Greptile Summary

Refactored writeFile and writeFileAsync to use EAFP (Easier to Ask for Forgiveness than Permission) pattern by removing the pre-write lstat directory check. This reduces syscalls by one per file write operation while maintaining identical error behavior.

  • Removed isDirectory() and isDirectoryAsync() helper functions
  • Removed lstat and lstatSync imports
  • Removed directory checks before writeFileSync and writeFileFs calls
  • Error handling remains unchanged - EISDIR errors from the filesystem are caught and wrapped in FileOperationError
  • All existing tests pass, confirming behavior preservation

Confidence Score: 5/5

  • This PR is safe to merge with minimal risk
  • The change is a straightforward performance optimization that removes redundant filesystem checks. The EAFP pattern is well-established and appropriate here. Comprehensive test coverage (lines 283-290, 360-367) verifies that directory write attempts still fail correctly. The refactoring maintains identical error behavior while reducing I/O overhead.
  • No files require special attention

Important Files Changed

Filename Overview
packages/utils/src/writeFile.ts Removed pre-write lstat checks to adopt EAFP pattern, reducing syscalls while maintaining error handling

Sequence Diagram

sequenceDiagram
    participant Caller
    participant writeFile
    participant resolveTargetFile
    participant validateContent
    participant writeFileSync
    participant handleWriteError
    participant FileOperationError

    Caller->>writeFile: writeFile({file, content, index})
    activate writeFile
    
    writeFile->>resolveTargetFile: resolveTargetFile(file, index)
    activate resolveTargetFile
    alt Invalid file
        resolveTargetFile-->>writeFile: throw ValidationError
    else Valid file
        resolveTargetFile-->>writeFile: targetFile
    end
    deactivate resolveTargetFile
    
    writeFile->>validateContent: validateContent(content)
    activate validateContent
    alt Empty content
        validateContent-->>writeFile: throw ValidationError
    else Valid content
        validateContent-->>writeFile: void
    end
    deactivate validateContent
    
    Note over writeFile,writeFileSync: EAFP: Try write without pre-check
    writeFile->>writeFileSync: writeFileSync(targetFile, content, encoding)
    activate writeFileSync
    alt Target is directory (EISDIR)
        writeFileSync-->>writeFile: throw EISDIR error
        writeFile->>handleWriteError: handleWriteError(error, file)
        activate handleWriteError
        handleWriteError->>FileOperationError: new FileOperationError("write to", file, error)
        FileOperationError-->>handleWriteError: wrapped error
        handleWriteError-->>Caller: throw FileOperationError
        deactivate handleWriteError
    else Write succeeds
        writeFileSync-->>writeFile: success
        writeFile-->>Caller: return content
    end
    deactivate writeFileSync
    deactivate writeFile
Loading

@srod
Copy link
Owner

srod commented Jan 16, 2026

@coderabbitai review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 16, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/utils/src/writeFile.ts (1)

51-55: Update JSDoc to match EAFP behavior.

The description still says the function “ensures the target is not a directory,” which is no longer true after removing the pre-check. Please update the comment to reflect that directory targets now fail via the underlying write error.

✏️ Suggested JSDoc update
- * Resolves the target from `file` (string or array) using `index` when provided, validates the content,
- * ensures the target is not a directory, and writes the content to disk.
+ * Resolves the target from `file` (string or array) using `index` when provided, validates the content,
+ * and writes the content to disk; directory targets will fail via the underlying write error.

@srod srod merged commit 6dc83f9 into develop Jan 16, 2026
10 checks passed
@srod srod deleted the bolt/optimize-writefile-eafp-13295786206695180100 branch January 16, 2026 21:25
@codecov
Copy link

codecov bot commented Jan 16, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 99.37%. Comparing base (3f4fcc8) to head (4c922b4).
⚠️ Report is 2 commits behind head on develop.

Additional details and impacted files
@@             Coverage Diff             @@
##           develop    #2782      +/-   ##
===========================================
- Coverage    99.37%   99.37%   -0.01%     
===========================================
  Files           63       63              
  Lines         1290     1277      -13     
  Branches       393      391       -2     
===========================================
- Hits          1282     1269      -13     
  Misses           8        8              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant