Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions app/src/App/CLI/Purs.purs
Original file line number Diff line number Diff line change
Expand Up @@ -191,10 +191,16 @@ callCompiler compilerArgs = do
compilerRaceConditionError :: String
compilerRaceConditionError = "Unexpected end of JSON input"

-- | Heap exhaustion can leave stdout empty, so JSON decoding also reports EOF.
isCompilerHeapExhaustion :: CompilerFailure -> Boolean
isCompilerHeapExhaustion = case _ of
UnknownError err -> String.contains (String.Pattern "purs: Heap exhausted") err
_ -> false
Comment thread
thomashoneyman marked this conversation as resolved.

-- | Check if a compiler failure is due to the known race condition bug.
isCompilerRaceCondition :: CompilerFailure -> Boolean
isCompilerRaceCondition = case _ of
UnknownError err -> String.contains (String.Pattern compilerRaceConditionError) err
isCompilerRaceCondition failure = case failure of
UnknownError err -> not (isCompilerHeapExhaustion failure) && String.contains (String.Pattern compilerRaceConditionError) err
_ -> false

-- | Compile PureScript source files with automatic retry for transient errors.
Expand Down
21 changes: 15 additions & 6 deletions app/src/App/Effect/PackageSets.purs
Original file line number Diff line number Diff line change
Expand Up @@ -263,12 +263,21 @@ handle env = case _ of
compileInstalledPackages :: Version -> Run _ (Either CompilerFailure String)
compileInstalledPackages compiler = do
Log.debug "Compiling installed packages..."
Purs.compile
{ globs: [ Path.concat [ Path.basename packagesWorkDir, "**/*.purs" ] ]
, profile: Purs.PackageSetBuild
, version: Just compiler
, cwd: Just env.workdir
}
let
compile = Purs.compile
{ globs: [ Path.concat [ Path.basename packagesWorkDir, "**/*.purs" ] ]
, profile: Purs.PackageSetBuild
, version: Just compiler
, cwd: Just env.workdir
}
result <- compile
case result of
Left err | Purs.isCompilerHeapExhaustion err -> do
Log.warn "Compiler heap exhausted; clearing package-set output and retrying once."
-- Keep the backup intact so a failed retry can still roll back.
Comment thread
thomashoneyman marked this conversation as resolved.
Outdated
FS.Extra.remove outputWorkDir
compile
_ -> pure result

attemptChanges :: Version -> PackageSet -> ChangeSet -> Run _ (Either CompilerFailure PackageSet)
attemptChanges compiler (PackageSet set) changes = do
Expand Down
11 changes: 11 additions & 0 deletions app/test/App/CLI/Purs.purs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,17 @@ spec = do
let err = UnknownError "Some prefix text\nJSON: Unexpected end of JSON input\nSome suffix"
Purs.isCompilerRaceCondition err `Assertions.shouldEqual` true

Spec.it "Recognizes heap exhaustion without treating its empty JSON output as a race" do
let
err = UnknownError $ String.joinWith "\n"
[ "purs: Heap exhausted;"
, "purs: Current maximum heap size is 3221225472 bytes (3072 MB)."
, "JSON: Unexpected end of JSON input"
]
Purs.isCompilerHeapExhaustion err `Assertions.shouldEqual` true
Purs.isCompilerRaceCondition err `Assertions.shouldEqual` false
Purs.isCompilerHeapExhaustion (UnknownError "JSON: Unexpected end of JSON input") `Assertions.shouldEqual` false

Comment thread
thomashoneyman marked this conversation as resolved.
Outdated
Spec.it "Does not detect race condition for normal UnknownError" do
let err = UnknownError "Some other compiler error message"
Purs.isCompilerRaceCondition err `Assertions.shouldEqual` false
Expand Down
Loading