Skip to content

Commit fe2a224

Browse files
authored
Add Ordered Processing PTransform to Java SDK (#30735)
* Initial check-in of the ordered processing extension in Java. * Address PR comments. * Address PR comments. * Added JavaDocs to OrderedProcessingStatus.java * Added batch tests. Added DLQ for events with the sequence outside of the valid range. * Added tests for windowed input. Added references to the unresolved TODO's captured as Beam's issues. * Added DLQ handling of checked exceptions happening during the state mutations.
1 parent e3fee51 commit fe2a224

16 files changed

Lines changed: 2972 additions & 0 deletions
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* License); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an AS IS BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
plugins { id 'org.apache.beam.module' }
19+
applyJavaNature(automaticModuleName: 'org.apache.beam.sdk.extensions.sorter')
20+
21+
description = "Apache Beam :: SDKs :: Java :: Extensions :: Ordered"
22+
23+
dependencies {
24+
implementation project(path: ":sdks:java:core", configuration: "shadow")
25+
implementation library.java.slf4j_api
26+
implementation library.java.joda_time
27+
implementation library.java.commons_lang3
28+
implementation library.java.vendored_guava_32_1_2_jre
29+
testImplementation library.java.junit
30+
testImplementation library.java.hamcrest
31+
testImplementation project(path: ':sdks:java:core')
32+
testRuntimeOnly project(path: ":runners:direct-java", configuration: "shadow")
33+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
package org.apache.beam.sdk.extensions.ordered;
19+
20+
import java.io.Serializable;
21+
import org.checkerframework.checker.nullness.qual.NonNull;
22+
23+
/**
24+
* Classes extending this interface will be called by {@link OrderedEventProcessor} to examine every
25+
* incoming event.
26+
*
27+
* @param <EventT>
28+
* @param <StateT>
29+
*/
30+
public interface EventExaminer<EventT, StateT extends MutableState<EventT, ?>>
31+
extends Serializable {
32+
33+
/**
34+
* Is this event the first expected event for the given key and window?
35+
*
36+
* @param sequenceNumber the sequence number of the event as defined by the key of the input
37+
* PCollection to {@link OrderedEventProcessor}
38+
* @param event being processed
39+
* @return true if this is the initial sequence.
40+
*/
41+
boolean isInitialEvent(long sequenceNumber, EventT event);
42+
43+
/**
44+
* If the event was the first event in the sequence, create the state to hold the required data
45+
* needed for processing. This data will be persisted.
46+
*
47+
* @param event the first event in the sequence.
48+
* @return the state to persist.
49+
*/
50+
@NonNull
51+
StateT createStateOnInitialEvent(EventT event);
52+
53+
/**
54+
* Is this event the last expected event for a given key and window?
55+
*
56+
* @param sequenceNumber of the event
57+
* @param event being processed
58+
* @return true if the last event. There are cases where it's impossible to know whether it's the
59+
* last event. False should be returned in those cases.
60+
*/
61+
boolean isLastEvent(long sequenceNumber, EventT event);
62+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
package org.apache.beam.sdk.extensions.ordered;
19+
20+
import java.io.Serializable;
21+
22+
/** Mutable state mutates when events apply to it. It is stored in a Beam state. */
23+
public interface MutableState<EventT, ResultT> extends Serializable {
24+
25+
/**
26+
* The interface assumes that events will mutate the state without the possibility of throwing an
27+
* error.
28+
*
29+
* @param event to be processed
30+
* @throws Exception if a checked exception is thrown, the event will be output into {@link
31+
* OrderedEventProcessorResult#unprocessedEvents()} with
32+
*/
33+
void mutate(EventT event) throws Exception;
34+
35+
/**
36+
* This method is called after each state mutation.
37+
*
38+
* @return Result of the processing. Can be null if nothing needs to be output after this
39+
* mutation.
40+
*/
41+
ResultT produceResult();
42+
}

0 commit comments

Comments
 (0)