Skip to content

Commit

Permalink
javadocs
Browse files Browse the repository at this point in the history
  • Loading branch information
LakshSingla committed Jul 26, 2024
1 parent 98ea5bb commit c7351d7
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,11 @@ public static void writeObjectUsingSerializerProvider(
}
}

/**
* Reads an object using the {@link JsonParser}. It reuses the provided {@link DeserializationContext} which offers
* better performance that calling {@link JsonParser#readValueAs(Class)} because it avoids re-creating the {@link DeserializationContext}
* for each readValue call
*/
@Nullable
public static <T> T readObjectUsingDeserializationContext(
final JsonParser jp,
Expand All @@ -138,6 +143,9 @@ public static <T> T readObjectUsingDeserializationContext(
return deserializationContext.readValue(jp, clazz);
}

/**
* @see #readObjectUsingDeserializationContext(JsonParser, DeserializationContext, Class)
*/
@Nullable
public static Object readObjectUsingDeserializationContext(
final JsonParser jp,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,11 @@ public final JavaType getBySegmentResultType()
* For most queries, this is a no-op, but it can be useful for query types that support more than one result
* serialization format. Queries that implement this method must not modify the provided ObjectMapper, but instead
* must return a copy.
* <p>
* Jackson's default implementation of deserialization is usually optimised and this method should be overriden
* only if there is a functional requirement of so. The method must be benchmarked in isolation, without other portions
* of the query engine executing as modifying this method can alter the performance of queries where deserializing is
* a major portion of the execution.
*/
public ObjectMapper decorateObjectMapper(final ObjectMapper objectMapper, final QueryType query)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,20 @@
import java.io.IOException;
import java.util.List;

/**
* Utility class for conditional serde of {@link ResultRow} objects. Depending on the query configuration and the query
* dimensions, this class chooses an optimally performant method for serdeing the result rows while also preserving the
* dimension classes.
* Any modification this class must be benchmarked properly as it runs in a hot-loop and can have significant impact on
* long-running queries. See {@code GroupByDeserializationBenchmark} for existing benchmarks
*/
public class ResultRowObjectMapperDecoratorUtil
{
/**
* Decorates the provided object mapper so that it can read the result rows generated by the given query and the
* groupByQueryConfig. It never modifies the provided object mapper. It can either return the same mapper undecorated,
* or clones the object mapper before decorating it.
*/
public static ObjectMapper decorateObjectMapper(
final ObjectMapper baseObjectMapper,
final GroupByQuery query,
Expand Down Expand Up @@ -73,6 +85,10 @@ private GroupByResultRowModule()
return decoratedObjectMapper;
}

/**
* Returns a deserializer required to for the result rows of the provided query. It returns null if no special
* deserialization is required, and type-unaware generic java objects are sufficient.
*/
@Nullable
private static JsonDeserializer<ResultRow> getDeserializer(
final ObjectMapper objectMapper,
Expand All @@ -89,13 +105,14 @@ private static JsonDeserializer<ResultRow> getDeserializer(
dimensionSpec -> dimensionRequiresConversion(dimensionSpec.getOutputType())
);

// Most common case - when array based rows are used, and grouping is done on primitive/array/json types
if (arrayBasedRows && !dimensionsRequireConversion) {
// We can assume ResultRow are serialized and deserialized as arrays. No need for special decoration,
// and we can save the overhead of making a copy of the ObjectMapper
return null;
} else if (!arrayBasedRows && !dimensionsRequireConversion) {
// Have to deserialize map based rows, however don't have to deserialize the dimensions individually
// Deserializer that can deserialize either array- or map-based rows.
// We have to deserialize map based rows, however we don't have to deserialize the dimensions individually
// Returns a deserializer that can deserialize both map and array based rows simultaneously
return new JsonDeserializer<ResultRow>()
{
@Override
Expand All @@ -111,7 +128,7 @@ public ResultRow deserialize(final JsonParser jp, final DeserializationContext c
};

} else {
// Have to deserialize the dimensions carefully
// Dimensions need to be serialized individually because some of them require conversion to specialized types
return new JsonDeserializer<ResultRow>()
{
final JavaType[] javaTypes = createJavaTypesForResultRow(query);
Expand Down Expand Up @@ -158,6 +175,10 @@ public ResultRow deserialize(final JsonParser jp, final DeserializationContext c
}
}

/**
* Returns a legacy mode aware serialiazer that serializes the result rows as arrays or maps depending on the query
* configuration
*/
@Nullable
private static JsonSerializer<ResultRow> getSerializer(
final GroupByQuery query,
Expand Down Expand Up @@ -199,11 +220,21 @@ public void serialize(ResultRow resultRow, JsonGenerator jsonGenerator, Serializ
}
}

/**
* Returns true if the dimension needs to be converted from generic Java objects to the specialized column type. It involves all
* complex types, except for JSON types. JSON types are special in a way that they can work with the generic java objects
* without any conversion
*/
private static boolean dimensionRequiresConversion(final ColumnType dimensionType)
{
return dimensionType.is(ValueType.COMPLEX) && !ColumnType.NESTED_DATA.equals(dimensionType);
}

/**
* Creates java types for deserializing the result row. For timestamp, aggregators and post-aggregators, it resorts to
* {@link Object.class}. For dimensions requiring conversion (check {@link #dimensionRequiresConversion(ColumnType)}),
* it returns the java type for the associated class of the complex object.
*/
private static JavaType[] createJavaTypesForResultRow(final GroupByQuery groupByQuery)
{
final TypeFactory typeFactory = TypeFactory.defaultInstance();
Expand Down

0 comments on commit c7351d7

Please sign in to comment.