Eliaaazzz commented on code in PR #40129:
URL: https://github.com/apache/beam/pull/40129#discussion_r4052155697
##########
runners/spark/src/main/java/org/apache/beam/runners/spark/SparkPipelineRunner.java:
##########
@@ -82,7 +83,14 @@ public SparkPipelineRunner(SparkPipelineOptions
pipelineOptions) {
public PortablePipelineResult run(RunnerApi.Pipeline pipeline, JobInfo
jobInfo) {
SparkPortablePipelineTranslator translator;
boolean isStreaming = pipelineOptions.isStreaming() ||
hasUnboundedPCollections(pipeline);
- if (isStreaming) {
+ if (pipelineOptions.getUseStructuredStreaming()) {
+ // The Dataset backend evaluates its own leaves. It never starts a
DStream context, and it
Review Comment:
Done in f4a2d39cfcf. The runner no longer sets the streaming option. It
selects the Dataset translator by useStructuredStreaming, and with that flag
set it never selects the DStream translator and never starts a streaming
context, whatever the streaming option says.
For the metrics accumulator I added an init overload with an explicit
useCheckpoint argument. The portable runner passes the streaming option
restricted to the DStream path, so the Dataset backend never opens the DStream
metrics checkpoint and the DStream path keeps its previous condition. The two
argument init keeps reading the streaming option, so the classic runner is
unchanged.
I also reworded the runner comment, the option description, the translator
javadoc, the rejection message and the README so the unbounded rejection reads
as the current status.
##########
runners/spark/src/test/java/org/apache/beam/runners/spark/SparkDatasetPortableExecutionTest.java:
##########
@@ -0,0 +1,219 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.beam.runners.spark;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.hasItem;
+import static org.junit.Assert.assertEquals;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+import org.apache.beam.model.jobmanagement.v1.JobApi.JobState;
+import org.apache.beam.model.pipeline.v1.RunnerApi;
+import org.apache.beam.runners.jobsubmission.JobInvocation;
+import org.apache.beam.sdk.Pipeline;
+import org.apache.beam.sdk.coders.BigEndianLongCoder;
+import org.apache.beam.sdk.coders.ByteArrayCoder;
+import org.apache.beam.sdk.coders.KvCoder;
+import org.apache.beam.sdk.coders.StringUtf8Coder;
+import org.apache.beam.sdk.io.GenerateSequence;
+import org.apache.beam.sdk.options.PipelineOptions;
+import org.apache.beam.sdk.options.PipelineOptionsFactory;
+import org.apache.beam.sdk.options.PortablePipelineOptions;
+import org.apache.beam.sdk.state.StateSpec;
+import org.apache.beam.sdk.state.StateSpecs;
+import org.apache.beam.sdk.state.ValueState;
+import org.apache.beam.sdk.testing.CrashingRunner;
+import org.apache.beam.sdk.testing.PAssert;
+import org.apache.beam.sdk.transforms.DoFn;
+import org.apache.beam.sdk.transforms.Flatten;
+import org.apache.beam.sdk.transforms.GroupByKey;
+import org.apache.beam.sdk.transforms.Impulse;
+import org.apache.beam.sdk.transforms.ParDo;
+import org.apache.beam.sdk.transforms.WithKeys;
+import org.apache.beam.sdk.util.construction.Environments;
+import org.apache.beam.sdk.util.construction.PipelineTranslation;
+import org.apache.beam.sdk.values.KV;
+import org.apache.beam.sdk.values.PCollection;
+import org.apache.beam.sdk.values.PCollectionList;
+import
org.apache.beam.vendor.guava.v32_1_2_jre.com.google.common.util.concurrent.ListeningExecutorService;
+import
org.apache.beam.vendor.guava.v32_1_2_jre.com.google.common.util.concurrent.MoreExecutors;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/**
+ * Runs portable pipelines end to end on the Dataset-based backend: job
invocation, executable stage
+ * translation, and execution with the embedded SDK harness.
+ */
+@RunWith(JUnit4.class)
+public class SparkDatasetPortableExecutionTest implements Serializable {
+ private static ListeningExecutorService executor;
+
+ @BeforeClass
+ public static void setUp() {
+ executor =
MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(1));
+ }
+
+ @AfterClass
+ public static void tearDown() throws InterruptedException {
+ executor.shutdown();
+ executor.awaitTermination(10, TimeUnit.SECONDS);
+ executor = null;
+ }
+
+ @Test(timeout = 180_000)
+ public void boundedPipelineRunsOnDatasets() throws Exception {
+ SparkPipelineOptions options = options();
+ Pipeline p = Pipeline.create(options);
+ PCollection<String> words =
+ p.apply("impulse", Impulse.create())
Review Comment:
Done in f4a2d39cfcf. SparkDatasetPortableExecutionTest keeps one end to end
run through the job invoker with --streaming and --useStructuredStreaming, as
the gate task sets them. The rest moved to component tests in the translation
package. The end to end rejection checks went with them, so a translation
failure surfacing as a FAILED job is no longer covered here.
SparkDatasetPortablePipelineTranslatorTest covers one piece at a time.
Flatten with mismatched input coders, GroupByKey with fixed windows and
Reshuffle are translated on injected Datasets. Impulse, a multi-output stage
and a side input go through the translator on a small pipeline and run in the
embedded harness. The unbounded, state and timer rejections are asserted on the
translator directly. SparkDatasetTranslationContextTest covers the persist
decisions and that only unconsumed Datasets are evaluated. The per transform
translators are package private with @VisibleForTesting for that.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]