Repository navigation
fix: async engine side-effect column propagation and collision resolution #509
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
Changes from 2 commits
b88508d
c378684
ece8f8c
818ef66
d47abcb
604aa21
ba84679
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -105,8 +105,15 @@ def add_edge(self, upstream: str, downstream: str) -> None: | |
| self._downstream.setdefault(upstream, set()).add(downstream) | ||
|
|
||
| def set_side_effect(self, side_effect_col: str, producer: str) -> None: | ||
| """Map a side-effect column name to its producing column.""" | ||
| self._side_effect_map[side_effect_col] = producer | ||
| """Map a side-effect column name to its producing column. | ||
|
|
||
| First-writer-wins: if a side-effect column is already mapped to a | ||
| different producer, the earlier mapping is kept. This matches sync | ||
| engine semantics where earlier consumers see the first producer's | ||
| value. | ||
| """ | ||
| if side_effect_col not in self._side_effect_map: | ||
| self._side_effect_map[side_effect_col] = producer | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Isn't a side effect column 1:1 with its producer? In which scenario would multiple producers point to the same side effect column?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You're right that in a correctly configured pipeline it should be 1:1. The collision scenario comes from Anonymizer's detection workflow - it has branching pipeline paths where different stages declare the same side-effect columns (e.g. That said, this is an unusual pattern and silently ignoring the second registration isn't great. I'll add a warning log on collision so misconfigurations don't go unnoticed.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. in this example wouldn't the side effect columns be
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I looked into this - the collision appears to be real. Side-effect column names are bare strings with no namespacing. In Anonymizer's detection workflow ( # merge_and_build_candidates (line 79)
side_effect_columns=[COL_MERGED_TAGGED_TEXT, COL_VALIDATION_CANDIDATES]
# prepare_validation_inputs (line 125)
side_effect_columns=[COL_MERGED_TAGGED_TEXT, COL_VALIDATION_CANDIDATES]Both resolve to the same literal strings ( I considered whether namespacing (e.g. Open to other ideas, but first-writer-wins + warning seems like the right pragmatic fix here.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. After our offline discussion, I agree with you - multiple producers for the same side-effect column is an anti-pattern. The Anonymizer case is actually an overwrite pattern within the same pipeline (not alternative paths), which works in the sync engine by accident. I've updated |
||
|
|
||
| def resolve_side_effect(self, column: str) -> str: | ||
| """Resolve a column name through the side-effect map. | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.