Repository navigation
Conversation
|
This replaces stale-closed #8186. The problem still reproduces on current main. The patch passes its regression, 349 broader tests and Ruff checks. /request-review @eugenegujing |
|
/request-review @eugenegujing |
Automated Reviewer SuggestionsBased on the
|
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #8955 +/- ##
============================================
- Coverage 92.30% 92.05% -0.26%
+ Complexity 5046 5041 -5
============================================
Files 1260 1286 +26
Lines 53887 55900 +2013
Branches 6711 7134 +423
============================================
+ Hits 49743 51458 +1715
- Misses 2486 2692 +206
- Partials 1658 1750 +92
*This pull request uses carry forward flags. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
| config | throughput | MB/s | latency | max Δ latest / 7d | |
|---|---|---|---|---|---|
| 🔴 | bs=10 sw=10 sl=64 | 748 | 0.457 | 13,030/17,237/17,237 us | 🔴 +8.7% / 🔴 +19.8% |
| 🔴 | bs=100 sw=10 sl=64 | 1,762 | 1.075 | 53,593/86,706/86,706 us | 🔴 +14.6% / 🟢 +51.2% |
| ⚪ | bs=1000 sw=10 sl=64 | 2,132 | 1.301 | 464,119/530,560/530,560 us | ⚪ within ±5% / 🟢 +78.1% |
Baseline details
Latest main 7426431 from same runner
| config | metric | PR | latest main | 7d avg | Δ latest | Δ 7d |
|---|---|---|---|---|---|---|
| bs=10 sw=10 sl=64 | throughput | 748 tuples/sec | 799 tuples/sec | 879.43 tuples/sec | -6.4% | -14.9% |
| bs=10 sw=10 sl=64 | MB/s | 0.457 MB/s | 0.488 MB/s | 0.537 MB/s | -6.4% | -14.9% |
| bs=10 sw=10 sl=64 | p50 | 13,030 us | 11,983 us | 11,622 us | +8.7% | +12.1% |
| bs=10 sw=10 sl=64 | p95 | 17,237 us | 18,346 us | 14,390 us | -6.0% | +19.8% |
| bs=10 sw=10 sl=64 | p99 | 17,237 us | 18,346 us | 17,721 us | -6.0% | -2.7% |
| bs=100 sw=10 sl=64 | throughput | 1,762 tuples/sec | 1,830 tuples/sec | 1,166 tuples/sec | -3.7% | +51.2% |
| bs=100 sw=10 sl=64 | MB/s | 1.075 MB/s | 1.117 MB/s | 0.711 MB/s | -3.8% | +51.1% |
| bs=100 sw=10 sl=64 | p50 | 53,593 us | 53,197 us | 91,298 us | +0.7% | -41.3% |
| bs=100 sw=10 sl=64 | p95 | 86,706 us | 75,649 us | 98,241 us | +14.6% | -11.7% |
| bs=100 sw=10 sl=64 | p99 | 86,706 us | 75,649 us | 113,458 us | +14.6% | -23.6% |
| bs=1000 sw=10 sl=64 | throughput | 2,132 tuples/sec | 2,140 tuples/sec | 1,197 tuples/sec | -0.4% | +78.1% |
| bs=1000 sw=10 sl=64 | MB/s | 1.301 MB/s | 1.306 MB/s | 0.731 MB/s | -0.4% | +78.1% |
| bs=1000 sw=10 sl=64 | p50 | 464,119 us | 465,079 us | 899,658 us | -0.2% | -48.4% |
| bs=1000 sw=10 sl=64 | p95 | 530,560 us | 538,015 us | 941,120 us | -1.4% | -43.6% |
| bs=1000 sw=10 sl=64 | p99 | 530,560 us | 538,015 us | 990,298 us | -1.4% | -46.4% |
Raw CSV
config_idx,batch_size,schema_width,string_len,num_batches,total_ms,total_tuples,total_bytes,tuples_per_sec,mb_per_sec,lat_p50_us,lat_p95_us,lat_p99_us
0,10,10,64,20,267.38,200,128000,748,0.457,13029.65,17237.06,17237.06
1,100,10,64,20,1135.11,2000,1280000,1762,1.075,53593.21,86706.11,86706.11
2,1000,10,64,20,9381.79,20000,12800000,2132,1.301,464118.53,530560.01,530560.0195fdbdc to
2743266
Compare
…smatches (apache#8769) ### What changes were proposed in this PR? Clear messages for the common Python UDF mistakes that show up while the workflow runs: - **`return` instead of `yield`** in `process_tuple`, `process_batch`, `process_table` or `produce` now says `process_table must yield results, not return them. Replace return x with yield x.` Before, users saw `pampy.MatchError: '_' not provided` or `'NoneType' object is not iterable`. Returning a list still works. - **`__init__` without `super().__init__()`** on a table or batch UDF no longer crashes with `'_TableOperator__table_data'`. The buffers are created on first use, the same way `Operator` already creates its template decoder. - **A DataFrame in a non-binary column** now says which column, and to yield the DataFrame itself or make the column binary. A DataFrame in a BINARY column is pickled as before. - **Output columns that don't match** keep the original message and point to "Retain input columns" and "Extra output column(s)" (or "Columns" for a 1-out Python UDF). Before and after, in the Console: | Before | After | |---|---| |<img width="800" height="288" alt="runtime-before" src="https://github.com/user-attachments/assets/7f854ffe-f5eb-4013-8fe4-9eb3a9e740ff" /> | <img width="800" height="288" alt="runtime-after" src="https://github.com/user-attachments/assets/fbaec933-683f-4dd2-b603-5d988b4f338d" /> | ### Any related issues, documentation, discussions? Part of apache#8736. Split out of apache#8737. ### How was this PR tested? New tests in `test_operator.py` (each `return` case, a returned list still working, table and batch UDFs with and without `super().__init__()`) and `test_data_processor.py` (`process_tuple` and `on_finish` returning a value, a DataFrame in BINARY, LARGE_BINARY and STRING columns, a missing or misspelled column next to a DataFrame, a wrong column type). ``` cd amber pytest -m "not integration" src/test/python/core/models/test_operator.py src/test/python/core/runnables/test_data_processor.py pytest -m "not integration" ruff check src/main/python src/test/python && ruff format --check src/main/python src/test/python ``` The screenshots are from a local Texera built from this branch. ### Was this PR authored or co-authored using generative AI tooling? Generated-by: Claude Code (Claude Opus 5.5) --------- Co-authored-by: suryaacharan <suryaacharan@suryaacharans-MacBook-Pro.local> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…che#8768) ### What changes were proposed in this PR? When a Python UDF fails to load, the error now says what to fix. The existing "There should be one and only one Operator defined" sentence stays first, so anything matching on it still works. The line number and fix are attached as a note to the original exception, so its type, message and attributes stay as raised. The RPC server now includes exception notes in the `ControlError` message, which is what the Static Error tab shows. | Mistake | Message now adds | |---|---| | No class (e.g. the whole template left commented out) | `No Operator class was found. Uncomment or write exactly one class...` | | Method doesn't match the base class | `WrapperClass subclasses UDFOperatorV2 but does not implement process_tuple. If you meant process_table, subclass UDFTableOperator instead.` | | Two classes | `Found 2: FirstOperator, SecondOperator. Keep one and delete or comment out the others.` | | Missing `from pytexera import *` | `name 'UDFOperatorV2' is not defined (line 2 of the UDF code). Add from pytexera import * at the top of the UDF.` | | `@overrides` on the wrong method | the base class to method pairing | | A class with two pytexera bases | `X uses more than one base class (UDFOperatorV2, UDFTableOperator). Subclass exactly one.` | | Any other load error | the line number in the user's code | Before and after, in the Static Error tab. Before is the untouched template; after is a class with the wrong method: | Before | After | |---|---| | <img width="800" height="288" alt="load-before" src="https://github.com/user-attachments/assets/bd2ac22c-1953-435c-b3d5-0cf2e6f0ddda" />| <img width="800" height="348" alt="load-after" src="https://github.com/user-attachments/assets/53985c6f-9ad3-4d93-aed1-0974d14e85ad" /> | Missing import, after: <img width="800" height="303" alt="load-after-import" src="https://github.com/user-attachments/assets/c1ed1322-f7d0-4937-8aa2-848917a115ba" /> ### Any related issues, documentation, discussions? Part of apache#8736. Split out of apache#8737 as the reviewer asked. ### How was this PR tested? New tests in `test_executor_manager.py` cover each case above, plus a syntax error, a `KeyError` and a custom exception at load time (both keep their own message and get the hint as a note), a class alias, and a `LoopEndOperator` subclass. `test_async_rpc_server.py` covers notes in `ControlError`, and loads a broken UDF inside a handler to check the message that gets sent back. ``` cd amber pytest -m "not integration" src/test/python/core/architecture/managers/test_executor_manager.py src/test/python/core/architecture/rpc/test_async_rpc_server.py pytest -m "not integration" ruff check src/main/python src/test/python && ruff format --check src/main/python src/test/python ``` The screenshots are from a local Texera built from this branch. The displayed text for those cases is the same after the follow-up commit. Known limitations: UI-parameter source-line mapping relies on the generated hook's reserved name and structure. Runtime traceback locations (e.g., errors inside process_tuple) are not remapped. ### Was this PR authored or co-authored using generative AI tooling? Generated-by: Claude Code (Claude Opus 5.5) --------- Co-authored-by: suryaacharan <suryaacharan@suryaacharans-MacBook-Pro.local> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…ad of UCI (apache#9000) ### What changes were proposed in this PR? The single-node examples ship `Iris.csv` in both the source release and the docker-compose bundle, and `LICENSE` records it as CC BY 4.0 from the UCI repository (apache#8803). ASF policy allows CC BY works only in binary form ("only include them in binary form", https://www.apache.org/legal/resolved.html), so the file can't be in a source release under that licence. This takes the dataset from the copy scikit-learn distributes under the BSD 3-Clause License instead. The CSV keeps its columns, row order and species names, so the example workflow is unaffected. Only rows 35 and 38 change: they are the two known transcription errors in the UCI copy, which scikit-learn's copy corrects to Fisher's published values. The `LICENSE` entries (root and `bin/single-node/`) move to BSD 3-Clause, the compose bundle ships the BSD 3-Clause text instead of CC BY 4.0, the now-unused `licenses/LICENSE-CC-BY-4.0.txt` is removed, and the dataset description names the new source. This conflicts with apache#8997 in `LICENSE`, since both add the BSD 3-Clause section; whichever lands second merges the two entries. ### Any related issues, documentation, discussions? Follows up apache#8803. ### How was this PR tested? Checked that every row of the new `Iris.csv` matches scikit-learn 1.7.2's `iris.csv`. Ran the bundle's `git archive` export step against this commit to confirm it picks up the BSD 3-Clause text, and checked that the new description still makes valid JSON in `load-examples.sh`, which inserts it unescaped. ### Was this PR authored or co-authored using generative AI tooling? Generated-by: Claude Code (claude-opus-5-5)
|
/request-review @mengw15 Could you review the large binary hash routing? The regression and broader tests pass locally, and CI is green. |
### What changes were proposed in this PR? The Python GlobalPortIdentity decoder now rejects invalid boolean tokens instead of silently treating them as false. Valid mixed-case true and false values remain supported. ### Any related issues, documentation, discussions? Closes apache#8239 ### How was this PR tested? Retested with Python 3.12 on Windows in a fresh detached worktree from upstream main at `7426431337`, which includes the merged loop-completion change apache#8938. Regression before implementation: 2 failed, 48 passed. After implementation: 50 passed. Generate protobufs with `bash bin/python-proto-gen.sh`, then run from `amber`: ```text python -m pytest src/test/python/core/util/test_virtual_identity.py src/test/python/core/storage/test_vfs_uri_factory.py -q --tb=line -p no:cacheprovider python -m ruff check src/main/python src/test/python python -m ruff format --check src/main/python src/test/python ``` Ruff lint and formatting pass for all 217 Python files. ### Was this PR authored or co-authored using generative AI tooling? Generated-by: Codex
…rop a superseded file (apache#8932) ### What changes were proposed in this PR? The file preview on dataset and model detail pages subscribed to each file request without an error handler and never cancelled it. So: A failed download (storage unreachable, expired link, network error) left the preview on “File content is loading” forever. When a file was clicked before the previous one finished, the earlier file could arrive last and replace the newer one’s content under the newer file’s name. UserDatasetFileRendererComponent now keeps the current request and cancels it whenever a new file is loaded, and shows the existing “File loading encounter error” message when the request fails. Before: a failed download keeps loading, and a slow earlier file replaces the selected one: <img width="1440" height="900" alt="before-1-download-failed" src="https://github.com/user-attachments/assets/ca24ccb0-e721-48c1-b18d-23dffc1996dc" /> <img width="1440" height="900" alt="before-3-first-file-overwrites" src="https://github.com/user-attachments/assets/3522331f-1941-42ff-bc8a-11364342837c" /> After: the failed download shows the error, and the selected file stays: <img width="1440" height="900" alt="after-1-download-failed" src="https://github.com/user-attachments/assets/6e3b9ded-910d-4d13-ae12-879918f82a4a" /> <img width="1440" height="900" alt="after-2-second-file-kept" src="https://github.com/user-attachments/assets/782cf354-7963-4ebc-bdbb-4685aac03601" /> ### Any related issues, documentation, discussions? Closes apache#8930 ### How was this PR tested? Added two cases to user-dataset-file-renderer.component.spec.ts: a failed fetch shows the loading error, and a slow file is dropped once another file is selected. Both fail without the fix. cd frontend yarn ng test --watch=false --include='**/user-dataset-file-renderer.component.spec.ts' Tests 57 passed (57) Also checked against a local stack: with the object store stopped, clicking a file shows the error; and with one file’s request delayed, clicking it and then another file keeps the second file’s content. ### Was this PR authored or co-authored using generative AI tooling? Generated-by: Claude Code (Claude Opus 5.5) --------- Co-authored-by: Meng Wang <mengw15@uci.edu>
…olicy (apache#8973) ### What changes were proposed in this PR? The computing-unit prepull DaemonSet hardcoded imagePullPolicy: Always, so on clusters that load images into the nodes (kind, minikube, air-gapped) setting texeraImages.pullPolicy to IfNotPresent or Never had no effect on it. Its init container still tried to pull from the registry and failed. It now reads {{ .Values.texeraImages.pullPolicy }}, like the Jupyter prepull DaemonSet and every other template that pulls a Texera image. texeraImages.pullPolicy defaults to Always, so default installs render exactly as before. Rendered with helm template, before: ``` pullPolicy=Always | CU prepuller: Always | Jupyter prepuller: Always pullPolicy=IfNotPresent | CU prepuller: Always | Jupyter prepuller: IfNotPresent pullPolicy=Never | CU prepuller: Always | Jupyter prepuller: Never ``` After: ``` pullPolicy=Always | CU prepuller: Always | Jupyter prepuller: Always pullPolicy=IfNotPresent | CU prepuller: IfNotPresent | Jupyter prepuller: IfNotPresent pullPolicy=Never | CU prepuller: Never | Jupyter prepuller: Never ``` ### Any related issues, documentation, discussions? Closes apache#8972 ### How was this PR tested? Rendered the DaemonSet with helm template under each texeraImages.pullPolicy value, before and after (output above), and with the default values, which still give Always. bin/k8s/tests/test_helm_values.sh passes. ### Was this PR authored or co-authored using generative AI tooling? Generated-by: Claude Code (Claude Opus 5.5) Co-authored-by: Meng Wang <mengw15@uci.edu>
…ons in LICENSE (apache#8997) ### What changes were proposed in this PR? The notebook-migration diagrams in `frontend/src/assets/notebook_migration_tool/` bundle the Project Jupyter logo (`tool_popup_diagram.png`) and three Material Symbols icons (all three diagrams). `frontend/LICENSE-binary` already lists them, but the root `LICENSE`, which covers the source release, did not. This adds the Jupyter logo to the BSD 3-Clause section (the license of jupyter/design), with a trademark note like the ORCID entry's, and extends the existing Material Symbols entry to the diagrams. No images change. `release/v1.3` gets a separate version of this fix rather than a backport, because it still ships `jupyter-logo.svg` and has only one of the diagrams. ### Any related issues, documentation, discussions? Part of apache#8982 (the Jupyter item). ### How was this PR tested? License text only. The entries mirror the ones already in `frontend/LICENSE-binary`, and the jupyter/design license and copyright line were checked at the source. ### Was this PR authored or co-authored using generative AI tooling? Generated-by: Claude Code (claude-opus-5-5)
…ty .proto files in LICENSE (apache#9010) ### What changes were proposed in this PR? The frontend commits TypeScript that `bin/frontend-proto-gen.sh` generates from ScalaPB's `scalapb.proto` and, through it, Google's `descriptor.proto` (apache#8802). `descriptor.ts` carries about 850 lines of Google's BSD-3 documentation comments, but neither generated file was listed in `LICENSE`. This adds `descriptor.ts` under BSD 3-Clause with Google's copyright line, and lists `scalapb.ts` in the existing ScalaPB entry. Only `LICENSE` changes; the files themselves are untouched. ### Any related issues, documentation, discussions? Part of apache#8802. The same files are on `release/v1.3` and `release/v1.2`. ### How was this PR tested? License text only. The copyright line and license come from the header of `descriptor.proto` in protocolbuffers/protobuf. ### Was this PR authored or co-authored using generative AI tooling? Generated-by: Claude Code (claude-opus-5-5)
…nged something they show (apache#8845) ### What changes were proposed in this PR? Closes apache#8844. Part of the Form View feature (apache#8011); from the apache#8439 refinements. Found on the apache#8761 demo (apache#8843). A compilation result rebuilt every card on the Form View, including the compilation a card's own write triggers. Three things followed from that, all visible with a Projection's drag-reorder list (apache#8761) and with any tick box: the controls were redrawn under the reader's eyes after every click (the row buttons flicker); the keyboard focus went with the replaced node, so a keyboard reader landed on the body about a second after every Move up / Move down; and a click made in the last 150 ms before the rebuild was lost, since the rebuild ended that card's pending debounced write and re-seeded the card from the operator, which still held the previous state (the row "jumps back"). The canvas's property panel redraws only when an operator's schema changes. The form now does the same: - A compilation rebuilds the cards only when it changed something they show: a card's operator schema (the column enums compilation writes into it, which turn an attribute box into a dropdown), the set of inputs (an operator deleted on the canvas makes its card broken; a property exposed or removed), or an operator value a card does not hold (a co-editor's edit), including the operator's other properties, which a card is seeded with as the context a custom widget reads to decide what it shows (the HuggingFace picker reads `task`): nothing but a rebuild re-seeds those, so a sibling changed on the canvas or by a co-editor would have left the card showing the old one (Copilot). Every property an input is bound to is left out of that context, this card's own and any other card's on the same step, since each is compared against the card that shows it: counting them as context too would make one card's edit a change to every other card of that step, and a form with two inputs from one step would rebuild wholesale on every compilation its own typing triggers -- the churn this PR exists to stop (Copilot). The keys are compared sorted, so a rewrite that only reorders them is not a change, and a card's own edit, written back or still on its way, is not a reason: the two agree once it is written. The result picker and the shown results still follow the graph on every compilation. - Before any rebuild, from any source, a card's unwritten edit is written, so a rebuild can no longer lose one. - An empty string and an absent value count as the same value in the comparison (formly's blank default for a property the operator never had), so such a card is not rebuilt on every compilation. ### Any related issues, documentation, discussions? Closes apache#8844. The drag-reorder list apache#8843 (apache#8761) brings to the form is where this is plain to see: every drop writes and compiles, and the rows redraw about a second later; a second drop made just before that redraw is undone. The cause is the form's own compile handling, present since the cards were first built from the compiled schema; on main alone a tick box goes through the same redraw, focus drop and lost second click, which take a keyboard or a stopwatch to notice. The Before/After below is therefore recorded on top of apache#8843 (before: apache#8843 alone; after: apache#8843 plus this); this PR does not depend on apache#8843 and applies to main as is. Known limitation, unchanged: a card still shows a co-editor's edit of the same property only after the rebuild that edit's compilation triggers (tracked as a follow-up). ### How was this PR tested? Unit tests (vitest), the form's spec: a compilation that changes nothing a card shows leaves the cards alone (same card objects) while the result picker is still refreshed; a changed operator schema, an operator gone from the graph, an operator value changed under a card (a co-editor's edit), another property of a card's operator changed (the widget context), a changed set of inputs (one exposed; a shown one turned broken) each rebuild; the same properties in another order do not, nor does a change to the card's own property while its edit is still on its way, nor one card's edit when two inputs come from the same step (both card objects survive it); an author's broken card is left alone; the card's own edit does not rebuild while pending nor once written; formly's blank and an absent value count as the same; an unwritten edit is written, once, before a rebuild from any source replaces the card; a read-only viewer's card has no write to flush; the typing hold still holds a needed rebuild until the focus leaves. Each guard was deletion-checked (every compilation rebuilding; the schema check, the context check, the exclusion of every bound property from it, that the exclusion covers the other cards of the step and not only this one, the context's key sort, the pending check, the broken-set check, the blank normalisation, the pre-rebuild flush, the pending mark, the pending reset and the result-picker refresh each removed; a broken card checked against a schema) and turned a named test red. eslint, prettier and the production (AOT) build pass; the full frontend suite passes; every statement, function and branch this PR adds is covered. Checked on a flag-on instance (main-demo; before = main, and main + apache#8843; after = the same plus this), a Projection's columns and its Drop Option exposed on the form. The tick box on main: 0.3 s after a tick the box still has the focus; 2.8 s later it is a new DOM node and the focus is on the body; two ticks 700 ms apart end in the state after the first (the second undone). With this change the box is the same node three seconds later, still focused, and both ticks land. The drag-reorder rows on main + apache#8843: after a drop the rows are replaced about a second later; with this change they are the same nodes, and the order still reaches a canvas tab open beside the form within a second, a drop made on the canvas panel still reaches the form (a value the card does not hold rebuilds it), and the saved workflow carries the order. #### Video **Before** https://github.com/user-attachments/assets/eac466c3-c0c9-4969-b39a-a6da41ec54ff **After** https://github.com/user-attachments/assets/3ecd6342-7d6b-405c-bd83-f45415c2bcba ### Was this PR authored or co-authored using generative AI tooling? Yes. Generated-by: Claude Code (Claude Fable 5.1, Anthropic). Co-authored with Claude, reviewed line by line by the author before submission. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
…not only the pointer (apache#9016) ### What changes were proposed in this PR? Closes apache#8943. Part of the Form View feature (apache#8011); from the apache#8439 refinements (item 5). A read-only input card -- what a viewer without write access sees -- is locked with `pointer-events: none`. That is hit testing only. The bound formly controls are disabled through `props.disabled`, but the controls a custom widget draws of its own are not: the HuggingFace audio and image uploaders each render a plain file input that nothing disables. A reader could Tab into one inside a locked card, open it with Enter and choose a file. For the audio input that is a real write. The widget POSTs the chosen file to `/api/huggingface/upload-audio`, which authorises any signed-in user and never asks who may write this workflow, so the file lands in the server's temp store. Checked on a workflow shared read-only: two presses of Tab reach the uploader inside the locked card, Enter opens the file dialog, and the POST comes back 200 with the stored path. The image uploader is client-side, so there the reader only makes the card display a picture of their choosing -- a read-only card wires no write-back and a reader's save is refused, so the operator keeps the author's value and a run still runs it. The card now also keeps the keyboard out, through a small directive on it (`texeraReadOnlyCard`, applied as `[texeraReadOnlyCard]="!canEdit"` beside the existing `read-only` class): - Every focusable descendant is taken out of the tab order (`tabindex="-1"`, its own value remembered) and marked `aria-disabled="true"`, so there is nothing for Tab to reach and assistive tech says why rather than going quiet. - Every control the browser will refuse outright -- button, input, select, textarea -- is also disabled natively, its previous state remembered. Out of the tab order is not out of reach: `tabindex="-1"` ends only sequential navigation and `aria-disabled` only announces, so a reader's assistive tech could still focus a widget's file input and activate it, which for the audio one posts the file (Copilot). - A card that becomes editable gets its controls back, each with the tabindex and the disabled state it had, and only those this directive took. - A control that leaves the card is let go of on the next pass: a widget redraws its own controls while the card lives on, so a set that only grew held every detached node for as long as the reader stayed on the page (Copilot). - Widgets render their own controls after the card is built and redraw them as they go, so the locking is re-applied on every change inside the card: a control added, one whose own tabindex is written back (ng-zorro writes one when it enables a control), and one a widget enables again (the audio uploader's `[disabled]="isUploading"`). The observer runs outside Angular and sets only what is not already set, so one pass settles it. `inert` is what the step panel uses for its read-only mount, and the issue suggested following it; this does not, deliberately. `inert` also removes the subtree from the accessibility tree, and a reader's card exists to be read -- the values are what a reader runs the workflow with -- so that would trade this bug for a worse one. Disabled controls stay in the accessibility tree and keep being announced. The directive's doc comment says so, next to the code. Nothing else changes: the pointer lock, the styles, the card's content and the author's editing path are untouched, and the directive does nothing at all while a card is editable. ### Any related issues, documentation, discussions? Closes apache#8943, which re-files apache#8758 (closed). Part of apache#8439 (item 5) and the Form View feature apache#8011. Raised by Copilot on apache#8437, apache#8438 and apache#8440. Three neighbouring things are deliberately left alone. The widgets' own controls still do not consult the field's disabled state in their own handlers -- fixing that is per-widget work (the HuggingFace uploaders, the dataset picker, the resource value selector), and the card-level lock covers every widget at once, including ones added later. The upload endpoint itself authorises on being signed in and nothing else (`@RolesAllowed("REGULAR","ADMIN")`, no workflow-access check), so it would still accept a file posted by hand; closing the UI route does not close that one, and it is worth its own issue. And the step panel's `inert` mount has the same accessibility-tree problem described above; changing it is not this issue's scope, and it is worth its own look. ### How was this PR tested? Unit tests (vitest). The directive's own spec, on a host shaped like a card (a bound input, a widget's Browse button, a link, a span, a control with its own `tabindex`): every focusable control in a read-only card is out of the tab order; each is marked `aria-disabled` while the card is not inert and its text is still there; an editable card is left alone, keeping a control's own `tabindex="3"`; a card that becomes editable gets that `3` back, the untouched control gets no `tabindex`, and the `aria-disabled` marks go; a control a widget adds after the card was built is locked; a control whose widget writes its `tabindex` back, or enables again, is locked again; a click on a locked control dispatches no activation and the controls report disabled (jsdom does not model a disabled control refusing focus, so that half is asserted through the property the browser acts on); the disabled state is given back on unlock; five rounds of a control being added and removed leave the tracked set where it started, rather than holding the detached nodes; the observer is disconnected when the card goes away. The page's rendered spec wires it through the real template: a read-only viewer's card, with a button appended the way a widget renders one, has it out of the tab order and marked, and the card is not inert. By hand, on two dev builds of the same base commit, one with this change and one without, signed in as a second account the workflow is shared read-only with. Before: from the view toggle, two presses of Tab land on the uploader inside the locked card, Enter opens the file dialog, and choosing a file POSTs it (200). After: the same two presses land on Run, the card is skipped, and no request goes out. The mouse reaches nothing in either build, and the stored workflow is unchanged in both. Each guard was deletion-checked and turned a named test red (the directive not applied; the tabindex write; the aria-disabled write; the native disable; the editable check; the unlock; the original-tabindex restore; the original-disabled restore; the release of what has left the card; the childList and both attribute halves of the observer; the disconnect). eslint, prettier and the production (AOT) build pass; every statement, function and branch this PR adds is covered, and the full frontend suite passes. #### Video **Before** https://github.com/user-attachments/assets/cd1b58ff-6cc4-4958-ad78-dd00bb86f14e **After** https://github.com/user-attachments/assets/8f524126-d370-48f3-bc70-68497791cf5f ### Was this PR authored or co-authored using generative AI tooling? Yes. Generated-by: Claude Code (Anthropic). Co-authored with Claude, reviewed line by line by the author before submission. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
…#9020) ### What changes were proposed in this PR? `bin/frontend-proto-gen.sh` runs `protoc` on `workflow.proto` and `virtualidentity.proto`, but ts-proto also writes TypeScript for their transitive imports. Those imports are used only for ScalaPB options (`scalapb.options`, `scalapb.field`), which shape the Scala output and produce no TypeScript types. As a result, two files nothing uses were generated and committed: | File | Lines | Imported by | | --- | --- | --- | | `proto/google/protobuf/descriptor.ts` | 6824 | `scalapb.ts` only | | `proto/scalapb/scalapb.ts` | 2394 | nothing | Changes: | File | Change | | --- | --- | | `bin/frontend-proto-gen.sh` | Removes `proto/scalapb` and `proto/google` after `protoc` runs, so the files don't come back on the next regeneration | | `frontend/src/app/common/type/proto/{google,scalapb}/` | Deleted | | `LICENSE` | Removes the `descriptor.ts` entry and the `scalapb.ts` line. The `scalapb.proto` entry stays because that file is still in the repo | | `.licenserc.yaml` | Removes the license-check exclusions for the two deleted files | ``` Before: protoc -> workflow.ts, virtualidentity.ts, scalapb.ts, descriptor.ts (committed, unused) After: protoc -> workflow.ts, virtualidentity.ts ``` User-facing behavior is unchanged. ### Any related issues, documentation, discussions? Closes apache#9012 Follows apache#9010, which added the `LICENSE` entries for these generated files. ### How was this PR tested? - `bash bin/frontend-proto-gen.sh`: the output folder contains only `org/apache/texera/amber/core/{virtualidentity,workflow}.ts` - `cd frontend && yarn build`: succeeds - `cd frontend && yarn test`: 237 test files passed; 6649 tests passed, 1 skipped No tests added: this removes dead generated code and nothing imports it. ### Was this PR authored or co-authored using generative AI tooling? Co-authored by Claude-Code (helped with file and code deletion, navigating repo, writing this PR description, and tests)
|
/request-review @sshiv012 @parshimers |
### What changes were proposed in this PR? Removes two selectors from the global stylesheet's Python-environment modal (`.pve-modal`) block that match no element. **+1/−8 lines.** There is no behaviour change. - **The `.pve-modal .system-header .subtitle` rule.** The only `.system-header` element (in the computing-unit selection modal) contains just a `.title`. No template, TS code or ng-zorro component produces a bare `subtitle` class. - **The bare `.package-inputs` token in `.package-header-row, .package-inputs`.** The rule and `.package-header-row` stay. The templates use `system-package-inputs` and `user-package-inputs`, and CSS matches whole class tokens, so neither matches `.package-inputs`. Because these are global styles, the check covered every template and TS file in the app, plus ng-zorro's compiled output. ### History | | | | --- | --- | | **Introduced by** | apache#4484 (2026-05-01), "feat: Add Python Virtual Environment Support: Creating a Virtual Environment", which added the whole `.pve-modal` block | | **Usage removed by** | apache#4902 (2026-05-12), "Installing User Defined Packages", renamed the element to `system-package-inputs`, which left `.package-inputs` unmatched. `.subtitle` was **never used** | `.package-inputs` has been dead for nearly five months. ### Any related issues, documentation, discussions? Closes apache#8925 ### How was this PR tested? No new tests; no spec referenced either selector. From `frontend/`: - `npx ng test --watch=false --include='**/user-venv.component.spec.ts' --include='**/computing-unit-selection.component.spec.ts'`: 2 files, 242 tests, all pass. These are the only specs that render the modal. - `yarn format:ci`: clean. - `npx ng build`: success. ### Was this PR authored or co-authored using generative AI tooling? Generated-by: Claude Code (Claude Opus 5.5) 🤖 Generated with [Claude Code](https://claude.com/claude-code)
### What changes were proposed in this PR? If this limit is too low, the merge queue can enter a starvation loop where every job times out if runners are simply busy. Raising the limit stops this. ### Any related issues, documentation, discussions? Closes apache#9095 and https://issues.apache.org/jira/browse/INFRA-28569 ### How was this PR tested? It wasn't; it's specific to ASF infra. I got the idea from a helpful hint from Andrew Lamb of DataFusion. ### Was this PR authored or co-authored using generative AI tooling? No
### What changes were proposed in this PR?
Nothing can merge into `main` right now. Three CI faults block it, and
each fix needs the others to land first.
```
Before: Scala job -> sbt/setup-sbt v1.5.7 -> nested carabiner action not allowed -> fails at Set up job
frontend job -> ubuntu-26.04 runner -> Playwright 1.59.1 has no Chromium -> fails at install
merge group -> no runner within 45 min -> checks_timed_out, PR leaves the queue
After: Scala job -> sbt/setup-sbt v1.5.12 -> every nested action allowed -> runs
frontend job -> ubuntu-26.04 runner -> Playwright 1.64.1 installs Chromium -> runs
merge group -> waits up to 360 min for runners -> merges
```
- **setup-sbt.** The ASF actions allowlist dropped the nested
`carabiner-dev/actions/install/*` refs that `sbt/setup-sbt` v1.5.7
reaches, so every job that sets up sbt (`amber`, `amber-integration`,
`platform`, `platform-integration`, `Bench`) has died at *Set up job*
since 2026-10-19. This moves all 9 call sites to v1.5.12, whose whole
chain is allowed. The action's inputs did not change.
- **Playwright.** `ubuntu-latest` now resolves to the Ubuntu 26.04
image, where Playwright 1.59.1 refuses to install Chromium ("Playwright
does not support chromium on ubuntu26.04-x64"), so the ubuntu frontend
leg fails before any test runs. This bumps `playwright` to 1.64.1, which
supports 26.04.
- **Merge queue timeout.** The queue ejects an entry whose required
checks have not reported within `check_response_timeout_minutes`, which
is 45. ASF's shared runners are backed up well past that: in the last
merge group, *Validate PR title*, a 2-second job, waited 110 minutes for
a runner. This raises the limit to 360 minutes, as DataFusion did in
apache/datafusion#26293.
`Required Checks` stays red without both version bumps, and no PR gets
through the queue without the higher limit, so all three go in one PR.
### Any related issues, documentation, discussions?
Closes apache#9095.
### How was this PR tested?
Every changed file parses:
```
python -I -c "import sys, yaml; [yaml.safe_load(open(f)) for f in sys.argv[1:]]" .asf.yaml .github/workflows/benchmarks.yml .github/workflows/build-and-push-images.yml .github/workflows/build.yml .github/workflows/dependency-graph.yml
```
Walking the `uses:` chain under `sbt/setup-sbt@ecad189` (v1.5.12)
reaches `ampel/verify@32587e8`, `install/ampel@d6d91c5`,
`install/download-and-verify@2fec8bd` and
`install/ampel-bootstrap@16009dc`, and all four are in
`apache/infrastructure-actions`' `approved_patterns.yml` as of
2026-10-23. Under v1.5.7, `install/ampel@2fec8bd`,
`install/download-and-verify@16009dc` and
`install/ampel-bootstrap@619a474` are not.
The rest is CI. The labeler applies `ci` for `.github/**`, which runs
every stack that sets up sbt, the frontend legs, and `Bench`. On this
PR's previous head every job passed except the ubuntu frontend leg,
which landed on ubuntu-26.04 and failed at the Playwright install. The
new timeout only shows once this is merged.
### Was this PR authored or co-authored using generative AI tooling?
Generated-by: Claude Code (Claude Opus 5.5)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Ian Maxon <ian@maxons.email>
…9070) ### What changes were proposed in this PR? Removes dead code from `UserDatasetVersionCreatorComponent`. **+3/−19 lines.** There is no behaviour change. - **`isCreateButtonDisabled`:** nothing ever writes it, so it is always `false`. The create button's `[disabled]="isCreateButtonDisabled || isCreating"` becomes `[disabled]="isCreating"`, which evaluates identically. - **The `formBuilder` injection:** nothing reads it. `FormBuilder` is provided in root, so dropping the parameter (and its import) changes nothing. - **`.file-uploader` and `.toggle-item .help-text`:** the component uses emulated encapsulation and no element in its template has either class. The `files-uploader` child renders its own `.file-uploader`, which this stylesheet can't reach. ### History | | | | --- | --- | | **Introduced by** | apache#2413 (2024-02-27), "Introduce Dataset GUI": `isCreateButtonDisabled`, `formBuilder` and `.file-uploader`. apache#3663 (2025-08-17), "feat: adding option to allow owner to disallow downloading datasets": `.help-text` | | **Usage removed by** | apache#3296 (2025-03-11), "Add FileService as a standalone microservice, LakeFS+S3 as dataset storage", removed the `<div class="file-uploader">` wrapper. `isCreateButtonDisabled`, `formBuilder` and `.help-text` were **never used** | `isCreateButtonDisabled` and `formBuilder` have been unused for the two and a half years since they were added. ### Any related issues, documentation, discussions? Closes apache#9067 ### How was this PR tested? No new tests. The component spec's create-button cases still cover the `[disabled]` binding through `isCreating`. From `frontend/`: - `npx ng test --watch=false --include='**/user-dataset-version-creator.component.spec.ts' --include='**/user-dataset.component.spec.ts' --include='**/result-exportation.component.spec.ts'`: 3 files, 105 tests, all pass. The last two specs cover the component's two modal hosts. - `yarn format:ci`: clean. - `npx ng build`: success. ### Was this PR authored or co-authored using generative AI tooling? Generated-by: Claude Code (Claude Opus 5.5) 🤖 Generated with [Claude Code](https://claude.com/claude-code)
### What changes were proposed in this PR? Removes three rules from the hub landing page's stylesheet that style nothing: `.search-bar`, `.section-intro-img` and `.browse-section`. **−15 lines.** There is no behaviour change. The component uses emulated encapsulation, so these rules can only match its own template. That template uses only `landing-page-container`, `section-intro` and `section-intro-text`, and has no class bindings or projected content. The browse sections are `<texera-browse-section>` elements, which the `.browse-section` class selector doesn't match. The rules for the intro block and its text stay. ### History | | | | --- | --- | | **Introduced by** | apache#2928 (2024-10-29), "Add landing page", with all three rules | | **Usage removed by** | apache#4134 (2026-01-14), "fix: restore proper license headers for third-party code", removed the `<img class="section-intro-img">` hub icon. `.search-bar` and `.browse-section` were **never used**: no version of the template has had either class | `.search-bar` and `.browse-section` have never applied in the two years since they were added; `.section-intro-img` has been dead for nine months. ### Any related issues, documentation, discussions? Closes apache#9066 ### How was this PR tested? No new tests; no spec referenced these classes. From `frontend/`: - `npx ng test --watch=false --include='**/landing-page.component.spec.ts'`: 17 tests, all pass. No other spec renders the component. - `yarn format:ci`: clean. - `npx ng build`: success. ### Was this PR authored or co-authored using generative AI tooling? Generated-by: Claude Code (Claude Opus 5.5) 🤖 Generated with [Claude Code](https://claude.com/claude-code)
…#9179) ### What changes were proposed in this PR? Removes unused configuration and enum definitions in `pyright-language-service`: 1. `config.json:2`: Dead property `"languageServerDir": "../node_modules/pyright/dist"`. `main.ts:34` defines the relative server runner path directly (`./node_modules/pyright/dist/pyright-langserver.js`) and parses `config.json` only for `clientPathName`. 2. `server-commons.ts:20`: Unused enum variant `LanguageName.java`. The pyright language service exclusively launches the Python language server via `LanguageName.node`. **+1/-4 lines.** Pure deletion with no behaviour change. ### Any related issues, documentation, discussions? Closes apache#9178. ### How was this PR tested? - Verified 0 callers repo-wide: `git grep -nw "languageServerDir"` (1 hit, now 0) `git grep -nw "LanguageName.java"` (0 hits) - Valid JSON verified for `config.json`. ### Was this PR authored or co-authored using generative AI tooling? Generated-by: Antigravity (Claude Opus 5.5)
### What changes were proposed in this PR? Removes dead members in user authentication services: 1. `AuthService.REFRESH_TOKEN` (`auth.service.ts:59`): Unreferenced static endpoint constant with 0 callers across production and test code. 2. `StubAuthService.validateUsername` (`stub-auth.service.ts:114-116`): Dead test double method (actual username validation is a static utility on `UserService`, not `AuthService`). **+0/-5 lines.** Pure deletion with no behaviour change. ### Any related issues, documentation, discussions? Closes apache#9176. ### How was this PR tested? - Prettier check passes: `npx prettier --check src/app/common/service/user/auth.service.ts src/app/common/service/user/stub-auth.service.ts` - Verified 0 callers repo-wide: `git grep -nw "REFRESH_TOKEN"` `git grep -nw "validateUsername"` (only active static calls on `UserService`) ### Was this PR authored or co-authored using generative AI tooling? Generated-by: Antigravity (Claude Opus 5.5)
### What changes were proposed in this PR? Removes the uncalled helper function `is_subsection_header` (`bin/licensing/concat_license_binary.py:110-115`). Subsection matching was inlined directly into `parse()` (lines 177-182), leaving the separate definition with 0 callers across the repository. **+0/-8 lines.** Pure deletion with no behaviour change. ### Any related issues, documentation, discussions? Closes apache#9182. ### How was this PR tested? - `python -m py_compile bin/licensing/concat_license_binary.py` passed with 0 errors. - `python -m pytest bin/licensing` passed (53 passed in 0.52s). - Verified 0 callers repo-wide: `git grep -nw "is_subsection_header"` (1 hit, now 0) ### Was this PR authored or co-authored using generative AI tooling? Generated-by: Antigravity (Claude Opus 5.5)
…pache#8576) ### What changes were proposed in this PR? A listing is where most people meet a workflow, so it has to agree with what opening it shows. This makes search and the hub match, display and link against the copy on show. - **Search matches the copy the caller may see.** One search returns both the caller's own workflows and public ones, so the filter is a disjunction of guarded filters — the working copy for rows they were granted, the frozen copy for rows they reach only because those are public. Written over bare columns rather than a `CASE`, so each side stays eligible for its own PGroonga index. A pinned workflow no longer turns up on keywords that exist only behind the pin, and the author still finds their own work on what they just typed. - **Listings show the frozen name and description** to a viewer without granted access — the same copy the detail page serves, so a card cannot advertise a title that opening it does not show. Both are NULL while following, which leaves the live values in place. - **The hub is the public shelf**, so everything on it is listed as the public sees it, for the author too: they are looking at the shelf, not at their own dashboard. - **One definition of "the public is behind".** `WorkflowPublishService.pinDiffersFromWorkingCopy` is the share dialog's comparison as a SQL condition, and the search projection and the hub listing both use it, so a card and the dialog cannot disagree about whether edits are held back. ### Any related issues, documentation, discussions? Closes apache#7940 Part of apache#7828. Design discussion: apache#7128. Builds on apache#7853 and apache#8575, both merged. ### How was this PR tested? 19 new cases in `WorkflowPublishSpec` plus `WorkflowSearchQueryBuilderSpec` and `UnifiedResourceSchemaSpec` (567 in the dashboard package): - search not matching a public workflow on anything that exists only in unpublished edits, and matching it on its published copy — content, name and description, each separately; - an unpinned public workflow still matching the author's latest, and the author still matching their own workflow on a name only they can see; - a listing showing a public viewer the published name and description, a collaborator the live ones, and a private workflow's own listing untouched; - the drift flag a card carries: true while a pin holds edits back, false for a workflow with nothing frozen, and equal to what the share dialog reports for the same workflow — including after a rename and after a change of view, the two fields most easily left out of one of the three places that answer this. The shared condition was checked by mutation: dropping the default-view term from it turns the card-versus-dialog case red. `scalafmtCheckAll` clean. ### Was this PR authored or co-authored using generative AI tooling? Generated-by: Claude Code (Opus 5) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
### What changes were proposed in this PR?
Removes unused `WorkflowActionService` injection from
`DatasetFileSelectorComponent`:
1. `dataset-file-selector.component.ts:52`: Constructor parameter
`public workflowActionService: WorkflowActionService` is never read in
the component, its template, or any caller.
2. `dataset-file-selector.component.spec.ts:57`: Corresponding mock
provider `{ provide: WorkflowActionService, useValue: {} }` and unused
import removed.
**+0/-4 lines.** Pure deletion with no behaviour change.
### Any related issues, documentation, discussions?
Closes apache#9184.
### How was this PR tested?
- Prettier check passes: `npx prettier --check
src/app/workspace/component/dataset-file-selector/dataset-file-selector.component.ts
src/app/workspace/component/dataset-file-selector/dataset-file-selector.component.spec.ts`
- TypeScript spec compilation: `npx tsc --noEmit -p
src/tsconfig.spec.json` (no errors in modified files)
- Verified 0 callers repo-wide: `git grep -nw "workflowActionService" --
frontend/src/app/workspace/component/dataset-file-selector/`
### Was this PR authored or co-authored using generative AI tooling?
Generated-by: Antigravity (Claude Opus 5.5)
…#9187) ### What changes were proposed in this PR? Removes the uncalled helper function `state_cell` (`bin/local-dev/tui.py:929-931`). Status cell styling was inlined in `_tick_state` (line 1164), leaving the separate definition with 0 callers across the repository. **+0/-5 lines.** Pure deletion with no behaviour change. ### Any related issues, documentation, discussions? Closes apache#9186. ### How was this PR tested? - `python -m py_compile bin/local-dev/tui.py` passed with 0 errors. - Verified 0 callers repo-wide: `git grep -nw "state_cell"` (1 hit, now 0) ### Was this PR authored or co-authored using generative AI tooling? Generated-by: Antigravity (Claude Opus 5.5)
…c icons (apache#8999) ### What changes were proposed in this PR? Per apache#8982, thirteen operator icons under `frontend/src/assets/operator_images/` were other organisations' logos (Twitter, Reddit, PostgreSQL, MySQL, Hugging Face, the Python logo), a photo of an iris, or stock-looking artwork, with no recorded source or licence. None of them has a licence that lets an Apache source release redistribute it, so this replaces them with project-made icons. The new icons follow the UDF icons from apache#5686: a large hero word with an optional gray descriptor on a 1024×1024 transparent canvas, so they match `Py`, `R` and `Java` on the canvas. They were drawn with Pillow, and the text uses Aileron Regular (CC0), the font bundled with Pillow, so no `LICENSE` entry is needed. File names are unchanged, so the `assets/operator_images/<operatorType>.png` lookup still finds them. `JavaUDF.png` on `main` is already the project-made icon from apache#5686, so it isn't touched. On `release/v1.2` it is still the Java logo, because apache#5686 wasn't backported, and that branch has no `HuggingFace.png`, so the v1.2 backport needs both adjusted. ### Any related issues, documentation, discussions? Part of apache#8982; its Jupyter item is apache#8997 and apache#8998. Part of apache#8800. ### How was this PR tested? Asset swap only, with no code change. Previewed the icons at the 35 px size the workflow canvas draws them at, and checked that the commit applies cleanly to `release/v1.3`. ### Was this PR authored or co-authored using generative AI tooling? Generated-by: Claude Code (claude-opus-5-5)
### What changes were proposed in this PR?
Removes unused Java members in `common/workflow-core`:
1. `ExecutionMode.fromString` (`ExecutionMode.java:26`): Redundant
wrapper `public static ExecutionMode fromString(String value) { return
valueOf(value); }` with 0 callers across the repository (all callers use
standard `ExecutionMode.valueOf` or direct enum constants).
2. `LargeBinary.java:25`: Unused import `import
org.apache.texera.amber.core.executor.OperatorExecutor;` with 0
references in the file.
**+0/-3 lines.** Pure deletion with no behaviour change.
### Any related issues, documentation, discussions?
Closes apache#9180.
### How was this PR tested?
- Clean Java compile: `javac ExecutionMode.java`
- Verified 0 callers repo-wide:
`git grep -nw "ExecutionMode.fromString"` (1 hit, now 0)
`git grep -nw "OperatorExecutor"` in `LargeBinary.java` (1 hit, now 0)
### Was this PR authored or co-authored using generative AI tooling?
Generated-by: Antigravity (Claude Opus 5.5)
### What changes were proposed in this PR? Removes the unused `@value.setter` on `AtomicInteger` in `amber/src/main/python/core/util/atomic.py:48-52`. Callers across the engine mutate the atomic value strictly via atomic methods (`inc`, `dec`, `get_and_inc`, `get_and_dec`, `get_and_set`) and read via the property getter (`.value`), leaving the setter unused. The corresponding unit test in `test_atomic.py` is updated to verify `value` is a read-only property (`AttributeError` on assignment). **+3/-11 lines.** Pure deletion of dead setter and regression test update. ### Any related issues, documentation, discussions? Closes apache#9188. ### How was this PR tested? - `python -m py_compile amber/src/main/python/core/util/atomic.py` - `python -m pytest amber/src/test/python/core/util/test_atomic.py` (11 passed) - Verified 0 callers repo-wide: `git grep -nw "AtomicInteger" | grep -v test` shows only `.inc()`, `.dec()`, `.get_and_inc()`, `.get_and_dec()`, `.get_and_set()`, `.value` (getter). ### Was this PR authored or co-authored using generative AI tooling? Generated-by: Antigravity (Claude Opus 5.5)
…indow (apache#9056) ### What changes were proposed in this PR? The result panel's default height went from 300 to 500, but its stylesheet still placed it 300px above the bottom of the workspace, so a panel opened or docked at the default height left its bottom 200px below the window, usually the pager with them. The panel's offset now comes from the same constant as its default height, so the two cannot drift apart again. | Before | After | |---|---| | <img width="1400" height="843" alt="result-panel-docked-below-window" src="https://github.com/user-attachments/assets/2f0db118-f19b-40b6-b368-3bb97406cbca" /> | <img width="1400" height="843" alt="result-panel-docked-after-fix" src="https://github.com/user-attachments/assets/98b17370-9a5f-4e58-b4f1-e8dd08f41d64" /> | ### Any related issues, documentation, discussions? Closes apache#9055. Part of apache#9052. ### How was this PR tested? A new case in `ResultPanelComponent`'s spec checks that the panel is placed one default height above the workspace's bottom edge. It fails on main. In the running app, the docked panel now ends at the window's bottom edge, where on main it ran 200px past it. ### Was this PR authored or co-authored using generative AI tooling? Generated-by: Claude Code (Claude Opus 5.5) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: Xinyuan Lin <xinyual3@uci.edu>
### What changes were proposed in this PR? Removes dead members and unused service injections from `WorkflowExecutionHistoryComponent` and its test suite: 1. `workflow-execution-history.component.ts`: - Drops unused `WorkflowActionService` constructor injection and import. - Drops `currentlyHoveredExecution` field which is never set (its hover handlers were dropped previously). 2. `workflow-execution-history.component.html`: - Simplifies the bookmark star icon's `[nzTheme]` condition to `row.bookmarked ? 'fill' : 'outline'`. 3. `workflow-execution-history.component.spec.ts`: - Drops `OperatorMetadataService` and `StubOperatorMetadataService` imports and provider, which were only needed to instantiate the unused `WorkflowActionService`. **+1/-9 lines.** Pure cleanup with no behavior change. ### Any related issues, documentation, discussions? Closes apache#9193. ### How was this PR tested? - Prettier check passed: `npx prettier --check src/app/dashboard/component/user/user-workflow/ngbd-modal-workflow-executions/workflow-execution-history.component.ts src/app/dashboard/component/user/user-workflow/ngbd-modal-workflow-executions/workflow-execution-history.component.html src/app/dashboard/component/user/user-workflow/ngbd-modal-workflow-executions/workflow-execution-history.component.spec.ts` - TypeScript compilation check (`src/tsconfig.spec.json`): zero errors in modified files. - Verified 0 callers repo-wide for `currentlyHoveredExecution`. ### Was this PR authored or co-authored using generative AI tooling? Generated-by: Antigravity (Claude Opus 5.5)
…ache#8637) ### What changes were proposed in this PR? Adds an **AI Fix** tab to the result panel. When a Python UDF operator fails, the user clicks **Analyze with AI**; the tab sends the error, the operator's code, its input schemas and its configuration to an LLM through the existing LiteLLM proxy (`/api/chat/completions`), and shows the proposed fix as a diff with a confidence badge. **Apply and re-run** patches the operator through `setOperatorProperty` (so it is undoable) and re-executes the workflow; **Discard** drops it. It handles three error shapes and says so plainly for anything else ("This error type is not yet supported for automatic fixing."): | Error | Fix the model is asked for | | --- | --- | | `KeyError: 'col'` | closest column name from the input schema | | `TypeError: unsupported operand` | an explicit cast | | `ValueError: ... NaN` | `.dropna()` or a null guard | Python UDFs only, and one kind of fix: a change to `code`. An operator without code would cost a model call to reach a refusal, so the tab is not offered there — a JVM operator raising `NullPointerException` classifies, but has nothing Apply could patch. A configuration fix is not offered either: nothing in the repo raises an error one could repair, since the HuggingFace operator retries a 404 as a chat completion and writes "All inference providers failed" into its result rows rather than raising. Classification reads the exception **header**, which both sources already separate from the stack: `mkConsoleMessage` puts `err.toString` in `title`, the Python worker puts `format_exception[-1]` there, and a fatal error carries it in `message` with the frames in `details`. Nothing has to find the exception inside the joined text, which also means a chained traceback arrives already reduced to the one that stopped the worker. **What leaves the browser.** The error text, the operator's code and every input port's schema. Not the operator's configuration: no fix this panel writes reads it, and filtering it could never be made safe. `withoutSecrets` matched top-level field names, but a Python UDF's `uiParameters` is a list of attribute/value pairs, so the name says nothing about whether a value is an API key the user typed in — and the list went into the prompt whole. The block is gone rather than filtered harder, which takes the two sanitisers, the operator's JSON schema lookup and the `OperatorMetadataService` dependency with it. The model the panel asks for is the alias the deployment's LiteLLM proxy publishes, read from `GuiConfig` (`gui.workflow-workspace.ai-fix-model`, overridable by `GUI_WORKFLOW_WORKSPACE_AI_FIX_MODEL`), so a proxy serving a different alias does not need a rebuild to be reachable. **When the tab appears.** A Python UDF exception never becomes a `WorkflowFatalError`: the worker pauses and the traceback arrives as an ERROR `ConsoleMessage` while the execution stays `Running`. The tab is driven by the console stream for that reason, with its own subscription that adds or removes only that entry — a full panel rerender on every console update would reset the Console frame's filter, scroll and debug input and the Result table whenever any operator printed. That decision is made against the frame map itself rather than anything remembered between emissions, because `rerenderResultPanel` writes to the same map: a remembered key went stale the moment the rerender dropped the tab, and the next traceback was then read as "no change". The frame tabs are keyed by their config object, since `keyvalue` hands `*ngFor` a fresh pair per entry and `NgComponentOutlet` only recreates a component when its type changes. It tears itself down when the operator stops reporting an error, and the whole panel resets when a run ends — or, since a UDF that raises leaves the run `Running` and never reaches a terminal state, when a newer error arrives on the same operator. **What Apply guarantees.** - The operator is re-read from the graph first, and the write is refused if the code has moved on since the suggestion was generated. - A suggestion that cannot be applied never reaches the screen. Refused at the analysis, not at the click: a snippet the model invented (zero matches), one quoted from the middle of a line, one that begins a line but stops inside a longer one, and any reply that is not a code change. A quote may include its line's trailing newline or not — one is dropped from each snippet, so the verdict does not depend on where in the file the line sits. - Every occurrence of the snippet is replaced, since a re-run would otherwise fail again on the second one; the panel says how many places that is when it is more than one, and Apply refuses if the count has changed since — an edit in between would otherwise touch a different number of lines than the panel promised. - No indentation is inferred. The prompt requires whole lines carrying the indentation they should have, and a reply that does not is refused, so the replacement is a replacement and nothing has to guess which convention the model used. - The modification lock is cleared first. The traceback arrives while the execution is still `Running`, and Texera locks workflow modification for as long as a run is live, so the panel kills the paused execution — which also releases the computing unit it still held. It refuses instead of killing when a live run is not what holds the lock: a read-only workflow locks through a path `enableWorkflowModification()` cannot reopen, and running only needs write access to the computing unit, so a read-only user can reach a paused run. Every other refusal is checked before that kill as well as after it, so a fix that was never going to be written does not cost the user their run. - It asks `ExecuteWorkflowService` whether the re-run request was sent rather than predicting it, so it never reports "re-running" over a toast saying the run was refused. A deployment can still reject the request after it leaves the browser; that arrives on the execution state stream. - A refused write is reported with its real reason and keeps the suggestion on screen, instead of being reported as a failed analysis. Gated on `copilotEnabled`, the flag the LiteLLM proxy already checks. The model is called only on an explicit click, never on render. ### Screenshots Recorded on Chrome at a 1536x639 viewport, against the current code. The workflow is `TextInput` → Python UDF → `Filter` → `Sort`; the UDF reads `tuple_["lines"]` while `TextInput` emits `line`. The JSON is in the reproduction comment below. <img width="1536" height="639" alt="ai-fix-demo" src="https://github.com/user-attachments/assets/13df908c-3620-4429-a90c-dc09a07101ad" /> The recording runs the whole loop, untouched: **Run** starts the workflow, the traceback arrives while the execution is still `Running`, and the **AI Fix** tab appears beside **Console** on its own — the operator is already selected, so nothing but the console stream puts it there. **Analyze** returns the root cause and a diff with a confidence badge, quoting the whole line with its indentation. **Apply and re-run** stops the paused execution, writes the fix and re-runs; the pipeline then completes through all four operators and the tab removes itself, because the operator no longer reports an error. The same panel when the error falls outside the three patterns -- here a `ZeroDivisionError` from the same operator. It is reported without calling the model at all, because the classification runs client-side before the request: <img width="1536" height="639" alt="ai-fix-unsupported" src="https://github.com/user-attachments/assets/68b132bf-dfcd-4dc0-a7b2-fff423ebf953" /> ### Any related issues, documentation, discussions? Closes apache#8662 Hackathon submission for apache#8520 (Universidad Panamericana – Apache Texera Hackathon). ### How was this PR tested? - **Unit tests**: 295 across the result-panel specs — 57 for the service, 23 for the frame, 4 for the prompt builder, 69 for the result panel itself. Every fix in this PR was confirmed failing against the code before it, which caught eight tests of mine that passed either way and had to be rewritten or deleted. ``` cd frontend && yarn test --include="src/app/workspace/component/result-panel/**/*.spec.ts" ``` - **Whole frontend suite**: 7011 passing across 247 files (1 skipped). Everything CI runs on the frontend was run locally too: `yarn format:ci`, `yarn build:ci` (clean production AOT build), `yarn test:ci`, and `ng run gui:test-browser` (23 passing in Chromium). - **End to end on a local stack** (Windows, native services, LiteLLM + `claude-haiku-4.5`), as recorded above: the Python worker raised `KeyError: 'lines'` with the execution still `Running`; Analyze returned `- title = tuple_["lines"]` / `+ title = tuple_["line"]` with high confidence, correctly citing the input schema; Apply patched the operator and the re-run reached `Completed` with rows through both downstream operators. - The prompt's whole-lines rule was measured rather than assumed: 28 of 28 replies from `claude-haiku-4.5` were accepted across the three code-change shapes, against 11 of 12 for the previous prompt, whose single refusal is exactly the mid-line snippet the rule exists for. ### Was this PR authored or co-authored using generative AI tooling? Yes. Generated-by: Claude Code (Claude Opus 5) --------- Co-authored-by: Pedro <pluimar973@gmail.com> Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
… is read (apache#9190) ### What changes were proposed in this PR? Workflows took the owner's privilege from their `workflow_user_access` row alone. If that row was missing or downgraded, the owner lost access to their own workflow, or it was hidden from them. This makes workflows match datasets, models and computing units (apache#8890): the owner is always WRITE. - **Access checks**: `WorkflowAccessResource.getPrivilege` reads the caller's own owner row and access row in one query (so a workflow with several owners still yields one row) and returns WRITE for the owner (via `OwnerAccess.privilege`). `hasReadAccess`, `hasWriteAccess`, `hasGrantedAccess` and sharing all go through it. - **Search and the workflow list**: these include owned workflows, not only ones with an access row, and report the owner as WRITE. For apache#8576's pinned copies, the owner counts as granted, so they always see their own live name and description, never the pinned ones. - **Owned-or-granted ids**: the new `WorkflowAccessResource.accessibleWids(uid)` is the single source for the ID and owner filters, the quota page and the admin executions page. Each of these used to read the access table alone. - **Hub**: `baseWorkflowSelect(uid)` joins only the viewer's access row, the same as the dataset/model hub fix in apache#8890. A workflow shared with several users now gives one card with the viewer's own level, instead of duplicates or someone else's level. ### Any related issues, documentation, discussions? Closes apache#9150. Follow-up to apache#8890. ### How was this PR tested? New tests: - `WorkflowAccessResourceSpec`: the owner is WRITE with no access row, and with a READ row. A workflow with several owner rows doesn't fail the check. `accessibleWids` lists owned and granted workflows once each. - `WorkflowResourceSpec`: after the owner's access row is deleted, they still see the workflow as WRITE in the list, search, the ID and owner filters, and when opening it. - `HubResourceSpec`: a workflow shared with two other users gives one entry with the viewer's own level (NONE for an ungranted or anonymous viewer). The owner without an access row gets WRITE. - `UserQuotaResourceSpec`, `AdminUserResourceSpec`, `AdminExecutionResourceSpec`: an owner without an access row still gets their workflow listed or marked accessible. - `WorkflowSearchQueryBuilderSpec`: the owner is WRITE whatever their access row says, and sees their live name rather than the pinned one. An anonymous viewer of a workflow with no owner row is not mistaken for the owner. Three existing tests assumed the old behaviour and were updated. One asserted NONE for an owner without an access row, which is the bug this PR fixes. The other two read the privilege as the owner, so they now read it as a non-owner. With the main-code changes reverted, the 6 new owner and hub tests fail. The affected amber specs pass (373), and `scalafmtCheckAll` and `scalafixAll --check` are clean. ### Was this PR authored or co-authored using generative AI tooling? Generated-by: Claude Code (Claude Opus 5.5)
…#5377) ### What changes were proposed in this PR? Provides the local deployment wiring that receives and stores telemetry. Off by default and isolated from the application services. - Adds an OpenTelemetry Collector configuration and wires it into the single-node `docker-compose` stack and the Kubernetes Helm chart. - Adds the Parca server configuration and the Parca eBPF agent for continuous profiling. - Adds the observability backends to the single-node `.env` and `docker-compose` as opt-in compose profiles; `COMPOSE_PROFILES` is empty by default, so `docker compose up` runs only core Texera. - Infrastructure only; the application runs unchanged whether or not these services are started. ### Any related issues, documentation, or discussions? Closes: apache#5369 Part of apache#4070. Stacked on apache#5376. ### How was this PR tested? - Configuration-validation specs for the collector and Parca config (`ObservabilityComposeSpec`, `ParcaConfigSpec`); 24 tests pass. - `sbt scalafmtCheckAll` passes; the build runs in this PR's CI. ### Was this PR authored or co-authored using generative AI tooling? Co-authored with Claude Opus 4.8 in compliance with ASF policy. Co-authored-by: Zuozhi Wang <zuozhiw@gmail.com>
…9204) ### What changes were proposed in this PR? The 48 Python visualization descriptors each restated the same output contract: a `getOutputSchemas` override returning one `html-content` STRING column on the single output port, and `producesDataFrame = false` so the exported script does not print the chart as a leaf DataFrame. A new trait, `PythonVisualizationOpDesc`, now declares both as `final` members, and the 48 descriptors extend it. The 41 Plotly charts keep `with PlotlyStandaloneCode`. | Surface | Pinned | | --- | --- | | output schema | one `html-content` STRING column on the single output port, independent of the input schemas | | exported script | not printed as a leaf DataFrame | | operator metadata | JSON schema and operator info unchanged for all 166 operators | The trait has no fields, so no JSON schema changes. Because both members are `final`, a chart that overrides either one no longer compiles. `VisualizationOutputSchemaSpec` still sweeps every registered chart. It now also requires every chart except the two Scala map operators, HtmlViz and UrlViz, to extend the trait, and asserts that `producesDataFrame()` is false next to the schema. ### Any related issues, documentation, discussions? Closes apache#9203. ### How was this PR tested? - `sbt "WorkflowOperator/test"`: each of its 2,769 tests (295 suites) has the same result before and after this change, compared test by test from the JUnit XML reports; the two `VisualizationOutputSchemaSpec` tests whose assertions grew were renamed and pass. Three tests fail on main and on this branch alike on the Windows machine used (a locked temp file in `FileScanSourceOpDescSpec`, a mount path in `PythonUdfUiParameterSupportSpec`, an exported-script comparison in `UrlVizOpDescSpec`); none touches the changed code. - `sbt "WorkflowCompilingService/testOnly org.apache.texera.amber.translator.*"`: 41 tests pass before and after. - The JSON schema and operator info of all 166 registered operators, dumped before and after, are identical. - Mutation check: making the trait's `producesDataFrame` return true fails the sweep, and so does pointing one chart (`BarChartOpDesc`) back at `PythonOperatorDescriptor` with its own correct overrides; overriding either `final` member in a chart fails to compile. - `sbt "WorkflowOperator/scalafmtCheck" "WorkflowOperator/Test/scalafmtCheck" "WorkflowOperator/scalafix --check" "WorkflowOperator/Test/scalafix --check"` ### Was this PR authored or co-authored using generative AI tooling? Generated-by: Claude Code (Claude Opus 5.5)
### What changes were proposed in this PR? - Adds a Vitest spec for `FileSaverService`, the thin wrapper whose `saveAs(data, filename?, options?)` forwards straight to the `file-saver` library's `saveAs`. - Mocks the `file-saver` library so the suite can assert the call is forwarded unchanged: a Blob payload passes through with its filename and options, and a string payload (such as a URL) passes through. - Asserts that an omitted filename and options arrive as `undefined`, and that an error thrown by the underlying `saveAs` propagates to the caller instead of being swallowed. ### Any related issues, documentation, discussions? Closes: apache#6448 Supersedes apache#6460, which the stale bot auto-closed for inactivity. The branch is now merged up to current `main`. ### How was this PR tested? - Run `cd frontend && npx ng test --include="**/file-saver.service.spec.ts" --watch=false`, expect the FileSaverService suite to pass. - Confirm the forwarding cases hold: a Blob and a string payload each reach the mocked `saveAs` unchanged, an omitted filename and options arrive as `undefined`, and a thrown error surfaces to the caller. ### Was this PR authored or co-authored using generative AI tooling? Co-authored with Claude Opus 4.8 in compliance with ASF --------- Signed-off-by: Xinyuan Lin <xinyual3@uci.edu> Co-authored-by: Xinyuan Lin <xinyual3@uci.edu> Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…rce language (apache#8910) ### What changes were proposed in this PR? This is the first of three PRs adding R support to the migration tool (apache#8009). It is a pure refactor with no behavior change: Python conversions send the same prompts and build the same operators as before. The migration tool hardcodes Python in three places that R needs to vary: the documentation and prompts sent to the model, the operator type built from each generated UDF (`PythonUDFV2`), and the kernelspec of the notebook derived for a script. This PR gathers those into one `MigrationPromptSet` per source language, held in a `PROMPT_SETS` table that only has a Python entry for now. * `convertNotebookToWorkflow` and `convertScriptToWorkflow` take a `language` argument, defaulting to `"python"`, and read everything from the set. * `buildWorkflow`, `requestConversion` and `finishConversion` receive the operator type and notebook metadata as arguments instead of hardcoding them. * The three Python documentation arrays move from private statics on the class to module level constants, unchanged, so the table can reference them. * The folder path uses the Python set explicitly. R folders come in a later PR. `MigrationLanguage` is `"python"` only in this PR. The next PR widens it to `"python" | "r"` and adds the R set. ### Any related issues, documentation, discussions? Part of apache#8009 Parent-issue apache#4301 The plan for R support is in apache#8866. The follow up PRs add the R prompts and the R option in the import modal. They are stacked on this one. ### How was this PR tested? Three new tests in `migration-llm.spec.ts` pin the Python output so later changes cannot alter it silently: * The notebook path sends exactly the existing system prelude, workflow prompt and mapping prompt. * The script path does the same with the script prelude and prompts. * Generated operators are built as `PythonUDFV2`. The existing notebook, script and folder tests pass unchanged. Coverage of `migration-llm.ts` is 100% of lines; the one uncovered branch is the `@Injectable()` decorator, as before this change. The full frontend suite passes. ### Was this PR authored or co-authored using generative AI tooling? Generated-by: Claude Code (Claude Opus 5.5)
|
@eugenegujing Added the partitioner-level LARGE_BINARY test you suggested, including a non-BMP URI. It reproduces the original KeyError. The focused suites give 144 passes; the existing Windows epoch-hashing test remains separate in #8957. Ruff passes, and CI has restarted. |
What changes were proposed in this PR?
Support hash routing for LARGE_BINARY fields by hashing the URI with Java-compatible UTF-16 code units. Null hashing stays unchanged.
Any related issues, documentation, discussions?
Closes #8185
Closes #8243
Replaces stale-closed #8186 and consolidates the overlapping #8244.
How was this PR tested?
Fresh upstream main at 7426431, Python 3.12 on Windows. All three URI regressions failed with KeyError before the implementation change and passed afterward. Coverage includes ASCII, supplementary Unicode, and null values.
From amber, after bash bin/python-proto-gen.sh:
The broader suites passed 356 tests with one expected failure. Two existing Windows pre-epoch fixtures were deselected. The new regression name avoids that deselection and all three cases ran. Ruff passed for all 217 Python files.
Review follow-up, October 29: Added partitioner-level LARGE_BINARY routing coverage for ordinary and non-BMP URI keys. Both cases fail with KeyError when the original hash mapping is restored and pass with this PR.
Fresh detached worktree from upstream main 8b89d0c with this PR applied. Focused tuple and partitioner suites: 144 passed, one existing epoch-hashing test deselected on Windows because it raises OSError without the separate #8957 change. No assertion in that test was changed. Ruff check and formatting check pass for all 217 Python files.
Was this PR authored or co-authored using generative AI tooling?
Generated-by: Codex