Skip to content

Commit db0933b

Browse files
authored
[Refactor] OpenSearchException streamables to a registry (opensearch-project#7646)
* [Refactor] OpenSearchException streamables to a registry OpenSearchException uses an enumerator to create a handler for each serializable Exception implementation. The enumerator is to make it easy to store in an immutable map. The problem with this Hack is that it makes it difficult to unwind the tight coupling of StreamInput with the OpenSearchException class. This commit switches from using an enumerator to a registry in the opensearch-core library in order to support serverless and cloud native implementations outside of the server module. This commit also refactors base primitive serialization readers and writers from StreamInput and StreamOutput to BaseStreamInput and BaseStreamOutput, respectively. Signed-off-by: Nicholas Walter Knize <nknize@apache.org> * revert Project_Default Signed-off-by: Nicholas Walter Knize <nknize@apache.org> --------- Signed-off-by: Nicholas Walter Knize <nknize@apache.org>
1 parent c81668c commit db0933b

File tree

202 files changed

+2023
-1648
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

202 files changed

+2023
-1648
lines changed

.idea/inspectionProfiles/Project_Default.xml

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

libs/core/src/main/java/org/opensearch/BaseOpenSearchException.java

+98
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,10 @@
3131
*/
3232
package org.opensearch;
3333

34+
import org.opensearch.common.CheckedFunction;
3435
import org.opensearch.common.Nullable;
3536
import org.opensearch.core.common.Strings;
37+
import org.opensearch.core.common.io.stream.BaseStreamInput;
3638
import org.opensearch.core.common.logging.LoggerMessageFormat;
3739
import org.opensearch.core.xcontent.ToXContent;
3840
import org.opensearch.core.xcontent.ToXContentFragment;
@@ -41,10 +43,12 @@
4143

4244
import java.io.IOException;
4345
import java.util.Arrays;
46+
import java.util.Collection;
4447
import java.util.HashMap;
4548
import java.util.List;
4649
import java.util.Map;
4750
import java.util.Set;
51+
import java.util.concurrent.ConcurrentHashMap;
4852

4953
import static java.util.Collections.singletonMap;
5054

@@ -434,4 +438,98 @@ private String getShardIdString() {
434438
}
435439
return null;
436440
}
441+
442+
/**
443+
* An ExceptionHandle for registering Exceptions that can be serialized over the transport wire
444+
*
445+
* @opensearch.internal
446+
*/
447+
protected static abstract class BaseOpenSearchExceptionHandle {
448+
final Class<? extends BaseOpenSearchException> exceptionClass;
449+
final CheckedFunction<? extends BaseStreamInput, ? extends BaseOpenSearchException, IOException> constructor;
450+
final int id;
451+
final Version versionAdded;
452+
453+
<E extends BaseOpenSearchException, S extends BaseStreamInput> BaseOpenSearchExceptionHandle(
454+
Class<E> exceptionClass,
455+
CheckedFunction<S, E, IOException> constructor,
456+
int id,
457+
Version versionAdded
458+
) {
459+
// We need the exceptionClass because you can't dig it out of the constructor reliably.
460+
this.exceptionClass = exceptionClass;
461+
this.constructor = constructor;
462+
this.versionAdded = versionAdded;
463+
this.id = id;
464+
}
465+
}
466+
467+
@SuppressWarnings("unchecked")
468+
public static <T extends BaseStreamInput> BaseOpenSearchException readException(T input, int id) throws IOException {
469+
CheckedFunction<T, ? extends BaseOpenSearchException, IOException> opensearchException = (CheckedFunction<
470+
T,
471+
? extends BaseOpenSearchException,
472+
IOException>) OpenSearchExceptionHandleRegistry.getSupplier(id);
473+
if (opensearchException == null) {
474+
throw new IllegalStateException("unknown exception for id: " + id);
475+
}
476+
return opensearchException.apply(input);
477+
}
478+
479+
/**
480+
* Registry of ExceptionHandlers
481+
*
482+
* @opensearch.internal
483+
*/
484+
public static class OpenSearchExceptionHandleRegistry {
485+
/** Registry mapping from unique Ordinal to the Exception Constructor */
486+
private static final Map<
487+
Integer,
488+
CheckedFunction<? extends BaseStreamInput, ? extends BaseOpenSearchException, IOException>> ID_TO_SUPPLIER_REGISTRY =
489+
new ConcurrentHashMap<>();
490+
/** Registry mapping from Exception class to the Exception Handler */
491+
private static final Map<
492+
Class<? extends BaseOpenSearchException>,
493+
BaseOpenSearchExceptionHandle> CLASS_TO_OPENSEARCH_EXCEPTION_HANDLE_REGISTRY = new ConcurrentHashMap<>();
494+
495+
/** returns the Exception constructor function from a given ordinal */
496+
public static CheckedFunction<? extends BaseStreamInput, ? extends BaseOpenSearchException, IOException> getSupplier(final int id) {
497+
return ID_TO_SUPPLIER_REGISTRY.get(id);
498+
}
499+
500+
/** registers the Exception handler */
501+
public static void registerExceptionHandle(final BaseOpenSearchExceptionHandle handle) {
502+
ID_TO_SUPPLIER_REGISTRY.put(handle.id, handle.constructor);
503+
CLASS_TO_OPENSEARCH_EXCEPTION_HANDLE_REGISTRY.put(handle.exceptionClass, handle);
504+
}
505+
506+
/** Gets the unique ordinal id of the Exception from the given class */
507+
public static int getId(final Class<? extends BaseOpenSearchException> exception) {
508+
return CLASS_TO_OPENSEARCH_EXCEPTION_HANDLE_REGISTRY.get(exception).id;
509+
}
510+
511+
/** returns a set of ids */
512+
public static Set<Integer> ids() {
513+
return ID_TO_SUPPLIER_REGISTRY.keySet();
514+
}
515+
516+
/** returns a collection of handles */
517+
public static Collection<BaseOpenSearchExceptionHandle> handles() {
518+
return CLASS_TO_OPENSEARCH_EXCEPTION_HANDLE_REGISTRY.values();
519+
}
520+
521+
/** checks that the exception class is registered */
522+
public static boolean isRegistered(final Class<? extends Throwable> exception, final Version version) {
523+
BaseOpenSearchExceptionHandle openSearchExceptionHandle = CLASS_TO_OPENSEARCH_EXCEPTION_HANDLE_REGISTRY.get(exception);
524+
if (openSearchExceptionHandle != null) {
525+
return version.onOrAfter(openSearchExceptionHandle.versionAdded);
526+
}
527+
return false;
528+
}
529+
530+
/** returns a set of registered exception classes */
531+
public static Set<Class<? extends BaseOpenSearchException>> getRegisteredKeys() { // for testing
532+
return CLASS_TO_OPENSEARCH_EXCEPTION_HANDLE_REGISTRY.keySet();
533+
}
534+
}
437535
}

0 commit comments

Comments
 (0)