-
Notifications
You must be signed in to change notification settings - Fork 40
BFD-4841: Improve IDR Pipeline error handling #3244
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
14 commits
Select commit
Hold shift + click to select a range
c2851f8
Add tblib
malessi 5fe75a7
Wrap model extraction errors instead of logging directly
malessi 7a18322
Unnest intermediate ExceptionGroup in loader
malessi 4cb57fe
Unnest intermediate ExceptionGroup in __init__; don't re-raise unnece…
malessi 6a72d31
Introduce exception_utils module for serializing exceptions between p…
malessi 5bbd8ab
Use exception serialization at process boundaries; quiet noise from s…
malessi 1f6db84
Catch BaseException, not exceptions in the Group
malessi ee21252
Remove unnecessary type: ignore
malessi a7c0df8
Revert change to comment in __init__
malessi 79a9fec
Revert extraneous newline add in loader
malessi 40b2deb
Remove unnecessary comments; reword some comments
malessi 5ffb6d3
Ensure pipeline doesn't wait forever for batch worker on startup
malessi acb4779
Exit with code 1 on unrecoverable exceptions
malessi a754885
Add comment explaining setting various sys properties
malessi File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -15,6 +15,7 @@ dependencies = [ | |
| "click>=8.3.3", | ||
| "anyio", | ||
| "loguru", | ||
| "tblib>=3.2.2", | ||
| ] | ||
|
|
||
| [dependency-groups] | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,84 @@ | ||
| from dataclasses import dataclass | ||
| from types import TracebackType | ||
| from typing import Any, cast | ||
|
|
||
| from tblib import Traceback # type: ignore | ||
|
malessi marked this conversation as resolved.
|
||
|
|
||
| type SerializedExceptionChain = list[SerializedException | SerializedExceptionGroup] | ||
|
|
||
|
|
||
| @dataclass(frozen=True, eq=True) | ||
| class SerializedException: | ||
| ex: BaseException | ||
| tb_dict: dict[str, Any] | ||
|
|
||
|
|
||
| @dataclass(frozen=True, eq=True) | ||
| class SerializedExceptionGroup: | ||
| ex_group: BaseExceptionGroup[Exception] | ExceptionGroup[Exception] | ||
| tb_dict: dict[str, Any] | ||
| exceptions: list[SerializedException] | ||
|
|
||
|
|
||
| def get_exception_tb_dict(ex: BaseException) -> dict[str, Any]: | ||
| return Traceback(ex.__traceback__).as_dict() # type: ignore | ||
|
|
||
|
|
||
| def get_traceback_from_dict(tb_dict: dict[str, Any]) -> TracebackType | None: | ||
| return cast(Traceback, Traceback.from_dict(tb_dict)).as_traceback() # type: ignore | ||
|
|
||
|
|
||
| def serialize_exception_chain(exc: BaseException) -> SerializedExceptionChain: | ||
| chain: list[SerializedException | SerializedExceptionGroup] = [] | ||
| current: BaseException | None = exc | ||
|
|
||
| while current is not None: | ||
| if isinstance(current, BaseExceptionGroup | ExceptionGroup): | ||
| current = cast(BaseExceptionGroup[Exception], current) | ||
| serialized_inner: list[SerializedException] = [ | ||
| SerializedException(ex=inner, tb_dict=get_exception_tb_dict(inner)) | ||
| for inner in current.exceptions | ||
| ] | ||
| chain.append( | ||
| SerializedExceptionGroup( | ||
| ex_group=current, | ||
| tb_dict=get_exception_tb_dict(current), | ||
| exceptions=serialized_inner, | ||
| ) | ||
| ) | ||
| else: | ||
| chain.append(SerializedException(ex=current, tb_dict=get_exception_tb_dict(current))) | ||
|
|
||
| current = current.__cause__ | ||
|
|
||
| return chain | ||
|
|
||
|
|
||
| def rebuild_exception_chain(chain: SerializedExceptionChain) -> BaseException: | ||
| if not chain: | ||
| raise ValueError("Chain must contain at least one exception") | ||
|
|
||
| resolved: list[tuple[BaseException, dict[str, Any]]] = [] | ||
| for entry in chain: | ||
| if isinstance(entry, SerializedExceptionGroup): | ||
| # Restore tracebacks on every inner exception. | ||
| restored_inners: list[BaseException] = [] | ||
| for serialized_inner in entry.exceptions: | ||
| inner_exc = serialized_inner.ex | ||
| inner_exc.__traceback__ = get_traceback_from_dict(serialized_inner.tb_dict) | ||
| restored_inners.append(inner_exc) | ||
|
|
||
| # Re-create the group with the restored inner exceptions so that | ||
| # the group's own .exceptions tuple reflects the restored state. | ||
| restored_group = entry.ex_group.derive(restored_inners) | ||
| resolved.append((restored_group, entry.tb_dict)) | ||
| else: | ||
| resolved.append((entry.ex, entry.tb_dict)) | ||
|
|
||
| # Re-create the "exception chain" (of __cause__s) and restore top-level (non-inner Exception) | ||
| # tracebacks | ||
| for i, (exc, tb_dict) in enumerate(resolved): | ||
| exc.__traceback__ = get_traceback_from_dict(tb_dict) | ||
| exc.__cause__ = resolved[i + 1][0] if i < len(resolved) - 1 else None | ||
|
|
||
| return resolved[0][0] | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.