Skip to content

Commit

Permalink
closes #305: reorganize and document config options (#331)
Browse files Browse the repository at this point in the history
  • Loading branch information
Ivan Senic authored Apr 17, 2023
1 parent c841b16 commit 9b48a95
Show file tree
Hide file tree
Showing 30 changed files with 274 additions and 223 deletions.
29 changes: 24 additions & 5 deletions CONFIGURATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,28 @@ Here are some Stargate-relevant property groups that are necessary for correct s
* `quarkus.grpc.clients.bridge` - property group for defining the Bridge gRPC client (see [gRPC Client configuration](https://quarkus.io/guides/grpc-service-consumption#client-configuration) for all options)
* `quarkus.cache.caffeine.keyspace-cache` - property group for defining the keyspace cache used by [SchemaManager](../sgv2-quarkus-common/src/main/java/io/stargate/sgv2/api/common/schema/SchemaManager.java) (see [Caffeine cache configuration](https://quarkus.io/guides/cache#caffeine-configuration-properties) for all options)

## Document configuration
*Configuration for documents and their storage properties, defined by [DocumentConfig.java](src/main/java/io/stargate/sgv2/jsonapi/service/bridge/config/DocumentConfig.java).*

| Property | Type | Default | Description |
|-------------------------------------------------|----------|--------------|--------------------------------------------------------------------|
| `stargate.document.page-size` | `int` | `20` | The maximum page size when reading documents. |
## Document limits configuration
*Configuration for document limits, defined by [DocumentLimitsConfig.java](src/main/java/io/stargate/sgv2/jsonapi/config/DocumentLimitsConfig.java).*

| Property | Type | Default | Description |
|-------------------------------------------------------------|-------|-------------|-------------------------------------------------------------------------------------------------------------|
| `stargate.jsonapi.document.limits.max-size` | `int` | `1_000_000` | The maximum size of a single document in characters. Defaults to 1 million characters or approximately 1MB. |
| `stargate.jsonapi.document.limits.max-depth` | `int` | `8` | The maximum document depth (nesting). |
| `stargate.jsonapi.document.limits.max-property-name-length` | `int` | `48` | The maximum length of property names in a document for an individual segment. |
| `stargate.jsonapi.document.limits.max-object-properties` | `int` | `64` | The maximum number of properties any single object in a document can contain. |
| `stargate.jsonapi.document.limits.max-string-length` | `int` | `16_000` | The maximum length of a single string value in a document. |
| `stargate.jsonapi.document.limits.max-array-length` | `int` | `100` | The maximum length of a single array in a document. |

## Operations configuration
*Configuration for the operation execution, defined by [OperationsConfig.java](src/main/java/io/stargate/sgv2/jsonapi/config/OperationsConfig.java).*

| Property | Type | Default | Description |
|---------------------------------------------------------|-------|----------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `stargate.jsonapi.operations.default-page-size` | `int` | `20` | The default Cassandra page size used for read queries. |
| `stargate.jsonapi.operations.default-sort-page-size` | `int` | `100` | The default Cassandra page size used for read queries that are used for sorting purposes. |
| `stargate.jsonapi.operations.max-document-sort-count` | `int` | `10_000` | The maximum amount of documents that could be sorted using the in-memory sorting. The request will fail in case in-memory sorting would break the limit. |
| `stargate.jsonapi.operations.max-document-insert-count` | `int` | `20` | The maximum amount of documents that can be inserted in a single operation. The request will fail fast without inserts if the limit is broken. |
| `stargate.jsonapi.operations.max-document-update-count` | `int` | `20` | The maximum amount of documents that can be updated in a single operation. In case there are more documents that could be updated, the operation will set the `moreData` response status to `true`. |
| `stargate.jsonapi.operations.max-document-delete-count` | `int` | `20` | The maximum amount of documents that can be deleted in a single operation. In case there are more documents that could be deleted, the operation will set the `moreData` response status to `true`. |
| `stargate.jsonapi.operations.lwt.retries` | `int` | `3` | The amount of client side retries in case of a LWT failure. |
39 changes: 35 additions & 4 deletions docs/jsonapi-spec.md
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,9 @@ JSON documents must adhere to the following limits. Attempting to insert
or modify a document beyond these limits will result in the command
failing.

> Note that all limits are configurable using run-time properties.
> See the [Document limits configuration](./../CONFIGURATION.md#document-limits-configuration) for further info.
#### Document Size Limit

The maximum size of a single document is 1 megabyte. The size is
Expand All @@ -390,10 +393,10 @@ The maximum number of fields allowed in a single JSON object is 64.

The maximum size of field values are:

| JSON Type | Maximum Value |
| ----------- | ------------------------------------------------------- |
| `string` | Maximum length of 16384 unicode characters |
| `number` | TODO: define max num that is well handled by BigDecimal |
| JSON Type | Maximum Value |
|-----------|---------------------------------------------------------|
| `string` | Maximum length of 16,000 unicode characters |
| `number` | TODO: define max num that is well handled by BigDecimal |


#### Document Array Limits
Expand Down Expand Up @@ -548,6 +551,10 @@ Fail Silently, a storage failure does not stop the command from processing.

See [Multi-Document Failure Considerations](#multi-document-failure-considerations).

#### deleteMany Command Limits

The maximum amount of documents that can be deleted in a single operation is 20. This limit is configurable using the [Operations configuration properties](./../CONFIGURATION.md#operations-configuration).

#### deleteMany Command Response

| Response Elements | Description |
Expand Down Expand Up @@ -652,6 +659,10 @@ Fail Fast, a storage failure causes the command to stop processing.

See [Multi-Document Failure Considerations](#multi-document-failure-considerations).

#### find Command Limits

If `<sort-clause>` is present, the maximum amount of documents that could be sorted using the in-memory sorting is 10,000. This limit is configurable using the [Operations configuration properties](./../CONFIGURATION.md#operations-configuration).

#### find Command Response

| Response Elements | Description |
Expand Down Expand Up @@ -750,6 +761,10 @@ If the replacement document `_id` field is different from the document read from
NOTE: you can omit `_id` in the replacement document. If `_id` is in the replacement, it should be exactly equal to the `_id` in the database. But if `_id` was omitted,
`findOneAndReplace` will use the existing document's `_id`.

#### findOneAndReplace Command Limits

If `<sort-clause>` is present, the maximum amount of documents that could be sorted using the in-memory sorting is 10,000. This limit is configurable using the [Operations configuration properties](./../CONFIGURATION.md#operations-configuration).

#### findOneAndReplace Command Response

| Response Elements | Description |
Expand Down Expand Up @@ -821,6 +836,10 @@ Fail Fast, a storage failure causes the command to stop processing.

See [Multi-Document Failure Considerations](#multi-document-failure-considerations).

#### findOneAndUpdate Command Limits

If `<sort-clause>` is present, the maximum amount of documents that could be sorted using the in-memory sorting is 10,000. This limit is configurable using the [Operations configuration properties](./../CONFIGURATION.md#operations-configuration).

#### findOneAndUpdate Command Response

| Response Elements | Description |
Expand All @@ -846,6 +865,10 @@ Fail Fast, a storage failure causes the command to stop processing.

See [Multi-Document Failure Considerations](#multi-document-failure-considerations).

#### findOne Command Limits

If `<sort-clause>` is present, the maximum amount of documents that could be sorted using the in-memory sorting is 10,000. This limit is configurable using the [Operations configuration properties](./../CONFIGURATION.md#operations-configuration).

#### findOne Command Response

| Response Element | Description |
Expand Down Expand Up @@ -875,6 +898,10 @@ See [insertMany Command Options](#insertMany-command-options) for `ordered`.

See [Multi-Document Failure Considerations](#multi-document-failure-considerations).

#### insertMany Command Limits

The maximum amount of documents that can be inserted in a single operation is 20. This limit is configurable using the [Operations configuration properties](./../CONFIGURATION.md#operations-configuration).

#### insertMany Command Response

| Response Element | Description |
Expand Down Expand Up @@ -926,6 +953,10 @@ Fail Silently, a storage failure does not stop the command from processing.

See [Multi-Document Failure Considerations](#multi-document-failure-considerations).

#### updateMany Command Limits

The maximum amount of documents that can be updated in a single operation is 20. This limit is configurable using the [Operations configuration properties](./../CONFIGURATION.md#operations-configuration).

#### updateMany Command Response

| Response Element | Description |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@
import io.stargate.sgv2.jsonapi.api.model.command.clause.filter.FilterOperation;
import io.stargate.sgv2.jsonapi.api.model.command.clause.filter.FilterOperator;
import io.stargate.sgv2.jsonapi.api.model.command.clause.filter.ValueComparisonOperator;
import io.stargate.sgv2.jsonapi.config.OperationsConfig;
import io.stargate.sgv2.jsonapi.config.constants.DocumentConstants;
import io.stargate.sgv2.jsonapi.exception.ErrorCode;
import io.stargate.sgv2.jsonapi.exception.JsonApiException;
import io.stargate.sgv2.jsonapi.service.bridge.config.DocumentConfig;
import io.stargate.sgv2.jsonapi.service.shredding.model.DocumentId;
import java.io.IOException;
import java.math.BigDecimal;
Expand All @@ -32,12 +32,12 @@

/** {@link StdDeserializer} for the {@link FilterClause}. */
public class FilterClauseDeserializer extends StdDeserializer<FilterClause> {
private DocumentConfig documentConfig;
private final OperationsConfig operationsConfig;

public FilterClauseDeserializer() {
super(FilterClause.class);
SmallRyeConfig config = ConfigProvider.getConfig().unwrap(SmallRyeConfig.class);
documentConfig = config.getConfigMapping(DocumentConfig.class);
operationsConfig = config.getConfigMapping(OperationsConfig.class);
}

/**
Expand Down Expand Up @@ -90,10 +90,12 @@ private void validate(String path, FilterOperation<?> filterOperation) {
throw new JsonApiException(
ErrorCode.INVALID_FILTER_EXPRESSION, "$in operator must have at least one value");
}
if (list.size() > documentConfig.defaultPageSize()) {
if (list.size() > operationsConfig.defaultPageSize()) {
throw new JsonApiException(
ErrorCode.INVALID_FILTER_EXPRESSION,
"$in operator must have at most " + documentConfig.defaultPageSize() + " values");
"$in operator must have at most "
+ operationsConfig.defaultPageSize()
+ " values");
}
} else {
throw new JsonApiException(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
package io.stargate.sgv2.jsonapi.api.model.command.validation;

import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.ElementType.CONSTRUCTOR;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.ElementType.TYPE_USE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import io.stargate.sgv2.jsonapi.config.DocumentLimitsConfig;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,29 +1,27 @@
package io.stargate.sgv2.jsonapi.api.model.command.validation;

import com.fasterxml.jackson.databind.JsonNode;
import io.stargate.sgv2.jsonapi.config.OperationsConfig;
import java.util.List;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.inject.Instance;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import org.eclipse.microprofile.config.inject.ConfigProperty;

/** Validator for the {@link MaxInsertManyDocuments} annotation. */
@ApplicationScoped
public class MaxInsertManyDocumentsValidation
implements ConstraintValidator<MaxInsertManyDocuments, List<JsonNode>> {

private final int limit;
private final Instance<OperationsConfig> config;

// due to https://github.com/quarkusio/quarkus/issues/32265
// I can only inject prop, not the whole config class
public MaxInsertManyDocumentsValidation(
@ConfigProperty(name = "stargate.jsonapi.doc-limits.max-insert-many-documents") int limit) {
this.limit = limit;
public MaxInsertManyDocumentsValidation(Instance<OperationsConfig> config) {
this.config = config;
}

/** {@inheritDoc} */
@Override
public boolean isValid(List<JsonNode> value, ConstraintValidatorContext context) {
return null != value && value.size() <= limit;
return null != value && value.size() <= config.get().maxDocumentInsertCount();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,28 +5,28 @@
import javax.validation.constraints.Positive;

/** Configuration Object that defines limits on Documents managed by JSON API. */
@ConfigMapping(prefix = "stargate.jsonapi.doc-limits")
@ConfigMapping(prefix = "stargate.jsonapi.document.limits")
public interface DocumentLimitsConfig {
/**
* @return Defines the maximum document page size, defaults to {@code 1 meg} (1 million
* characters).
*/
@Positive
@WithDefault("1000000")
int maxDocSize();
int maxSize();

/** @return Defines the maximum document depth (nesting), defaults to {@code 8 levels} */
@Positive
@WithDefault("8")
int maxDocDepth();
int maxDepth();

/**
* @return Defines the maximum length of property names in JSON documents, defaults to {@code 48
* characters} (note: length is for individual name segments; full dotted names can be longer)
*/
@Positive
@WithDefault("48")
int maxNameLength();
int maxPropertyNameLength();

/**
* @return Defines the maximum number of properties any single Object in JSON document can
Expand All @@ -46,11 +46,4 @@ public interface DocumentLimitsConfig {
@Positive
@WithDefault("100")
int maxArrayLength();

/**
* @return Maximum amount of documents that can be inserted using <code>insertMany</code> command.
*/
// keep in sync with MaxInsertManyDocumentsValidation
@Positive
int maxInsertManyDocuments();
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,18 @@
*
*/

package io.stargate.sgv2.jsonapi.service.bridge.config;
package io.stargate.sgv2.jsonapi.config;

import io.smallrye.config.ConfigMapping;
import io.smallrye.config.WithDefault;
import javax.validation.Valid;
import javax.validation.constraints.Max;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Positive;

/** Configuration for the documents. */
@ConfigMapping(prefix = "stargate.document")
public interface DocumentConfig {
/** Configuration for the operation execution. */
@ConfigMapping(prefix = "stargate.jsonapi.operations")
public interface OperationsConfig {

/** @return Defines the default document page size, defaults to <code>20</code>. */
@Max(500)
Expand All @@ -41,23 +43,14 @@ public interface DocumentConfig {
@WithDefault("100")
int defaultSortPageSize();

/**
* @return Defines the maximum limit of document that can be returned for a request, defaults to
* <code>1000</code>.
*/
@Max(Integer.MAX_VALUE)
@Positive
@WithDefault("1000")
int maxLimit();

/**
* @return Defines the maximum limit of document read to perform in memory sorting <code>10000
* </code>.
*/
@Max(10000)
@Positive
@WithDefault("10000")
int maxSortReadLimit();
int maxDocumentSortCount();

/**
* @return Defines the maximum limit of document that can be deleted for a request, defaults to
Expand All @@ -77,10 +70,21 @@ public interface DocumentConfig {
@WithDefault("20")
int maxDocumentUpdateCount();

/** {@inheritDoc} */
/**
* @return Maximum amount of documents that can be inserted using <code>insertMany</code> command.
*/
@Max(100)
@Positive
@WithDefault("20")
int maxDocumentInsertCount();

@NotNull
@Valid
LwtConfig lwt();

/** Configuration setup for the Light-weight transactions. */
interface LwtConfig {

/** @return Defines the maximum retry for lwt failure <code>3</code>. */
@Max(5)
@Positive
Expand Down
Loading

0 comments on commit 9b48a95

Please sign in to comment.