[FLINK] Support ORC filesystem sink format#12327
Open
zhanglistar wants to merge 5 commits into
Open
Conversation
b9fe77f to
4e42142
Compare
KevinyhZou
reviewed
Jun 23, 2026
647a12f to
43d0e3f
Compare
Contributor
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.
Comments suppressed due to low confidence (1)
gluten-flink/ut/src/test/java/org/apache/gluten/table/runtime/stream/custom/NexmarkTest.java:259
- verifyQ10OrcOutput() only checks Files.exists(outputDir), which would also pass if the path exists but is not a directory (e.g., a leftover file). Using Files.isDirectory makes the assertion stricter and avoids misleading failures later in Files.walk.
}
String insertQuery = sqlStatements[sqlStatements.length - 2].trim();
Contributor
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 9 out of 9 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (1)
gluten-flink/ut/src/test/java/org/apache/gluten/table/runtime/stream/custom/NexmarkTest.java:263
- This AssertJ call doesn't assert anything because it doesn't chain an assertion (e.g. .isTrue()). As written, the test will pass even if checkJobRunningStatus() returns false, reducing coverage for the Kafka-source path.
String insertQuery = sqlStatements[sqlStatements.length - 2].trim();
Comment on lines
+226
to
+247
| // Clean the ORC output directory before running q10_orc to ensure deterministic verification. | ||
| if ("q10_orc.sql".equals(queryFileName)) { | ||
| Path orcOutputDir = Paths.get("/tmp/data/output/bid_orc"); | ||
| if (Files.exists(orcOutputDir)) { | ||
| try { | ||
| try (java.util.stream.Stream<Path> files = Files.walk(orcOutputDir)) { | ||
| files | ||
| .sorted(java.util.Comparator.reverseOrder()) | ||
| .forEach( | ||
| p -> { | ||
| try { | ||
| Files.deleteIfExists(p); | ||
| } catch (IOException e) { | ||
| throw new RuntimeException("Failed to delete " + p, e); | ||
| } | ||
| }); | ||
| } | ||
| } catch (IOException e) { | ||
| throw new RuntimeException("Failed to clean ORC output directory", e); | ||
| } | ||
| } | ||
| } |
1c10b05 to
b418981
Compare
Comment on lines
371
to
376
| @Override | ||
| public void snapshotState(StateSnapshotContext context) throws Exception { | ||
| // TODO: implement it | ||
| snapshotNativeState(context.getCheckpointId()); | ||
| task.snapshotState(0); | ||
| super.snapshotState(context); | ||
| } |
Comment on lines
+232
to
+245
| private void processAvailableElement() { | ||
| final StatefulElement statefulElement = task.statefulGet(); | ||
| try { | ||
| if (statefulElement.isWatermark()) { | ||
| StatefulWatermark watermark = statefulElement.asWatermark(); | ||
| output.emitWatermark(new Watermark(watermark.getTimestamp())); | ||
| } else { | ||
| outputBridge.collect( | ||
| output, statefulElement.asRecord(), sessionResource.getAllocator(), outputType); | ||
| } | ||
| } finally { | ||
| statefulElement.close(); | ||
| } | ||
| } |
Comment on lines
+214
to
+227
| private void processAvailableElement() { | ||
| final StatefulElement element = task.statefulGet(); | ||
| try { | ||
| if (element.isWatermark()) { | ||
| StatefulWatermark watermark = element.asWatermark(); | ||
| output.emitWatermark(new Watermark(watermark.getTimestamp())); | ||
| } else { | ||
| outputBridge.collect( | ||
| output, element.asRecord(), sessionResource.getAllocator(), outputType); | ||
| } | ||
| } finally { | ||
| element.close(); | ||
| } | ||
| } |
Comment on lines
+254
to
+272
| private void finishTask() { | ||
| while (true) { | ||
| UpIterator.State state = task.advance(); | ||
| switch (state) { | ||
| case AVAILABLE: | ||
| processAvailableElement(); | ||
| break; | ||
| case BLOCKED: | ||
| task.waitFor(); | ||
| break; | ||
| case FINISHED: | ||
| return; | ||
| default: | ||
| // Treat unknown states as terminal, consistent with GlutenSourceFunction. | ||
| LOG.warn("Unexpected Velox task state in finishTask: {}", state); | ||
| return; | ||
| } | ||
| } | ||
| } |
Comment on lines
+236
to
+254
| private void finishTask() { | ||
| while (true) { | ||
| UpIterator.State state = task.advance(); | ||
| switch (state) { | ||
| case AVAILABLE: | ||
| processAvailableElement(); | ||
| break; | ||
| case BLOCKED: | ||
| task.waitFor(); | ||
| break; | ||
| case FINISHED: | ||
| return; | ||
| default: | ||
| // Treat unknown states as terminal, consistent with GlutenSourceFunction. | ||
| LOG.warn("Unexpected Velox task state in finishTask: {}", state); | ||
| return; | ||
| } | ||
| } | ||
| } |
Comment on lines
+270
to
+274
| // Allow filesystem sink to flush and commit partitions after job completion. | ||
| Thread.sleep(2000); | ||
| if ("q10_orc.sql".equals(queryFileName)) { | ||
| verifyQ10OrcOutput(queryStartMillis); | ||
| } |
84ef067 to
7749d8a
Compare
Comment on lines
269
to
+274
| waitForJobCompletion(insertResult, 30000); | ||
| // Allow filesystem sink to flush and commit partitions after job completion. | ||
| Thread.sleep(2000); | ||
| if ("q10_orc.sql".equals(queryFileName)) { | ||
| verifyQ10OrcOutput(queryStartMillis); | ||
| } |
Comment on lines
31
to
+35
| <properties> | ||
| <flink.version>1.19.2</flink.version> | ||
| <velox4j.version>0.1.0-SNAPSHOT</velox4j.version> | ||
| <protobuf.version>3.25.5</protobuf.version> | ||
| <hadoop.version>2.7.2</hadoop.version> |
Comment on lines
65
to
68
| } else if (operatorFactory instanceof GlutenOneInputOperatorFactory) { | ||
| return Optional.of(((GlutenOneInputOperatorFactory) operatorFactory).getOperator()); | ||
| } else if (operatorFactory instanceof GlutenTwoInputOperatorFactory) { | ||
| return Optional.of(((GlutenTwoInputOperatorFactory) operatorFactory).getOperator()); | ||
| } | ||
| return Optional.empty(); |
Comment on lines
+283
to
+286
| outputIdle = leftInputIdle && rightInputIdle; | ||
| if (wasIdle != outputIdle) { | ||
| output.emitWatermarkStatus(outputIdle ? WatermarkStatus.IDLE : WatermarkStatus.ACTIVE); | ||
| } |
| // ProcessingTimeService for Flink AbstractStreamOperator. GlutenTwoInputOperator uses | ||
| // GlutenAbstractStreamOperator so it needs the Gluten-specific factory. | ||
| offloadedOpConfig.setStreamOperatorFactory(new GlutenTwoInputOperatorFactory<>(newTwoInputOp)); | ||
| offloadedOpConfig.setStreamOperator(newTwoInputOp); |
| // ProcessingTimeService for Flink AbstractStreamOperator. GlutenTwoInputOperator uses | ||
| // GlutenAbstractStreamOperator so it needs the Gluten-specific factory. | ||
| offloadedOpConfig.setStreamOperatorFactory(new GlutenTwoInputOperatorFactory<>(newTwoInputOp)); | ||
| offloadedOpConfig.setStreamOperator(newTwoInputOp); |
- Support ORC filesystem sink format with q10_orc.sql test - Add finishTask() to endInput() for both OneInput and TwoInput operators - Route finishTask through drainOutput for mailbox reentrancy guard - Treat unknown UpIterator.State as terminal (log+return, not throw) - Close() only releases resources, does not drain output - Add close tests for both operators - Use protobuf.version and hadoop.version properties in UT pom - Use dedicated output dir and process trigger for q10_orc - Clean ORC output dir before q10_orc for deterministic verification - Align Kafka port with KafkaToHiveE2ETest (19092) - Update velox4j commit to f8684c84 (includes EmptyOperator NYI fix) - Remove GlutenWatermarkStatuses (not supported by current velox4j)
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Comment on lines
65
to
68
| } else if (operatorFactory instanceof GlutenOneInputOperatorFactory) { | ||
| return Optional.of(((GlutenOneInputOperatorFactory) operatorFactory).getOperator()); | ||
| } else if (operatorFactory instanceof GlutenTwoInputOperatorFactory) { | ||
| return Optional.of(((GlutenTwoInputOperatorFactory) operatorFactory).getOperator()); | ||
| } | ||
| return Optional.empty(); |
| // ProcessingTimeService for Flink AbstractStreamOperator. GlutenTwoInputOperator uses | ||
| // GlutenAbstractStreamOperator so it needs the Gluten-specific factory. | ||
| offloadedOpConfig.setStreamOperatorFactory(new GlutenTwoInputOperatorFactory<>(newTwoInputOp)); | ||
| offloadedOpConfig.setStreamOperator(newTwoInputOp); |
Comment on lines
+270
to
+274
| if ("q10_orc.sql".equals(queryFileName)) { | ||
| // Allow filesystem sink to flush and commit partitions after job completion. | ||
| Thread.sleep(2000); | ||
| verifyQ10OrcOutput(queryStartMillis); | ||
| } |
Comment on lines
65
to
67
| } else if (operatorFactory instanceof GlutenOneInputOperatorFactory) { | ||
| return Optional.of(((GlutenOneInputOperatorFactory) operatorFactory).getOperator()); | ||
| } else if (operatorFactory instanceof GlutenTwoInputOperatorFactory) { | ||
| return Optional.of(((GlutenTwoInputOperatorFactory) operatorFactory).getOperator()); | ||
| } |
Comment on lines
280
to
285
| sourceOperator.getRightInputType(), | ||
| sourceOperator.getOutputTypes(), | ||
| inClass, | ||
| outClass); | ||
| // setStreamOperator would wrap this in Flink's SimpleOperatorFactory, which only initializes | ||
| // ProcessingTimeService for Flink AbstractStreamOperator. GlutenTwoInputOperator uses | ||
| // GlutenAbstractStreamOperator so it needs the Gluten-specific factory. | ||
| offloadedOpConfig.setStreamOperatorFactory(new GlutenTwoInputOperatorFactory<>(newTwoInputOp)); | ||
| offloadedOpConfig.setStreamOperator(newTwoInputOp); | ||
| offloadedOpConfig.setStatePartitioner(0, new GlutenKeySelector()); |
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
What changes are proposed in this pull request?
Gluten Flink support ORC flilesystem sink format, solves #12203.
Depends on bigo-sg/velox4j#43 and bigo-sg/velox#52.
How was this patch tested?
UT
Was this patch authored or co-authored using generative AI tooling?