-
Notifications
You must be signed in to change notification settings - Fork 751
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[GOBBLIN-1941] Develop Temporal abstractions, including
Workload
fo…
…r workflows of unbounded size through sub-workflow nesting (#3811) * Define `Workload` abstraction for Temporal workflows of unbounded size through sub-workflow nesting * Adjust Gobblin-Temporal configurability for consistency and abstraction * Define `WorkerConfig`, to pass the `TemporalWorker`'s configuration to the workflows and activities it hosts * Improve javadoc * Javadoc fixup * Minor changes * Update per review suggestions * Insert pause, to spread the load on the temporal server, before launch of each child workflow that may have direct leaves of its own * Appease findbugs by having `SeqSliceBackedWorkSpan::next` throw `NoSuchElementException` * Add comment
- Loading branch information
Showing
12 changed files
with
619 additions
and
16 deletions.
There are no files selected for viewing
This file contains 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
This file contains 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
This file contains 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
28 changes: 28 additions & 0 deletions
28
gobblin-temporal/src/main/java/org/apache/gobblin/temporal/cluster/TemporalWorker.java
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
/* | ||
* 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.gobblin.temporal.cluster; | ||
|
||
/** Marker interface for a temporal.io "worker", with capability to `start()` and `shutdown()` */ | ||
public interface TemporalWorker { | ||
|
||
/** Starts the worker */ | ||
void start(); | ||
|
||
/** Shuts down the worker */ | ||
void shutdown(); | ||
} |
72 changes: 72 additions & 0 deletions
72
gobblin-temporal/src/main/java/org/apache/gobblin/temporal/cluster/WorkerConfig.java
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
/* | ||
* 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.gobblin.temporal.cluster; | ||
|
||
import java.util.Optional; | ||
import java.util.concurrent.ConcurrentHashMap; | ||
|
||
import lombok.extern.slf4j.Slf4j; | ||
|
||
import com.typesafe.config.Config; | ||
|
||
|
||
/** | ||
* Static holder to stash the {@link Config} used to construct each kind of {@link org.apache.gobblin.temporal.cluster.TemporalWorker} | ||
* (within the current JVM). Lookup may be by either the {@link Class} of the worker or of any workflow or activity implementation supplied by | ||
* that worker. The objective is to facilitate sharing the worker's Config with workflow and activity implementations (running within that worker). | ||
* | ||
* ATTENTION: for sanity, construct multiple instances of the same worker always with the same {@link Config}. When this is violated, the `Config` | ||
* given to the most-recently constructed worker "wins". | ||
* | ||
* NOTE: the preservation and sharing of {@link Config} is predicated entirely on its immutability. Thank you TypeSafe! | ||
* Storage indexing uses FQ class name, not the {@link Class}, to be independent of classloader. | ||
*/ | ||
@Slf4j | ||
public class WorkerConfig { | ||
private static final ConcurrentHashMap<String, Config> configByFQClassName = new ConcurrentHashMap<>(); | ||
|
||
private WorkerConfig() {} | ||
|
||
/** @return whether initialized now (vs. being previously known) */ | ||
public static boolean forWorker(Class<? extends TemporalWorker> workerClass, Config config) { | ||
return storeAs(workerClass.getName(), config); | ||
} | ||
|
||
/** @return whether initialized now (vs. being previously known) */ | ||
public static boolean withImpl(Class<?> workflowOrActivityImplClass, Config config) { | ||
return storeAs(workflowOrActivityImplClass.getName(), config); | ||
} | ||
|
||
public static Optional<Config> ofWorker(Class<? extends TemporalWorker> workerClass) { | ||
return Optional.ofNullable(configByFQClassName.get(workerClass.getName())); | ||
} | ||
|
||
public static Optional<Config> ofImpl(Class<?> workflowOrActivityImplClass) { | ||
return Optional.ofNullable(configByFQClassName.get(workflowOrActivityImplClass.getName())); | ||
} | ||
|
||
public static Optional<Config> of(Object workflowOrActivityImpl) { | ||
return ofImpl(workflowOrActivityImpl.getClass()); | ||
} | ||
|
||
private static boolean storeAs(String className, Config config) { | ||
Config prior = configByFQClassName.put(className, config); | ||
log.info("storing config of {} values as '{}'{}", config.entrySet().size(), className, prior == null ? " (new)" : ""); | ||
return prior == null; | ||
} | ||
} |
This file contains 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
70 changes: 70 additions & 0 deletions
70
...mporal/src/main/java/org/apache/gobblin/temporal/util/nesting/work/SeqBackedWorkSpan.java
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
/* | ||
* 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.gobblin.temporal.util.nesting.work; | ||
|
||
import java.util.Iterator; | ||
import java.util.List; | ||
import lombok.NoArgsConstructor; | ||
import lombok.NonNull; | ||
import lombok.RequiredArgsConstructor; | ||
|
||
|
||
/** Logical sub-sequence of `WORK_ITEM`s, backed for simplicity's sake by an in-memory collection */ | ||
@NoArgsConstructor | ||
@RequiredArgsConstructor | ||
public class SeqBackedWorkSpan<WORK_ITEM> implements Workload.WorkSpan<WORK_ITEM> { | ||
|
||
@NonNull | ||
private List<WORK_ITEM> elems; | ||
// CAUTION: despite the "warning: @NonNull is meaningless on a primitive @lombok.RequiredArgsConstructor"... | ||
// if removed, no two-arg ctor is generated, so syntax error on `new CollectionBackedTaskSpan(elems, startIndex)` | ||
@NonNull | ||
private int startingIndex; | ||
private transient Iterator<WORK_ITEM> statefulDelegatee = null; | ||
|
||
@Override | ||
public int getNumElems() { | ||
return elems.size(); | ||
} | ||
|
||
@Override | ||
public boolean hasNext() { | ||
if (statefulDelegatee == null) { | ||
statefulDelegatee = elems.iterator(); | ||
} | ||
return statefulDelegatee.hasNext(); | ||
} | ||
|
||
@Override | ||
public WORK_ITEM next() { | ||
if (statefulDelegatee == null) { | ||
throw new IllegalStateException("first call `hasNext()`!"); | ||
} | ||
return statefulDelegatee.next(); | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return getClassNickname() + "(" + startingIndex + "... {+" + getNumElems() + "})"; | ||
} | ||
|
||
protected String getClassNickname() { | ||
// return getClass().getSimpleName(); | ||
return "WorkSpan"; | ||
} | ||
} |
75 changes: 75 additions & 0 deletions
75
...l/src/main/java/org/apache/gobblin/temporal/util/nesting/work/SeqSliceBackedWorkSpan.java
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
/* | ||
* 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.gobblin.temporal.util.nesting.work; | ||
|
||
import java.util.NoSuchElementException; | ||
import lombok.NoArgsConstructor; | ||
import lombok.NonNull; | ||
import lombok.RequiredArgsConstructor; | ||
import com.fasterxml.jackson.annotation.JsonIgnore; | ||
|
||
|
||
/** Logical sub-sequence of `WORK_ITEM`s, backed for simplicity's sake by an in-memory collection, *SHARED* w/ other work spans */ | ||
@NoArgsConstructor | ||
@RequiredArgsConstructor | ||
public class SeqSliceBackedWorkSpan<WORK_ITEM> implements Workload.WorkSpan<WORK_ITEM> { | ||
private static final int NOT_SET_SENTINEL = -1; | ||
|
||
@NonNull private WORK_ITEM[] sharedElems; | ||
// CAUTION: despite the "warning: @NonNull is meaningless on a primitive @lombok.RequiredArgsConstructor"... | ||
// if removed, no two-arg ctor is generated, so syntax error on `new CollectionSliceBackedTaskSpan(elems, startIndex)` | ||
@NonNull private int startingIndex; | ||
@NonNull private int numElements; | ||
private transient volatile int nextElemIndex = NOT_SET_SENTINEL; | ||
|
||
@Override | ||
public int getNumElems() { | ||
return getEndingIndex() - startingIndex; | ||
} | ||
|
||
@Override | ||
public boolean hasNext() { | ||
if (nextElemIndex == NOT_SET_SENTINEL) { | ||
nextElemIndex = startingIndex; // NOTE: `startingIndex` should be effectively `final` (post-deser) and always >= 0 | ||
} | ||
return nextElemIndex < this.getEndingIndex(); | ||
} | ||
|
||
@Override | ||
public WORK_ITEM next() { | ||
if (nextElemIndex >= startingIndex + numElements) { | ||
throw new NoSuchElementException("index " + nextElemIndex + " >= " + startingIndex + " + " + numElements); | ||
} | ||
return sharedElems[nextElemIndex++]; | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return getClassNickname() + "(" + startingIndex + "... {+" + getNumElems() + "})"; | ||
} | ||
|
||
protected String getClassNickname() { | ||
// return getClass().getSimpleName(); | ||
return "WorkSpan"; | ||
} | ||
|
||
@JsonIgnore // (because no-arg method resembles 'java bean property') | ||
protected final int getEndingIndex() { | ||
return Math.min(startingIndex + numElements, sharedElems.length); | ||
} | ||
} |
Oops, something went wrong.