From a8977a4ab703322745fbaac5b79602dab704094c Mon Sep 17 00:00:00 2001 From: Tatu Saloranta Date: Thu, 2 Nov 2023 14:31:20 -0700 Subject: [PATCH 1/7] DRAFT: try to merge changes from `main` to `native_cql_changes` -- 1 conflict left --- CHANGELOG.md | 152 +++++++++++++++++- CONFIGURATION.md | 6 + README.md | 2 +- docker-compose/.env | 2 +- docs/jsonapi-network-spec.md | 2 +- fallout/dataset-test-nosqlbench.yaml | 24 +-- fallout/smoke-test-nosqlbench.yaml | 28 ++-- fallout/vector-insertmany-nosqlbench.yaml | 6 +- fallout/vector-test-nosqlbench.yaml | 16 +- nosqlbench/http-jsonapi-crud-basic.yaml | 14 +- nosqlbench/http-jsonapi-crud-dataset.yaml | 24 +-- nosqlbench/http-jsonapi-keyvalue.yaml | 12 +- nosqlbench/http-jsonapi-search-advanced.yaml | 34 ++-- nosqlbench/http-jsonapi-search-basic.yaml | 4 +- .../http-jsonapi-search-filter-sort.yaml | 8 +- nosqlbench/http-jsonapi-vector-crud.yaml | 18 +-- .../http-jsonapi-vector-insertmany.yaml | 8 +- pom.xml | 8 +- src/main/docker/Dockerfile.jvm | 4 +- .../stargate/sgv2/jsonapi/JsonApiStartUp.java | 6 +- .../sgv2/jsonapi/StargateJsonApi.java | 6 +- .../ConstraintViolationExceptionMapper.java | 5 +- .../jsonapi/api/model/command/Command.java | 4 +- .../api/model/command/CommandResult.java | 1 + ...mmands.java => CountDocumentsCommand.java} | 2 +- .../command/impl/CreateCollectionCommand.java | 20 ++- .../model/command/impl/InsertManyCommand.java | 2 +- .../api/security/ErrorChallengeSender.java | 13 +- .../jsonapi/api/v1/CollectionResource.java | 4 +- .../sgv2/jsonapi/api/v1/TokenFilter.java | 32 ++++ .../jsonapi/config/DatabaseLimitsConfig.java | 39 +++++ .../sgv2/jsonapi/config/DebugModeConfig.java | 11 ++ .../jsonapi/config/DocumentLimitsConfig.java | 13 ++ .../config/constants/HttpConstants.java | 10 ++ .../sgv2/jsonapi/exception/ErrorCode.java | 6 +- .../jsonapi/exception/JsonApiException.java | 18 ++- .../mappers/ThrowableToErrorMapper.java | 36 ++++- .../bridge/executor/NamespaceCache.java | 21 ++- .../model/impl/CreateCollectionOperation.java | 35 +++- .../processor/MeteredCommandProcessor.java | 11 +- .../impl/CountDocumentsCommandResolver.java | 14 +- .../impl/CreateCollectionCommandResolver.java | 15 +- .../impl/matcher/FilterableResolver.java | 14 +- src/main/resources/application.yaml | 11 ++ .../ObjectMapperConfigurationTest.java | 57 +++++-- .../serializers/ErrorSerializerTest.java | 16 +- ...AbstractCollectionIntegrationTestBase.java | 2 +- .../AbstractNamespaceIntegrationTestBase.java | 8 +- .../v1/CollectionResourceIntegrationTest.java | 4 +- .../jsonapi/api/v1/CountIntegrationTest.java | 4 +- .../v1/CreateCollectionIntegrationTest.java | 72 ++++++++- .../v1/CreateNamespaceIntegrationTest.java | 2 +- .../v1/DeleteCollectionIntegrationTest.java | 2 +- .../api/v1/DeleteManyIntegrationTest.java | 2 +- .../api/v1/DeleteOneIntegrationTest.java | 2 +- .../api/v1/DropNamespaceIntegrationTest.java | 3 +- .../v1/FindCollectionsIntegrationTest.java | 10 +- .../jsonapi/api/v1/FindIntegrationTest.java | 56 ++++++- .../api/v1/FindNamespacesIntegrationTest.java | 2 +- .../v1/FindOneAndDeleteIntegrationTest.java | 2 +- .../v1/FindOneAndReplaceIntegrationTest.java | 2 +- .../v1/FindOneAndUpdateIntegrationTest.java | 2 +- .../api/v1/FindOneIntegrationTest.java | 2 +- .../FindOneWithProjectionIntegrationTest.java | 2 +- .../FindOperationWithSortIntegrationTest.java | 2 +- .../v1/GeneralResourceIntegrationTest.java | 4 +- .../api/v1/HttpStatusCodeIntegrationTest.java | 30 +++- .../jsonapi/api/v1/InsertIntegrationTest.java | 2 +- .../api/v1/LwtRetryIntegrationTest.java | 2 +- .../v1/NamespaceResourceIntegrationTest.java | 4 +- .../api/v1/UpdateManyIntegrationTest.java | 2 +- .../api/v1/UpdateOneIntegrationTest.java | 2 +- .../api/v1/VectorSearchIntegrationTest.java | 16 +- .../v1/VectorizeSearchIntegrationTest.java | 6 +- .../CommandResultToRestResponseTest.java | 21 ++- .../exception/JsonApiExceptionTest.java | 5 + .../ThrowableCommandResultSupplierTest.java | 5 + .../impl/CreateCollectionOperationTest.java | 21 ++- .../MeteredCommandProcessorTest.java | 22 +-- .../model/impl/CountCommandResolverTest.java | 8 +- .../CountDocumentsCommandResolverTest.java | 6 +- .../CreateCollectionCommandResolverTest.java | 10 +- ...eCollectionResolverVectorDisabledTest.java | 4 +- .../jsonapi/testresource/DseTestResource.java | 3 +- src/test/resources/application.yaml | 2 + 85 files changed, 882 insertions(+), 268 deletions(-) rename src/main/java/io/stargate/sgv2/jsonapi/api/model/command/impl/{CountDocumentsCommands.java => CountDocumentsCommand.java} (88%) create mode 100644 src/main/java/io/stargate/sgv2/jsonapi/api/v1/TokenFilter.java create mode 100644 src/main/java/io/stargate/sgv2/jsonapi/config/DatabaseLimitsConfig.java create mode 100644 src/main/java/io/stargate/sgv2/jsonapi/config/DebugModeConfig.java create mode 100644 src/main/java/io/stargate/sgv2/jsonapi/config/constants/HttpConstants.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 179f9742a3..30b8148e55 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,158 @@ -[Full Changelog](https://github.com/stargate/jsonapi/compare/v1.0.0-ALPHA-13...HEAD) +# Changelog + +## [Unreleased](https://github.com/stargate/jsonapi/tree/HEAD) + +[Full Changelog](https://github.com/stargate/jsonapi/compare/v1.0.0-BETA-3...HEAD) + +**Closed issues:** + +- Replace `X-Cassandra-Token` with `Token` [\#569](https://github.com/stargate/jsonapi/issues/569) + +## [v1.0.0-BETA-3](https://github.com/stargate/jsonapi/tree/v1.0.0-BETA-3) (2023-11-02) + +[Full Changelog](https://github.com/stargate/jsonapi/compare/v1.0.0-BETA-2...v1.0.0-BETA-3) + +**Implemented enhancements:** + +- Improve JSON API error messages with more informative help and \(where possible\) suggested user action [\#552](https://github.com/stargate/jsonapi/issues/552) + +**Fixed bugs:** + +- UNAUTHENTICATED: Invalid token msg is override because of Metrics tag exception [\#603](https://github.com/stargate/jsonapi/issues/603) + +**Closed issues:** + +- Misleading error message on nonexisting table when implying vector-enabled [\#609](https://github.com/stargate/jsonapi/issues/609) +- Remove extra trailing white space from text aggregated for text search [\#602](https://github.com/stargate/jsonapi/issues/602) +- Native Image build failure [\#597](https://github.com/stargate/jsonapi/issues/597) +- ExceptionClass exposure in error message [\#578](https://github.com/stargate/jsonapi/issues/578) +- Enforce limit of maximum 5 Collections per ---database--- namespace [\#577](https://github.com/stargate/jsonapi/issues/577) +- Fully rely on List\\> for build where clause [\#543](https://github.com/stargate/jsonapi/issues/543) +- SPEC - Document using $slice in projections [\#130](https://github.com/stargate/jsonapi/issues/130) + +**Merged pull requests:** + +- fix collection not exist [\#612](https://github.com/stargate/jsonapi/pull/612) ([Yuqi-Du](https://github.com/Yuqi-Du)) +- \Revert "fix collection not exist" \(accidental push to main\) [\#611](https://github.com/stargate/jsonapi/pull/611) ([tatu-at-datastax](https://github.com/tatu-at-datastax)) +- token header name "X-Casssandra-Token" -\> "Token" [\#607](https://github.com/stargate/jsonapi/pull/607) ([Yuqi-Du](https://github.com/Yuqi-Du)) +- fix error mapping [\#604](https://github.com/stargate/jsonapi/pull/604) ([Yuqi-Du](https://github.com/Yuqi-Du)) +- ensure JVM heap memory settings applied in Java-based image [\#599](https://github.com/stargate/jsonapi/pull/599) ([jeffreyscarpenter](https://github.com/jeffreyscarpenter)) +- Fix native image building with datastax driver dependency [\#598](https://github.com/stargate/jsonapi/pull/598) ([kathirsvn](https://github.com/kathirsvn)) +- Verify max 5 collections creation \(per namespace\) [\#595](https://github.com/stargate/jsonapi/pull/595) ([tatu-at-datastax](https://github.com/tatu-at-datastax)) +- Update dse-next reference for ITs to latest one as well [\#592](https://github.com/stargate/jsonapi/pull/592) ([tatu-at-datastax](https://github.com/tatu-at-datastax)) +- provide additional detail on swagger docs for insertMany [\#591](https://github.com/stargate/jsonapi/pull/591) ([jeffreyscarpenter](https://github.com/jeffreyscarpenter)) +- Bumping version for next jsonapi release [\#590](https://github.com/stargate/jsonapi/pull/590) ([github-actions[bot]](https://github.com/apps/github-actions)) +- expose ExceptionClass only in debug mode [\#584](https://github.com/stargate/jsonapi/pull/584) ([Yuqi-Du](https://github.com/Yuqi-Du)) + +## [v1.0.0-BETA-2](https://github.com/stargate/jsonapi/tree/v1.0.0-BETA-2) (2023-10-24) + +[Full Changelog](https://github.com/stargate/jsonapi/compare/v1.0.0-BETA-1...v1.0.0-BETA-2) + +**Fixed bugs:** + +- Performance tests returning bad status code errors [\#422](https://github.com/stargate/jsonapi/issues/422) + +**Closed issues:** + +- CountDocumentsCommands should be CountDocumentsCommand [\#583](https://github.com/stargate/jsonapi/issues/583) +- Add `isEmpty\(\)` method in `JsonFieldExtractor` [\#579](https://github.com/stargate/jsonapi/issues/579) +- Add validation of path expression configuration for Field Extractor \(in `json-api-analyzer-filter`\) [\#574](https://github.com/stargate/jsonapi/issues/574) +- Allow passing of empty JSON Object \(`{ }`\) for `sort` for `find` and `findOne` Commands [\#572](https://github.com/stargate/jsonapi/issues/572) +- Vector options name change [\#567](https://github.com/stargate/jsonapi/issues/567) +- Add simple micro-benchmarking of Field Extractor for `json-api-analyzer-filter` [\#564](https://github.com/stargate/jsonapi/issues/564) +- Add ability to "JSON detect" input given to Field Extractor [\#563](https://github.com/stargate/jsonapi/issues/563) +- includeSimilarity option doesn't seem to work with `findOne\(\)` [\#558](https://github.com/stargate/jsonapi/issues/558) +- Implement efficient JSON document filtering to be used by "JSON analyzer" for $text indexing [\#554](https://github.com/stargate/jsonapi/issues/554) +- Provide a way to display collection options [\#550](https://github.com/stargate/jsonapi/issues/550) +- Limit number of filtering fields in find commands [\#548](https://github.com/stargate/jsonapi/issues/548) +- support $and, $or [\#547](https://github.com/stargate/jsonapi/issues/547) +- Handling of createCollection command [\#546](https://github.com/stargate/jsonapi/issues/546) +- Json api messaging if namespace is not found. [\#545](https://github.com/stargate/jsonapi/issues/545) +- Add NoSQLBench test for insertMany [\#541](https://github.com/stargate/jsonapi/issues/541) +- revisit jsonapi native image build and publish process [\#494](https://github.com/stargate/jsonapi/issues/494) +- Limit number of documents to count [\#431](https://github.com/stargate/jsonapi/issues/431) +- Decide on system and non-jsonapi namespace handling [\#341](https://github.com/stargate/jsonapi/issues/341) +- Implement `$in` support [\#291](https://github.com/stargate/jsonapi/issues/291) + +**Merged pull requests:** + +- Update to latest dse-db-all [\#587](https://github.com/stargate/jsonapi/pull/587) ([tatu-at-datastax](https://github.com/tatu-at-datastax)) +- typo fix: CountDocumentsCommands -\> CountDocumentsCommand [\#585](https://github.com/stargate/jsonapi/pull/585) ([Yuqi-Du](https://github.com/Yuqi-Du)) +- Update Jackson to latest release, 2.15.3 [\#580](https://github.com/stargate/jsonapi/pull/580) ([tatu-at-datastax](https://github.com/tatu-at-datastax)) +- Fix \#572: add ITs to verify empty JSON Object is valid for `sort` of `find`/`findOne`, fix as necessary [\#576](https://github.com/stargate/jsonapi/pull/576) ([tatu-at-datastax](https://github.com/tatu-at-datastax)) +- Changes for create collection option names [\#575](https://github.com/stargate/jsonapi/pull/575) ([maheshrajamani](https://github.com/maheshrajamani)) +- Use Stargate v2.1.0-BETA-2 [\#573](https://github.com/stargate/jsonapi/pull/573) ([github-actions[bot]](https://github.com/apps/github-actions)) +- Limit number of filtering fields in find commands [\#570](https://github.com/stargate/jsonapi/pull/570) ([Hazel-Datastax](https://github.com/Hazel-Datastax)) +- fix changelog [\#568](https://github.com/stargate/jsonapi/pull/568) ([Yuqi-Du](https://github.com/Yuqi-Du)) +- Add error message in createCollection\(\) [\#566](https://github.com/stargate/jsonapi/pull/566) ([Hazel-Datastax](https://github.com/Hazel-Datastax)) +- Support and or [\#565](https://github.com/stargate/jsonapi/pull/565) ([Yuqi-Du](https://github.com/Yuqi-Du)) +- Vertex AI embedding client fix [\#561](https://github.com/stargate/jsonapi/pull/561) ([maheshrajamani](https://github.com/maheshrajamani)) +- Return create collection options as part of findCollections response [\#559](https://github.com/stargate/jsonapi/pull/559) ([maheshrajamani](https://github.com/maheshrajamani)) +- Handle error when the namespace doesn't exist [\#557](https://github.com/stargate/jsonapi/pull/557) ([Hazel-Datastax](https://github.com/Hazel-Datastax)) +- Update `dse-next` dependency to latest \(4.0.11-669ae5e3994d\) [\#556](https://github.com/stargate/jsonapi/pull/556) ([tatu-at-datastax](https://github.com/tatu-at-datastax)) +- Add NosqlBench insertmany test [\#555](https://github.com/stargate/jsonapi/pull/555) ([Hazel-Datastax](https://github.com/Hazel-Datastax)) +- update base image to smaller runtime version [\#553](https://github.com/stargate/jsonapi/pull/553) ([jeffreyscarpenter](https://github.com/jeffreyscarpenter)) +- Use Stargate v2.1.0-BETA-1 [\#551](https://github.com/stargate/jsonapi/pull/551) ([github-actions[bot]](https://github.com/apps/github-actions)) +- Update Docker base images to address Python vuln/CVE [\#549](https://github.com/stargate/jsonapi/pull/549) ([tatu-at-datastax](https://github.com/tatu-at-datastax)) +- Bumping version for next jsonapi release [\#544](https://github.com/stargate/jsonapi/pull/544) ([github-actions[bot]](https://github.com/apps/github-actions)) + +## [v1.0.0-BETA-1](https://github.com/stargate/jsonapi/tree/v1.0.0-BETA-1) (2023-09-27) + +[Full Changelog](https://github.com/stargate/jsonapi/compare/v1.0.0-ALPHA-14...v1.0.0-BETA-1) + +**Closed issues:** + +- \[Vectorize\] Make vectorize\(\) method call run on worker thread [\#537](https://github.com/stargate/jsonapi/issues/537) +- \[Vectorize\] Add validation for update clause [\#533](https://github.com/stargate/jsonapi/issues/533) +- \[Vectorize\] Remove $vectorize field in the document [\#532](https://github.com/stargate/jsonapi/issues/532) +- Add metrics tagging for vector functionality [\#526](https://github.com/stargate/jsonapi/issues/526) +- \[Vectorize\] Implement embedding service call [\#524](https://github.com/stargate/jsonapi/issues/524) +- pricing investigation for JSON API [\#523](https://github.com/stargate/jsonapi/issues/523) +- JSON API should allow hyphens \(`-`\) in document property names \(but should not allow empty String\) [\#521](https://github.com/stargate/jsonapi/issues/521) +- findOneAndDelete by vector has NPE issue in concurrent situation [\#517](https://github.com/stargate/jsonapi/issues/517) +- findOne filtering by `$vector` returns no results [\#516](https://github.com/stargate/jsonapi/issues/516) +- User-friendly notification of unsupported features [\#389](https://github.com/stargate/jsonapi/issues/389) + +**Merged pull requests:** + +- Vectorize update validation [\#542](https://github.com/stargate/jsonapi/pull/542) ([maheshrajamani](https://github.com/maheshrajamani)) +- Run operation resolver on worker thread [\#540](https://github.com/stargate/jsonapi/pull/540) ([maheshrajamani](https://github.com/maheshrajamani)) +- Add metrics for sort type and vector enabled [\#539](https://github.com/stargate/jsonapi/pull/539) ([maheshrajamani](https://github.com/maheshrajamani)) +- ensure password is masked on ecr login [\#538](https://github.com/stargate/jsonapi/pull/538) ([jeffreyscarpenter](https://github.com/jeffreyscarpenter)) +- Use Stargate v2.1.0-ALPHA-11 [\#536](https://github.com/stargate/jsonapi/pull/536) ([github-actions[bot]](https://github.com/apps/github-actions)) +- In support [\#535](https://github.com/stargate/jsonapi/pull/535) ([Yuqi-Du](https://github.com/Yuqi-Du)) +- Update dse-db-all dependency to latest \(same as Stargate\) [\#534](https://github.com/stargate/jsonapi/pull/534) ([tatu-at-datastax](https://github.com/tatu-at-datastax)) +- Fix update vector [\#531](https://github.com/stargate/jsonapi/pull/531) ([maheshrajamani](https://github.com/maheshrajamani)) +- update to beta [\#530](https://github.com/stargate/jsonapi/pull/530) ([jeffreyscarpenter](https://github.com/jeffreyscarpenter)) +- Fixed JSON API Documentation url [\#529](https://github.com/stargate/jsonapi/pull/529) ([kathirsvn](https://github.com/kathirsvn)) +- Add embedding support api [\#528](https://github.com/stargate/jsonapi/pull/528) ([maheshrajamani](https://github.com/maheshrajamani)) +- Use Stargate v2.1.0-ALPHA-10 [\#527](https://github.com/stargate/jsonapi/pull/527) ([github-actions[bot]](https://github.com/apps/github-actions)) +- Fix \#521: allow hyphen in names, prevent empty String [\#522](https://github.com/stargate/jsonapi/pull/522) ([tatu-at-datastax](https://github.com/tatu-at-datastax)) +- Use Stargate v2.1.0-ALPHA-9 [\#520](https://github.com/stargate/jsonapi/pull/520) ([github-actions[bot]](https://github.com/apps/github-actions)) +- Fixes \#516: add validation to fail on attempts to filter on $vector \(except with $exists\) [\#519](https://github.com/stargate/jsonapi/pull/519) ([tatu-at-datastax](https://github.com/tatu-at-datastax)) +- fix NPE when concurrent delete [\#518](https://github.com/stargate/jsonapi/pull/518) ([Yuqi-Du](https://github.com/Yuqi-Du)) +- add fallout configuration and fallout nosqlbench workload [\#515](https://github.com/stargate/jsonapi/pull/515) ([Yuqi-Du](https://github.com/Yuqi-Du)) +- Bumping version for next jsonapi release [\#514](https://github.com/stargate/jsonapi/pull/514) ([github-actions[bot]](https://github.com/apps/github-actions)) +- add nb test cases for vector search jsonapi [\#512](https://github.com/stargate/jsonapi/pull/512) ([Yuqi-Du](https://github.com/Yuqi-Du)) + +## [v1.0.0-ALPHA-14](https://github.com/stargate/jsonapi/tree/v1.0.0-ALPHA-14) (2023-08-21) + +[Full Changelog](https://github.com/stargate/jsonapi/compare/v1.0.0-ALPHA-13...v1.0.0-ALPHA-14) **Closed issues:** - Reduce index columns [\#505](https://github.com/stargate/jsonapi/issues/505) +- IT cases for vector size validations [\#497](https://github.com/stargate/jsonapi/issues/497) +- Create APP using JSON API [\#465](https://github.com/stargate/jsonapi/issues/465) +- \[Design Revisit\] Projection handling of $vector [\#461](https://github.com/stargate/jsonapi/issues/461) + +**Merged pull requests:** + +- Use Stargate v2.1.0-ALPHA-7 [\#513](https://github.com/stargate/jsonapi/pull/513) ([github-actions[bot]](https://github.com/apps/github-actions)) +- Swagger vector search [\#511](https://github.com/stargate/jsonapi/pull/511) ([maheshrajamani](https://github.com/maheshrajamani)) +- User friendly unsupported feature notification [\#510](https://github.com/stargate/jsonapi/pull/510) ([Yuqi-Du](https://github.com/Yuqi-Du)) +- Bumping version for next jsonapi release [\#507](https://github.com/stargate/jsonapi/pull/507) ([github-actions[bot]](https://github.com/apps/github-actions)) +- Create integration test for vector unmatched size\(insert/find\) [\#503](https://github.com/stargate/jsonapi/pull/503) ([Yuqi-Du](https://github.com/Yuqi-Du)) ## [v1.0.0-ALPHA-13](https://github.com/stargate/jsonapi/tree/v1.0.0-ALPHA-13) (2023-08-16) diff --git a/CONFIGURATION.md b/CONFIGURATION.md index 97f30fc5e9..7845a21d1d 100644 --- a/CONFIGURATION.md +++ b/CONFIGURATION.md @@ -11,6 +11,12 @@ 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) +## Database limits configuration +*Configuration for document limits, defined by [DatabaseLimitsConfig.java](src/main/java/io/stargate/sgv2/jsonapi/config/DatabaseLimitsConfig.java).* + +| Property | Type | Default | Description | +|---------------------------------------------|-------|---------|--------------------------------------------------------------------------------------| +| `stargate.database.limits.max-collections` | `int` | `5` | The maximum number of Collections allowed to be created per Database: defaults to 5. | ## Document limits configuration *Configuration for document limits, defined by [DocumentLimitsConfig.java](src/main/java/io/stargate/sgv2/jsonapi/config/DocumentLimitsConfig.java).* diff --git a/README.md b/README.md index 392bef9d66..e95b571f89 100644 --- a/README.md +++ b/README.md @@ -229,5 +229,5 @@ The extension setups the health endpoints under `/stargate/health`. The OpenAPI definitions are generated and available under `/api/json/openapi` endpoint. The [StargateJsonApi](src/main/java/io/stargate/sgv2/jsonapi/StargateJsonApi.java) class defines the `@OpenAPIDefinition` annotation. -This definition defines the default *SecurityScheme* named `Token`, which expects the header based authentication with the HTTP Header `X-Cassandra-Token`. +This definition defines the default *SecurityScheme* named `Token`, which expects the header based authentication with the HTTP Header `Token`. The `info` portions of the Open API definitions are set using the `quarkus.smallrye-openapi.info-` configuration properties. diff --git a/docker-compose/.env b/docker-compose/.env index f692cb35d1..7673c99f9d 100644 --- a/docker-compose/.env +++ b/docker-compose/.env @@ -1,5 +1,5 @@ COMPOSE_PROJECT_NAME=dse-next-stargate -DSETAG=4.0.11-669ae5e3994d +DSETAG=4.0.11-45d4657e507e LOGLEVEL=INFO REQUESTLOG=false SGTAG=v2.1 diff --git a/docs/jsonapi-network-spec.md b/docs/jsonapi-network-spec.md index aa24949b58..3e5aead43e 100644 --- a/docs/jsonapi-network-spec.md +++ b/docs/jsonapi-network-spec.md @@ -150,7 +150,7 @@ The HTTP API provides two types of endpoints: Both endpoints follow these rules: 1. All requests **must** use a HTTP `POST` verb. -2. Requests **must** supply a `Cassandra-Token` header **TODO:** Why +2. Requests **must** supply a `Token` header **TODO:** Why not just Authorization, current rest API is X-Cassandra-Token, using X is deprecated https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers diff --git a/fallout/dataset-test-nosqlbench.yaml b/fallout/dataset-test-nosqlbench.yaml index 8cad1a5ecb..bbdf8f5f42 100644 --- a/fallout/dataset-test-nosqlbench.yaml +++ b/fallout/dataset-test-nosqlbench.yaml @@ -55,7 +55,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1 Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: ".*\"ok\":1.*" body: >2 @@ -72,7 +72,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: ".*\"ok\":1.*" body: >2 @@ -87,7 +87,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: ".*\"ok\":1.*" body: >2 @@ -105,7 +105,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<>/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: '.*\"insertedIds\":\[.*\].*' body: >2 @@ -129,7 +129,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<>/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: ".*\"data\".*" body: >2 @@ -148,7 +148,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<>/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: ".*\"data\".*" body: >2 @@ -167,7 +167,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<>/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: ".*\"data\".*" body: >2 @@ -186,7 +186,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<>/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: ".*\"data\".*" body: >2 @@ -209,7 +209,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<>/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: ".*\"data\".*" body: >2 @@ -232,7 +232,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<>/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" # because this is not an upsert, modified count could technically be 0 or 1, # but since we are fixing the _ids to be sequential over the docscount range during the write phase, @@ -259,7 +259,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<>/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: ".*\"deletedCount\":[0,1].*" body: >2 @@ -278,7 +278,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<>/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: ".*\"data\".*" body: >2 diff --git a/fallout/smoke-test-nosqlbench.yaml b/fallout/smoke-test-nosqlbench.yaml index 762589b40b..9f4766e1f1 100644 --- a/fallout/smoke-test-nosqlbench.yaml +++ b/fallout/smoke-test-nosqlbench.yaml @@ -52,7 +52,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1 Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: ".*\"ok\":1.*" body: >2 @@ -69,7 +69,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: ".*\"ok\":1.*" body: >2 @@ -84,7 +84,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: ".*\"ok\":1.*" body: >2 @@ -103,7 +103,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<>/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: '.*\"insertedIds\":\[.*\].*' body: >2 @@ -146,7 +146,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<>/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: ".*\"data\".*" body: >2 @@ -165,7 +165,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<>/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: ".*\"data\".*" body: >2 @@ -184,7 +184,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<>/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: ".*\"data\".*" body: >2 @@ -204,7 +204,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<>/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: ".*\"data\".*" body: >2 @@ -230,7 +230,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<>/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: ".*\"data\".*" body: >2 @@ -252,7 +252,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<>/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: ".*\"data\".*" body: >2 @@ -280,7 +280,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<>/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: ".*\"deletedCount\":[0,1].*" body: >2 @@ -299,7 +299,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<>/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: ".*\"data\".*" body: >2 @@ -344,7 +344,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<>/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: ".*\"status\".*" body: >2 @@ -371,7 +371,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<>/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: ".*\"count\".*" body: >2 diff --git a/fallout/vector-insertmany-nosqlbench.yaml b/fallout/vector-insertmany-nosqlbench.yaml index 3bf7c56632..2f8cce0d32 100644 --- a/fallout/vector-insertmany-nosqlbench.yaml +++ b/fallout/vector-insertmany-nosqlbench.yaml @@ -45,7 +45,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: ".*\"ok\":1.*" body: >2 @@ -59,7 +59,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: ".*\"ok\":1.*" # vector mush be enabled when creating collection @@ -84,7 +84,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<>/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: '.*\"insertedIds\":\[.*\].*' body: >2 diff --git a/fallout/vector-test-nosqlbench.yaml b/fallout/vector-test-nosqlbench.yaml index 9553f5321c..d8fba5eac2 100644 --- a/fallout/vector-test-nosqlbench.yaml +++ b/fallout/vector-test-nosqlbench.yaml @@ -47,7 +47,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: ".*\"ok\":1.*" body: >2 @@ -61,7 +61,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: ".*\"ok\":1.*" # vector mush be enabled when creating collection @@ -71,7 +71,7 @@ blocks: "name": "<>", "options": { "vector": { - "size": 1536 + "dimension": 1536 } } } @@ -86,7 +86,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<>/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: '.*\"insertedIds\":\[.*\].*' body: >2 @@ -106,7 +106,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<>/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: ".*\"data\".*" body: >2 @@ -122,7 +122,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<>/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: ".*\"data\".*" body: >2 @@ -143,7 +143,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<>/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: ".*\"data\".*" body: >2 @@ -162,7 +162,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<>/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: ".*\"deletedCount\":[0,1].*" body: >2 diff --git a/nosqlbench/http-jsonapi-crud-basic.yaml b/nosqlbench/http-jsonapi-crud-basic.yaml index 1081b385ea..a707e3df86 100644 --- a/nosqlbench/http-jsonapi-crud-basic.yaml +++ b/nosqlbench/http-jsonapi-crud-basic.yaml @@ -55,7 +55,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1 Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: ".*\"ok\":1.*" body: >2 @@ -70,7 +70,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: ".*\"ok\":1.*" body: >2 @@ -85,7 +85,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: ".*\"ok\":1.*" body: >2 @@ -104,7 +104,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<>/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: '.*\"insertedIds\":\[.*\].*' body: >2 @@ -145,7 +145,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<>/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: ".*\"data\".*" body: >2 @@ -167,7 +167,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<>/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" # because this is not an upsert, modified count could technically be 0 or 1, # but since we are fixing the _ids to be sequential over the docscount range during the write phase, @@ -215,7 +215,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<>/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: ".*\"deletedCount\":[0,1].*" body: >2 diff --git a/nosqlbench/http-jsonapi-crud-dataset.yaml b/nosqlbench/http-jsonapi-crud-dataset.yaml index 5f0a5bd33f..7c2f30ee81 100644 --- a/nosqlbench/http-jsonapi-crud-dataset.yaml +++ b/nosqlbench/http-jsonapi-crud-dataset.yaml @@ -54,7 +54,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1 Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: ".*\"ok\":1.*" body: >2 @@ -69,7 +69,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: ".*\"ok\":1.*" body: >2 @@ -84,7 +84,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: ".*\"ok\":1.*" body: >2 @@ -102,7 +102,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<>/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: ".*\"insertedIds\":\"{seq_key}\".*" body: >2 @@ -125,7 +125,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<>/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: ".*\"data\".*" body: >2 @@ -144,7 +144,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<>/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: ".*\"data\".*" body: >2 @@ -163,7 +163,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<>/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: ".*\"data\".*" body: >2 @@ -182,7 +182,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<>/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: ".*\"data\".*" body: >2 @@ -205,7 +205,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<>/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: ".*\"data\".*" body: >2 @@ -228,7 +228,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<>/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" # because this is not an upsert, modified count could technically be 0 or 1, # but since we are fixing the _ids to be sequential over the docscount range during the write phase, @@ -255,7 +255,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<>/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: ".*\"deletedCount\":[0,1].*" body: >2 @@ -274,7 +274,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<>/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: ".*\"data\".*" body: >2 diff --git a/nosqlbench/http-jsonapi-keyvalue.yaml b/nosqlbench/http-jsonapi-keyvalue.yaml index 9593f45613..b9846a4e14 100644 --- a/nosqlbench/http-jsonapi-keyvalue.yaml +++ b/nosqlbench/http-jsonapi-keyvalue.yaml @@ -47,7 +47,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1 Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: ".*\"ok\":1.*" body: >2 @@ -62,7 +62,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: ".*\"ok\":1.*" body: >2 @@ -77,7 +77,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: ".*\"ok\":1.*" body: >2 @@ -95,7 +95,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<>/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: '.*\"insertedIds\":\[.*\].*' body: >2 @@ -118,7 +118,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<>/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: ".*\"data\".*" body: >2 @@ -136,7 +136,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<>/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" # because this is not an upsert, modified count could be 0 or 1 ok-body: ".*\"modifiedCount\":[0,1].*" diff --git a/nosqlbench/http-jsonapi-search-advanced.yaml b/nosqlbench/http-jsonapi-search-advanced.yaml index 6799783bc6..3c4bc49b4f 100644 --- a/nosqlbench/http-jsonapi-search-advanced.yaml +++ b/nosqlbench/http-jsonapi-search-advanced.yaml @@ -78,7 +78,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1 Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: ".*\"ok\":1.*" body: >2 @@ -93,7 +93,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: ".*\"ok\":1.*" body: >2 @@ -108,7 +108,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: ".*\"ok\":1.*" body: >2 @@ -126,7 +126,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<>/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: '.*\"insertedIds\":\[.*\].*' body: >2 @@ -169,7 +169,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<>/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: ".*\"data\".*" body: >2 @@ -193,7 +193,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<>/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: ".*\"data\".*" body: >2 @@ -217,7 +217,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<>/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: ".*\"data\".*" body: >2 @@ -244,7 +244,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<>/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: ".*\"data\".*" body: >2 @@ -277,7 +277,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<>/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: ".*\"data\".*" body: >2 @@ -319,7 +319,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<>/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: ".*\"data\".*" body: >2 @@ -370,7 +370,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<>/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: ".*\"data\".*" body: >2 @@ -423,7 +423,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<>/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: ".*\"data\".*" body: >2 @@ -447,7 +447,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<>/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: ".*\"data\".*" body: >2 @@ -471,7 +471,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<>/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: ".*\"data\".*" body: >2 @@ -498,7 +498,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<>/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: ".*\"data\".*" body: >2 @@ -531,7 +531,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<>/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: ".*\"data\".*" body: >2 @@ -573,7 +573,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<>/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: ".*\"data\".*" body: >2 diff --git a/nosqlbench/http-jsonapi-search-basic.yaml b/nosqlbench/http-jsonapi-search-basic.yaml index e19e708c76..634ebfde7c 100644 --- a/nosqlbench/http-jsonapi-search-basic.yaml +++ b/nosqlbench/http-jsonapi-search-basic.yaml @@ -63,7 +63,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1 Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: ".*\"ok\":1.*" body: >2 @@ -78,7 +78,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: ".*\"ok\":1.*" body: >2 diff --git a/nosqlbench/http-jsonapi-search-filter-sort.yaml b/nosqlbench/http-jsonapi-search-filter-sort.yaml index ea57420ce3..b882e991f4 100644 --- a/nosqlbench/http-jsonapi-search-filter-sort.yaml +++ b/nosqlbench/http-jsonapi-search-filter-sort.yaml @@ -65,7 +65,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1 Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: ".*\"ok\":1.*" body: | @@ -80,7 +80,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: ".*\"ok\":1.*" body: | @@ -95,7 +95,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: ".*\"ok\":1.*" body: | @@ -114,7 +114,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<>/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: '.*\"insertedIds\":\[.*\].*' body: | diff --git a/nosqlbench/http-jsonapi-vector-crud.yaml b/nosqlbench/http-jsonapi-vector-crud.yaml index 54767930f8..142b914dbe 100644 --- a/nosqlbench/http-jsonapi-vector-crud.yaml +++ b/nosqlbench/http-jsonapi-vector-crud.yaml @@ -49,7 +49,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1 Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: ".*\"ok\":1.*" body: >2 @@ -64,7 +64,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: ".*\"ok\":1.*" body: >2 @@ -79,7 +79,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: ".*\"ok\":1.*" # vector mush be enabled when creating collection @@ -89,7 +89,7 @@ blocks: "name": "<>", "options": { "vector": { - "size": 1536 + "dimension": 1536 } } } @@ -105,7 +105,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<>/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: '.*\"insertedIds\":\[.*\].*' body: >2 @@ -125,7 +125,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<>/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: ".*\"data\".*" body: >2 @@ -142,7 +142,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<>/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: ".*\"data\".*" body: >2 @@ -165,7 +165,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<>/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: ".*\"data\".*" body: >2 @@ -185,7 +185,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<>/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: ".*\"deletedCount\":[0,1].*" body: >2 diff --git a/nosqlbench/http-jsonapi-vector-insertmany.yaml b/nosqlbench/http-jsonapi-vector-insertmany.yaml index b23e8d26f2..5b93460e0d 100644 --- a/nosqlbench/http-jsonapi-vector-insertmany.yaml +++ b/nosqlbench/http-jsonapi-vector-insertmany.yaml @@ -46,7 +46,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1 Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: ".*\"ok\":1.*" body: >2 @@ -61,7 +61,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: ".*\"ok\":1.*" body: >2 @@ -76,7 +76,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: ".*\"ok\":1.*" # vector mush be enabled when creating collection @@ -102,7 +102,7 @@ blocks: uri: <>://{weighted_hosts}:<><>/v1/<>/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" - X-Cassandra-Token: "{token}" + Token: "{token}" Content-Type: "application/json" ok-body: '.*\"insertedIds\":\[.*\].*' body: >2 diff --git a/pom.xml b/pom.xml index d4e4a9b078..67c1ad0e17 100644 --- a/pom.xml +++ b/pom.xml @@ -7,11 +7,11 @@ 2.1.0-BETA-2 sgv2-jsonapi - 1.0.0-BETA-2-SNAPSHOT + 1.0.0-BETA-4-SNAPSHOT ${project.parent.version} - 2.15.2 + 2.15.3 false stargateio @@ -22,8 +22,8 @@ stargateio/dse-next - - 4.0.11-669ae5e3994d + + 4.0.11-45d4657e507e stargateio/coordinator-dse-next v${stargate.version} dse-next-${stargate.int-test.cassandra.image-tag}-cluster diff --git a/src/main/docker/Dockerfile.jvm b/src/main/docker/Dockerfile.jvm index 1b982bb03a..5809901471 100644 --- a/src/main/docker/Dockerfile.jvm +++ b/src/main/docker/Dockerfile.jvm @@ -77,7 +77,7 @@ # accessed directly. (example: "foo.example.com,bar.example.com") # ### -FROM registry.access.redhat.com/ubi8/openjdk-17:1.17 +FROM registry.access.redhat.com/ubi8/openjdk-17-runtime:1.17 ENV LANGUAGE='en_US:en' @@ -90,6 +90,6 @@ COPY --chown=185 target/quarkus-app/quarkus/ /deployments/quarkus/ EXPOSE 8181 USER 185 -ENV JAVA_OPTS="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager" +ENV JAVA_OPTS_APPEND="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager" ENV JAVA_APP_JAR="/deployments/quarkus-run.jar" diff --git a/src/main/java/io/stargate/sgv2/jsonapi/JsonApiStartUp.java b/src/main/java/io/stargate/sgv2/jsonapi/JsonApiStartUp.java index 266f40d36c..135731156f 100644 --- a/src/main/java/io/stargate/sgv2/jsonapi/JsonApiStartUp.java +++ b/src/main/java/io/stargate/sgv2/jsonapi/JsonApiStartUp.java @@ -3,6 +3,7 @@ import io.quarkus.runtime.Quarkus; import io.quarkus.runtime.StartupEvent; import io.stargate.sgv2.api.common.properties.datastore.DataStoreProperties; +import io.stargate.sgv2.jsonapi.config.DebugModeConfig; import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.event.Observes; import jakarta.inject.Inject; @@ -14,13 +15,16 @@ public class JsonApiStartUp { private static final Logger LOGGER = LoggerFactory.getLogger(JsonApiStartUp.class); private final DataStoreProperties dataStoreProperties; + private final DebugModeConfig config; @Inject - public JsonApiStartUp(DataStoreProperties dataStoreProperties) { + public JsonApiStartUp(DataStoreProperties dataStoreProperties, DebugModeConfig config) { this.dataStoreProperties = dataStoreProperties; + this.config = config; } void onStart(@Observes StartupEvent ev) { + LOGGER.info(String.format("DEBUG mode Enabled: %s", config.enabled())); LOGGER.info( String.format("VectorSearch Enabled: %s", dataStoreProperties.vectorSearchEnabled())); LOGGER.info( diff --git a/src/main/java/io/stargate/sgv2/jsonapi/StargateJsonApi.java b/src/main/java/io/stargate/sgv2/jsonapi/StargateJsonApi.java index ffbfcb1b22..5e3c39450e 100644 --- a/src/main/java/io/stargate/sgv2/jsonapi/StargateJsonApi.java +++ b/src/main/java/io/stargate/sgv2/jsonapi/StargateJsonApi.java @@ -1,7 +1,7 @@ package io.stargate.sgv2.jsonapi; -import io.stargate.sgv2.api.common.config.constants.HttpConstants; import io.stargate.sgv2.api.common.grpc.SourceApiQualifier; +import io.stargate.sgv2.jsonapi.config.constants.HttpConstants; import io.stargate.sgv2.jsonapi.config.constants.OpenApiConstants; import jakarta.ws.rs.Produces; import jakarta.ws.rs.core.Application; @@ -387,8 +387,8 @@ "name": "events_vector", "options": { "vector": { - "size": 2, - "function": "cosine" + "dimension": 2, + "metric": "cosine" } } } diff --git a/src/main/java/io/stargate/sgv2/jsonapi/api/exception/ConstraintViolationExceptionMapper.java b/src/main/java/io/stargate/sgv2/jsonapi/api/exception/ConstraintViolationExceptionMapper.java index 43e42238ec..1d2d3e6e98 100644 --- a/src/main/java/io/stargate/sgv2/jsonapi/api/exception/ConstraintViolationExceptionMapper.java +++ b/src/main/java/io/stargate/sgv2/jsonapi/api/exception/ConstraintViolationExceptionMapper.java @@ -18,6 +18,9 @@ public class ConstraintViolationExceptionMapper { public static final Map ERROR_FIELDS = Map.of("exceptionClass", ConstraintViolationException.class.getSimpleName()); + public static final Map ERROR_FIELDS_METRICS_TAG = + Map.of("exceptionClass", ConstraintViolationException.class.getSimpleName()); + @ServerExceptionMapper public RestResponse constraintViolationException( ConstraintViolationException exception) { @@ -35,6 +38,6 @@ private static CommandResult.Error getError(ConstraintViolation violation) { String message = violation.getMessage(); Path propertyPath = violation.getPropertyPath(); String msg = "Request invalid, the field %s not valid: %s.".formatted(propertyPath, message); - return new CommandResult.Error(msg, ERROR_FIELDS, Response.Status.OK); + return new CommandResult.Error(msg, ERROR_FIELDS, ERROR_FIELDS_METRICS_TAG, Response.Status.OK); } } diff --git a/src/main/java/io/stargate/sgv2/jsonapi/api/model/command/Command.java b/src/main/java/io/stargate/sgv2/jsonapi/api/model/command/Command.java index 5ef7003086..35e611f229 100644 --- a/src/main/java/io/stargate/sgv2/jsonapi/api/model/command/Command.java +++ b/src/main/java/io/stargate/sgv2/jsonapi/api/model/command/Command.java @@ -2,7 +2,7 @@ import com.fasterxml.jackson.annotation.JsonSubTypes; import com.fasterxml.jackson.annotation.JsonTypeInfo; -import io.stargate.sgv2.jsonapi.api.model.command.impl.CountDocumentsCommands; +import io.stargate.sgv2.jsonapi.api.model.command.impl.CountDocumentsCommand; import io.stargate.sgv2.jsonapi.api.model.command.impl.CreateCollectionCommand; import io.stargate.sgv2.jsonapi.api.model.command.impl.CreateEmbeddingServiceCommand; import io.stargate.sgv2.jsonapi.api.model.command.impl.CreateNamespaceCommand; @@ -41,7 +41,7 @@ */ @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.WRAPPER_OBJECT) @JsonSubTypes({ - @JsonSubTypes.Type(value = CountDocumentsCommands.class), + @JsonSubTypes.Type(value = CountDocumentsCommand.class), @JsonSubTypes.Type(value = CreateEmbeddingServiceCommand.class), @JsonSubTypes.Type(value = CreateNamespaceCommand.class), @JsonSubTypes.Type(value = CreateCollectionCommand.class), diff --git a/src/main/java/io/stargate/sgv2/jsonapi/api/model/command/CommandResult.java b/src/main/java/io/stargate/sgv2/jsonapi/api/model/command/CommandResult.java index 782d815dd2..92e1fb97a4 100644 --- a/src/main/java/io/stargate/sgv2/jsonapi/api/model/command/CommandResult.java +++ b/src/main/java/io/stargate/sgv2/jsonapi/api/model/command/CommandResult.java @@ -171,6 +171,7 @@ public List getResponseDocuments() { }) public record Error( String message, + @JsonIgnore @Schema(hidden = true) Map fieldsForMetricsTag, @JsonAnyGetter @Schema(hidden = true) Map fields, // Http status to be used in the response, defaulted to 200 @JsonIgnore Response.Status status) { diff --git a/src/main/java/io/stargate/sgv2/jsonapi/api/model/command/impl/CountDocumentsCommands.java b/src/main/java/io/stargate/sgv2/jsonapi/api/model/command/impl/CountDocumentsCommand.java similarity index 88% rename from src/main/java/io/stargate/sgv2/jsonapi/api/model/command/impl/CountDocumentsCommands.java rename to src/main/java/io/stargate/sgv2/jsonapi/api/model/command/impl/CountDocumentsCommand.java index a80730edf0..b6f03b6512 100644 --- a/src/main/java/io/stargate/sgv2/jsonapi/api/model/command/impl/CountDocumentsCommands.java +++ b/src/main/java/io/stargate/sgv2/jsonapi/api/model/command/impl/CountDocumentsCommand.java @@ -13,5 +13,5 @@ description = "Command that returns count of documents in a collection based on the collection.") @JsonTypeName("countDocuments") -public record CountDocumentsCommands(@Valid @JsonProperty("filter") FilterClause filterClause) +public record CountDocumentsCommand(@Valid @JsonProperty("filter") FilterClause filterClause) implements ReadCommand, NoOptionsCommand, Filterable {} diff --git a/src/main/java/io/stargate/sgv2/jsonapi/api/model/command/impl/CreateCollectionCommand.java b/src/main/java/io/stargate/sgv2/jsonapi/api/model/command/impl/CreateCollectionCommand.java index 0068c3a109..c4317b6f45 100644 --- a/src/main/java/io/stargate/sgv2/jsonapi/api/model/command/impl/CreateCollectionCommand.java +++ b/src/main/java/io/stargate/sgv2/jsonapi/api/model/command/impl/CreateCollectionCommand.java @@ -1,6 +1,8 @@ package io.stargate.sgv2.jsonapi.api.model.command.impl; +import com.fasterxml.jackson.annotation.JsonAlias; import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonTypeName; import io.stargate.sgv2.jsonapi.api.model.command.NamespaceCommand; import jakarta.validation.constraints.*; @@ -41,12 +43,14 @@ public record Options( VectorizeConfig vectorize) { public record VectorSearchConfig( - @Positive(message = "size should be greater than `0`") + @Positive(message = "dimension should be greater than `0`") @Schema( - description = "Vector field embedding size", + description = "Dimension of the vector field", type = SchemaType.INTEGER, implementation = Integer.class) - Integer size, + @JsonProperty("dimension") + @JsonAlias("size") // old name + Integer dimension, @Nullable @Pattern( regexp = "(dot_product|cosine|euclidean)", @@ -57,10 +61,12 @@ public record VectorSearchConfig( defaultValue = "cosine", type = SchemaType.STRING, implementation = String.class) - String function) { - public VectorSearchConfig(Integer size, String function) { - this.size = size; - this.function = function == null ? "cosine" : function; + @JsonProperty("metric") + @JsonAlias("function") // old name + String metric) { + public VectorSearchConfig(Integer dimension, String metric) { + this.dimension = dimension; + this.metric = metric == null ? "cosine" : metric; } } diff --git a/src/main/java/io/stargate/sgv2/jsonapi/api/model/command/impl/InsertManyCommand.java b/src/main/java/io/stargate/sgv2/jsonapi/api/model/command/impl/InsertManyCommand.java index 2e39657908..56b7d1e5ce 100644 --- a/src/main/java/io/stargate/sgv2/jsonapi/api/model/command/impl/InsertManyCommand.java +++ b/src/main/java/io/stargate/sgv2/jsonapi/api/model/command/impl/InsertManyCommand.java @@ -36,7 +36,7 @@ public record InsertManyCommand( public record Options( @Schema( description = - "When `true` the server will insert the documents in sequential order, otherwise when `false` the server is free to re-order the inserts and parallelize them for performance. See specifications for more info on failure modes.", + "When `true` the server will insert the documents in sequential order, ensuring each document is successfully inserted before starting the next. Additionally the command will \"fail fast\", failing the first document that fails to insert. When `false` the server is free to re-order the inserts and parallelize them for performance. In this mode more than one document may fail to be inserted (aka \"fail silently\" mode).", defaultValue = "true") Boolean ordered) {} } diff --git a/src/main/java/io/stargate/sgv2/jsonapi/api/security/ErrorChallengeSender.java b/src/main/java/io/stargate/sgv2/jsonapi/api/security/ErrorChallengeSender.java index 8dac25b056..2d20898fa6 100644 --- a/src/main/java/io/stargate/sgv2/jsonapi/api/security/ErrorChallengeSender.java +++ b/src/main/java/io/stargate/sgv2/jsonapi/api/security/ErrorChallengeSender.java @@ -6,6 +6,7 @@ import io.smallrye.mutiny.Uni; import io.stargate.sgv2.api.common.security.challenge.ChallengeSender; import io.stargate.sgv2.jsonapi.api.model.command.CommandResult; +import io.stargate.sgv2.jsonapi.config.constants.HttpConstants; import io.vertx.ext.web.RoutingContext; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; @@ -14,7 +15,6 @@ import jakarta.ws.rs.core.Response; import java.util.Collections; import java.util.List; -import org.eclipse.microprofile.config.inject.ConfigProperty; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -31,17 +31,14 @@ public class ErrorChallengeSender implements ChallengeSender { private final CommandResult commandResult; @Inject - public ErrorChallengeSender( - @ConfigProperty(name = "stargate.auth.header-based.header-name", defaultValue = "") - String headerName, - ObjectMapper objectMapper) { + public ErrorChallengeSender(ObjectMapper objectMapper) { this.objectMapper = objectMapper; - // create the response String message = "Role unauthorized for operation: Missing token, expecting one in the %s header." - .formatted(headerName); + .formatted(HttpConstants.AUTHENTICATION_TOKEN_HEADER_NAME); CommandResult.Error error = - new CommandResult.Error(message, Collections.emptyMap(), Response.Status.UNAUTHORIZED); + new CommandResult.Error( + message, Collections.emptyMap(), Collections.emptyMap(), Response.Status.UNAUTHORIZED); commandResult = new CommandResult(List.of(error)); } diff --git a/src/main/java/io/stargate/sgv2/jsonapi/api/v1/CollectionResource.java b/src/main/java/io/stargate/sgv2/jsonapi/api/v1/CollectionResource.java index ac7f2ec47d..6863ee5726 100644 --- a/src/main/java/io/stargate/sgv2/jsonapi/api/v1/CollectionResource.java +++ b/src/main/java/io/stargate/sgv2/jsonapi/api/v1/CollectionResource.java @@ -5,7 +5,7 @@ import io.stargate.sgv2.jsonapi.api.model.command.CollectionCommand; import io.stargate.sgv2.jsonapi.api.model.command.CommandContext; import io.stargate.sgv2.jsonapi.api.model.command.CommandResult; -import io.stargate.sgv2.jsonapi.api.model.command.impl.CountDocumentsCommands; +import io.stargate.sgv2.jsonapi.api.model.command.impl.CountDocumentsCommand; import io.stargate.sgv2.jsonapi.api.model.command.impl.DeleteManyCommand; import io.stargate.sgv2.jsonapi.api.model.command.impl.DeleteOneCommand; import io.stargate.sgv2.jsonapi.api.model.command.impl.FindCommand; @@ -85,7 +85,7 @@ public CollectionResource(MeteredCommandProcessor meteredCommandProcessor) { schema = @Schema( anyOf = { - CountDocumentsCommands.class, + CountDocumentsCommand.class, DeleteOneCommand.class, DeleteManyCommand.class, FindOneCommand.class, diff --git a/src/main/java/io/stargate/sgv2/jsonapi/api/v1/TokenFilter.java b/src/main/java/io/stargate/sgv2/jsonapi/api/v1/TokenFilter.java new file mode 100644 index 0000000000..7968e09116 --- /dev/null +++ b/src/main/java/io/stargate/sgv2/jsonapi/api/v1/TokenFilter.java @@ -0,0 +1,32 @@ +package io.stargate.sgv2.jsonapi.api.v1; + +import static io.stargate.sgv2.jsonapi.config.constants.HttpConstants.DEPRECATED_AUTHENTICATION_TOKEN_HEADER_NAME; + +import io.quarkus.vertx.http.runtime.filters.Filters; +import io.vertx.core.MultiMap; +import jakarta.enterprise.context.RequestScoped; +import jakarta.enterprise.event.Observes; + +/** + * Request based, filtering out authentication token and add correct header Coordinator needs + * X-Cassandra-Token as token name JSON API requires Token as token name Also supports + * X-Cassandra-Token for backward compatibility + */ +@RequestScoped +public class TokenFilter { + + // JSON API token name "Token", also supports X-Cassandra-Token for backward compatibility + public void registerMyFilter(@Observes Filters filters) { + filters.register( + rc -> { + MultiMap headers = rc.request().headers(); + if (headers.contains("Token")) { + headers.add(DEPRECATED_AUTHENTICATION_TOKEN_HEADER_NAME, headers.get("Token")); + } else if (headers.contains("token")) { + headers.add(DEPRECATED_AUTHENTICATION_TOKEN_HEADER_NAME, headers.get("token")); + } + rc.next(); + }, + 10000); + } +} diff --git a/src/main/java/io/stargate/sgv2/jsonapi/config/DatabaseLimitsConfig.java b/src/main/java/io/stargate/sgv2/jsonapi/config/DatabaseLimitsConfig.java new file mode 100644 index 0000000000..0bd87c0ca2 --- /dev/null +++ b/src/main/java/io/stargate/sgv2/jsonapi/config/DatabaseLimitsConfig.java @@ -0,0 +1,39 @@ +/* + * Copyright The Stargate Authors + * + * Licensed 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 io.stargate.sgv2.jsonapi.config; + +import io.quarkus.runtime.annotations.StaticInitSafe; +import io.smallrye.config.ConfigMapping; +import io.smallrye.config.WithDefault; +import jakarta.validation.constraints.Positive; + +/** Configuration for limits that apply to Databases. */ +@StaticInitSafe +@ConfigMapping(prefix = "stargate.database.limits") +public interface DatabaseLimitsConfig { + // Constant we need to access from Integration tests + int DEFAULT_MAX_COLLECTIONS = 5; + + /** + * @return Defines maximum Collections allowed to be created per Database. Defaults to 5 + * due to underlying Cassandra indexing limitations. + */ + @Positive + @WithDefault("" + DEFAULT_MAX_COLLECTIONS) + int maxCollections(); +} diff --git a/src/main/java/io/stargate/sgv2/jsonapi/config/DebugModeConfig.java b/src/main/java/io/stargate/sgv2/jsonapi/config/DebugModeConfig.java new file mode 100644 index 0000000000..b3c8f50dd9 --- /dev/null +++ b/src/main/java/io/stargate/sgv2/jsonapi/config/DebugModeConfig.java @@ -0,0 +1,11 @@ +package io.stargate.sgv2.jsonapi.config; + +import io.smallrye.config.ConfigMapping; +import io.smallrye.config.WithDefault; + +@ConfigMapping(prefix = "stargate.debug") +public interface DebugModeConfig { + + @WithDefault("false") + boolean enabled(); +} diff --git a/src/main/java/io/stargate/sgv2/jsonapi/config/DocumentLimitsConfig.java b/src/main/java/io/stargate/sgv2/jsonapi/config/DocumentLimitsConfig.java index 0193db4be6..19e3606a60 100644 --- a/src/main/java/io/stargate/sgv2/jsonapi/config/DocumentLimitsConfig.java +++ b/src/main/java/io/stargate/sgv2/jsonapi/config/DocumentLimitsConfig.java @@ -12,6 +12,10 @@ @StaticInitSafe @ConfigMapping(prefix = "stargate.jsonapi.document.limits") public interface DocumentLimitsConfig { + + /** Defines the max size of filter fields, default is 64 fields. */ + int DEFAULT_MAX_FILTER_SIZE = 64; + /** * @return Defines the maximum document page size, defaults to {@code 1 meg} (1 million * characters). @@ -42,6 +46,15 @@ public interface DocumentLimitsConfig { @WithDefault("64") int maxObjectProperties(); + /** + * @return Defines the max size of filter fields, defaults to {@code 64}, which is tha same as the + * maximum number of properties of a single Json object. (note: this does not count the fields + * in '$operation' such as $in, $all) + */ + @Positive + @WithDefault("" + DEFAULT_MAX_FILTER_SIZE) + int maxFilterObjectProperties(); + /** @return Defines the maximum length of a single Number value (in characters). */ @Positive @WithDefault("50") diff --git a/src/main/java/io/stargate/sgv2/jsonapi/config/constants/HttpConstants.java b/src/main/java/io/stargate/sgv2/jsonapi/config/constants/HttpConstants.java new file mode 100644 index 0000000000..5127cdeff3 --- /dev/null +++ b/src/main/java/io/stargate/sgv2/jsonapi/config/constants/HttpConstants.java @@ -0,0 +1,10 @@ +package io.stargate.sgv2.jsonapi.config.constants; + +public interface HttpConstants { + + /** JSON API Authentication token header name. */ + String AUTHENTICATION_TOKEN_HEADER_NAME = "Token"; + + /** JSON API also supports X-Cassandra-Token for backward compatibility. */ + String DEPRECATED_AUTHENTICATION_TOKEN_HEADER_NAME = "X-Cassandra-Token"; +} diff --git a/src/main/java/io/stargate/sgv2/jsonapi/exception/ErrorCode.java b/src/main/java/io/stargate/sgv2/jsonapi/exception/ErrorCode.java index 7574a5e7b5..0394aaf0f1 100644 --- a/src/main/java/io/stargate/sgv2/jsonapi/exception/ErrorCode.java +++ b/src/main/java/io/stargate/sgv2/jsonapi/exception/ErrorCode.java @@ -9,7 +9,7 @@ public enum ErrorCode { COMMAND_ACCEPTS_NO_OPTIONS("Command accepts no options"), CONCURRENCY_FAILURE("Unable to complete transaction due to concurrent transactions"), - + COLLECTION_NOT_EXIST("Collection does not exist, collection name: "), DATASET_TOO_BIG("Response data set too big to be sorted, add more filters"), DOCUMENT_ALREADY_EXISTS("Document already exists with the given _id"), @@ -24,6 +24,8 @@ public enum ErrorCode { FILTER_MULTIPLE_ID_FILTER( "Should only have one _id filter, document id cannot be restricted by more than one relation if it includes an Equal"), + FILTER_FIELDS_LIMIT_VIOLATION("Filter fields size limitation violated"), + NAMESPACE_DOES_NOT_EXIST("The provided namespace does not exist."), SHRED_BAD_DOCUMENT_TYPE("Bad document type to shred"), @@ -57,6 +59,8 @@ public enum ErrorCode { INVALID_COLLECTION_NAME("Invalid collection name "), + TOO_MANY_COLLECTIONS("Too many collections"), + UNSUPPORTED_FILTER_DATA_TYPE("Unsupported filter data type"), UNSUPPORTED_FILTER_OPERATION("Unsupported filter operator"), diff --git a/src/main/java/io/stargate/sgv2/jsonapi/exception/JsonApiException.java b/src/main/java/io/stargate/sgv2/jsonapi/exception/JsonApiException.java index 33ad0ecec9..88526d9b99 100644 --- a/src/main/java/io/stargate/sgv2/jsonapi/exception/JsonApiException.java +++ b/src/main/java/io/stargate/sgv2/jsonapi/exception/JsonApiException.java @@ -1,11 +1,14 @@ package io.stargate.sgv2.jsonapi.exception; +import io.smallrye.config.SmallRyeConfig; import io.stargate.sgv2.jsonapi.api.model.command.CommandResult; +import io.stargate.sgv2.jsonapi.config.DebugModeConfig; import io.stargate.sgv2.jsonapi.exception.mappers.ThrowableToErrorMapper; import jakarta.ws.rs.core.Response; import java.util.List; import java.util.Map; import java.util.function.Supplier; +import org.eclipse.microprofile.config.ConfigProvider; /** * Our own {@link RuntimeException} that uses {@link ErrorCode} to describe the exception cause. @@ -58,9 +61,20 @@ public CommandResult get() { } public CommandResult.Error getCommandResultError(String message) { - Map fields = + Map fieldsForMetricsTag = Map.of("errorCode", errorCode.name(), "exceptionClass", this.getClass().getSimpleName()); - return new CommandResult.Error(message, fields, Response.Status.OK); + Map fields = null; + SmallRyeConfig config = ConfigProvider.getConfig().unwrap(SmallRyeConfig.class); + // enable debug mode for unit tests, since it can not be injected + DebugModeConfig debugModeConfig = config.getConfigMapping(DebugModeConfig.class); + final boolean debugEnabled = debugModeConfig.enabled(); + if (debugEnabled) { + fields = + Map.of("errorCode", errorCode.name(), "exceptionClass", this.getClass().getSimpleName()); + } else { + fields = Map.of("errorCode", errorCode.name()); + } + return new CommandResult.Error(message, fieldsForMetricsTag, fields, Response.Status.OK); } public ErrorCode getErrorCode() { diff --git a/src/main/java/io/stargate/sgv2/jsonapi/exception/mappers/ThrowableToErrorMapper.java b/src/main/java/io/stargate/sgv2/jsonapi/exception/mappers/ThrowableToErrorMapper.java index e009a8f5ff..466f8990e6 100644 --- a/src/main/java/io/stargate/sgv2/jsonapi/exception/mappers/ThrowableToErrorMapper.java +++ b/src/main/java/io/stargate/sgv2/jsonapi/exception/mappers/ThrowableToErrorMapper.java @@ -10,12 +10,15 @@ import io.grpc.Status; import io.grpc.StatusRuntimeException; import io.quarkus.security.UnauthorizedException; +import io.smallrye.config.SmallRyeConfig; import io.stargate.sgv2.jsonapi.api.model.command.CommandResult; +import io.stargate.sgv2.jsonapi.config.DebugModeConfig; import io.stargate.sgv2.jsonapi.exception.JsonApiException; import jakarta.ws.rs.core.Response; import java.util.Map; import java.util.function.BiFunction; import java.util.function.Function; +import org.eclipse.microprofile.config.ConfigProvider; /** * Simple mapper for mapping {@link Throwable}s to {@link CommandResult.Error}, with a default @@ -28,20 +31,39 @@ public final class ThrowableToErrorMapper { if (throwable instanceof JsonApiException jae) { return jae.getCommandResultError(message); } +<<<<<<< HEAD // add error code as error field Map fields = Map.of("exceptionClass", throwable.getClass().getSimpleName()); if (throwable instanceof StatusRuntimeException sre) { if (sre.getStatus().getCode() == Status.Code.UNAUTHENTICATED) { return new CommandResult.Error( "UNAUTHENTICATED: Invalid token", fields, Response.Status.UNAUTHORIZED); +======= + // Override response error code + SmallRyeConfig config = ConfigProvider.getConfig().unwrap(SmallRyeConfig.class); + DebugModeConfig debugModeConfig = config.getConfigMapping(DebugModeConfig.class); + final boolean debugEnabled = debugModeConfig.enabled(); + if (throwable instanceof StatusRuntimeException sre) { + Map fields = + debugEnabled ? Map.of("exceptionClass", throwable.getClass().getSimpleName()) : null; + Map fieldsForMetricsTag = + Map.of("exceptionClass", throwable.getClass().getSimpleName()); + if (sre.getStatus().getCode() == Status.Code.UNAUTHENTICATED) { + return new CommandResult.Error( + message, fieldsForMetricsTag, fields, Response.Status.UNAUTHORIZED); +>>>>>>> main } else if (sre.getStatus().getCode() == Status.Code.INTERNAL) { - return new CommandResult.Error(message, fields, Response.Status.INTERNAL_SERVER_ERROR); + return new CommandResult.Error( + message, fieldsForMetricsTag, fields, Response.Status.INTERNAL_SERVER_ERROR); } else if (sre.getStatus().getCode() == Status.Code.UNAVAILABLE) { - return new CommandResult.Error(message, fields, Response.Status.BAD_GATEWAY); + return new CommandResult.Error( + message, fieldsForMetricsTag, fields, Response.Status.BAD_GATEWAY); } else if (sre.getStatus().getCode() == Status.Code.DEADLINE_EXCEEDED) { - return new CommandResult.Error(message, fields, Response.Status.GATEWAY_TIMEOUT); + return new CommandResult.Error( + message, fieldsForMetricsTag, fields, Response.Status.GATEWAY_TIMEOUT); } } +<<<<<<< HEAD if (throwable instanceof UnauthorizedException || throwable instanceof com.datastax.oss.driver.api.core.servererrors.UnauthorizedException) { @@ -62,6 +84,14 @@ public final class ThrowableToErrorMapper { return new CommandResult.Error(message, fields, Response.Status.GATEWAY_TIMEOUT); } return new CommandResult.Error(message, fields, Response.Status.OK); +======= + // add error code as error field + Map fields = + debugEnabled ? Map.of("exceptionClass", throwable.getClass().getSimpleName()) : null; + Map fieldsForMetricsTag = + Map.of("exceptionClass", throwable.getClass().getSimpleName()); + return new CommandResult.Error(message, fieldsForMetricsTag, fields, Response.Status.OK); +>>>>>>> main }; private static final Function MAPPER = throwable -> { diff --git a/src/main/java/io/stargate/sgv2/jsonapi/service/bridge/executor/NamespaceCache.java b/src/main/java/io/stargate/sgv2/jsonapi/service/bridge/executor/NamespaceCache.java index c64e7dc155..b3e6271de9 100644 --- a/src/main/java/io/stargate/sgv2/jsonapi/service/bridge/executor/NamespaceCache.java +++ b/src/main/java/io/stargate/sgv2/jsonapi/service/bridge/executor/NamespaceCache.java @@ -6,6 +6,7 @@ import io.grpc.StatusRuntimeException; import io.smallrye.mutiny.Uni; import io.stargate.sgv2.jsonapi.exception.ErrorCode; +import io.stargate.sgv2.jsonapi.exception.JsonApiException; import java.time.Duration; /** Caches the vector enabled status for the namespace */ @@ -41,14 +42,24 @@ protected Uni getCollectionProperties(String collectionName) .transformToUni( (result, error) -> { if (null != error) { + // collection does not exist + if (error instanceof RuntimeException rte + && rte.getMessage() + .startsWith(ErrorCode.INVALID_COLLECTION_NAME.getMessage())) { + return Uni.createFrom() + .failure( + new JsonApiException( + ErrorCode.COLLECTION_NOT_EXIST, + ErrorCode.COLLECTION_NOT_EXIST + .getMessage() + .concat(collectionName))); + } + // ignoring the error and return false. This will be handled while trying to // execute the query if ((error instanceof StatusRuntimeException sre - && (sre.getStatus().getCode() == io.grpc.Status.Code.NOT_FOUND - || sre.getStatus().getCode() == io.grpc.Status.Code.INVALID_ARGUMENT)) - || (error instanceof RuntimeException rte - && rte.getMessage() - .startsWith(ErrorCode.INVALID_COLLECTION_NAME.getMessage()))) { + && (sre.getStatus().getCode() == io.grpc.Status.Code.NOT_FOUND + || sre.getStatus().getCode() == io.grpc.Status.Code.INVALID_ARGUMENT))) { return Uni.createFrom() .item(new CollectionSettings(collectionName, false, 0, null, null, null)); } diff --git a/src/main/java/io/stargate/sgv2/jsonapi/service/operation/model/impl/CreateCollectionOperation.java b/src/main/java/io/stargate/sgv2/jsonapi/service/operation/model/impl/CreateCollectionOperation.java index 960b056d7d..7e63199200 100644 --- a/src/main/java/io/stargate/sgv2/jsonapi/service/operation/model/impl/CreateCollectionOperation.java +++ b/src/main/java/io/stargate/sgv2/jsonapi/service/operation/model/impl/CreateCollectionOperation.java @@ -8,6 +8,7 @@ import io.stargate.sgv2.api.common.schema.SchemaManager; import io.stargate.sgv2.jsonapi.api.model.command.CommandContext; import io.stargate.sgv2.jsonapi.api.model.command.CommandResult; +import io.stargate.sgv2.jsonapi.config.DatabaseLimitsConfig; import io.stargate.sgv2.jsonapi.exception.ErrorCode; import io.stargate.sgv2.jsonapi.exception.JsonApiException; import io.stargate.sgv2.jsonapi.service.bridge.executor.CollectionSettings; @@ -21,6 +22,7 @@ public record CreateCollectionOperation( CommandContext commandContext, + DatabaseLimitsConfig dbLimitsConfig, ObjectMapper objectMapper, SchemaManager schemaManager, String name, @@ -42,6 +44,7 @@ public record CreateCollectionOperation( public static CreateCollectionOperation withVectorSearch( CommandContext commandContext, + DatabaseLimitsConfig dbLimitsConfig, ObjectMapper objectMapper, SchemaManager schemaManager, String name, @@ -50,6 +53,7 @@ public static CreateCollectionOperation withVectorSearch( String vectorize) { return new CreateCollectionOperation( commandContext, + dbLimitsConfig, objectMapper, schemaManager, name, @@ -61,17 +65,21 @@ public static CreateCollectionOperation withVectorSearch( public static CreateCollectionOperation withoutVectorSearch( CommandContext commandContext, + DatabaseLimitsConfig dbLimitsConfig, ObjectMapper objectMapper, SchemaManager schemaManager, String name) { return new CreateCollectionOperation( - commandContext, objectMapper, schemaManager, name, false, 0, null, null); + commandContext, dbLimitsConfig, objectMapper, schemaManager, name, false, 0, null, null); } @Override public Uni> execute(QueryExecutor queryExecutor) { return schemaManager - .getTable(commandContext.namespace(), name, MISSING_KEYSPACE_FUNCTION) + .getTables(commandContext.namespace(), MISSING_KEYSPACE_FUNCTION) + .collect() + .asList() + .map(tables -> findTableAndValidateLimits(tables, name)) .onItem() .transformToUni( table -> { @@ -166,6 +174,29 @@ private Uni> executeCollectionCreation(QueryExecutor que return indexResult.onItem().transform(res -> new SchemaChangeResult(res)); } + /** + * Method for finding existing table with given name, if one exists and returning that table; or + * if not, verify maximum table limit and return null. + * + * @return Existing table with given name, if any; {@code null} if not + */ + Schema.CqlTable findTableAndValidateLimits(List tables, String name) { + for (Schema.CqlTable table : tables) { + if (table.getName().equals(name)) { + return table; + } + } + final int MAX_COLLECTIONS = dbLimitsConfig.maxCollections(); + if (tables.size() >= MAX_COLLECTIONS) { + throw new JsonApiException( + ErrorCode.TOO_MANY_COLLECTIONS, + String.format( + "%s: number of collections in database cannot exceed %d, already have %d", + ErrorCode.TOO_MANY_COLLECTIONS.getMessage(), MAX_COLLECTIONS, tables.size())); + } + return null; + } + protected SimpleStatement getCreateTable(String keyspace, String table) { if (vectorSearch) { String createTableWithVector = diff --git a/src/main/java/io/stargate/sgv2/jsonapi/service/processor/MeteredCommandProcessor.java b/src/main/java/io/stargate/sgv2/jsonapi/service/processor/MeteredCommandProcessor.java index 7d2b60cdfa..bcffda0ced 100644 --- a/src/main/java/io/stargate/sgv2/jsonapi/service/processor/MeteredCommandProcessor.java +++ b/src/main/java/io/stargate/sgv2/jsonapi/service/processor/MeteredCommandProcessor.java @@ -114,13 +114,18 @@ private Tags getCustomTags(CommandContext commandContext, Command command, Comma if (null != result.errors() && !result.errors().isEmpty()) { errorTag = errorTrue; String errorClass = - (String) result.errors().get(0).fields().getOrDefault("exceptionClass", UNKNOWN_VALUE); + (String) + result + .errors() + .get(0) + .fieldsForMetricsTag() + .getOrDefault("exceptionClass", UNKNOWN_VALUE); errorClassTag = Tag.of(jsonApiMetricsConfig.errorClass(), errorClass); String errorCode = - (String) result.errors().get(0).fields().getOrDefault("errorCode", UNKNOWN_VALUE); + (String) + result.errors().get(0).fieldsForMetricsTag().getOrDefault("errorCode", UNKNOWN_VALUE); errorCodeTag = Tag.of(jsonApiMetricsConfig.errorCode(), errorCode); } - Tag vectorEnabled = commandContext.isVectorEnabled() ? Tag.of(jsonApiMetricsConfig.vectorEnabled(), "true") diff --git a/src/main/java/io/stargate/sgv2/jsonapi/service/resolver/model/impl/CountDocumentsCommandResolver.java b/src/main/java/io/stargate/sgv2/jsonapi/service/resolver/model/impl/CountDocumentsCommandResolver.java index 4df7c4c8d8..680358f888 100644 --- a/src/main/java/io/stargate/sgv2/jsonapi/service/resolver/model/impl/CountDocumentsCommandResolver.java +++ b/src/main/java/io/stargate/sgv2/jsonapi/service/resolver/model/impl/CountDocumentsCommandResolver.java @@ -2,7 +2,7 @@ import io.stargate.sgv2.jsonapi.api.model.command.CommandContext; import io.stargate.sgv2.jsonapi.api.model.command.clause.filter.LogicalExpression; -import io.stargate.sgv2.jsonapi.api.model.command.impl.CountDocumentsCommands; +import io.stargate.sgv2.jsonapi.api.model.command.impl.CountDocumentsCommand; import io.stargate.sgv2.jsonapi.service.operation.model.CountOperation; import io.stargate.sgv2.jsonapi.service.operation.model.Operation; import io.stargate.sgv2.jsonapi.service.resolver.model.CommandResolver; @@ -10,22 +10,22 @@ import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; -/** Resolves the {@link CountDocumentsCommands } */ +/** Resolves the {@link CountDocumentsCommand } */ @ApplicationScoped -public class CountDocumentsCommandResolver extends FilterableResolver - implements CommandResolver { +public class CountDocumentsCommandResolver extends FilterableResolver + implements CommandResolver { @Inject public CountDocumentsCommandResolver() { super(); } @Override - public Class getCommandClass() { - return CountDocumentsCommands.class; + public Class getCommandClass() { + return CountDocumentsCommand.class; } @Override - public Operation resolveCommand(CommandContext ctx, CountDocumentsCommands command) { + public Operation resolveCommand(CommandContext ctx, CountDocumentsCommand command) { LogicalExpression logicalExpression = resolve(ctx, command); return new CountOperation(ctx, logicalExpression); } diff --git a/src/main/java/io/stargate/sgv2/jsonapi/service/resolver/model/impl/CreateCollectionCommandResolver.java b/src/main/java/io/stargate/sgv2/jsonapi/service/resolver/model/impl/CreateCollectionCommandResolver.java index ee9201fdff..9fd1e2232a 100644 --- a/src/main/java/io/stargate/sgv2/jsonapi/service/resolver/model/impl/CreateCollectionCommandResolver.java +++ b/src/main/java/io/stargate/sgv2/jsonapi/service/resolver/model/impl/CreateCollectionCommandResolver.java @@ -6,6 +6,7 @@ import io.stargate.sgv2.api.common.schema.SchemaManager; import io.stargate.sgv2.jsonapi.api.model.command.CommandContext; import io.stargate.sgv2.jsonapi.api.model.command.impl.CreateCollectionCommand; +import io.stargate.sgv2.jsonapi.config.DatabaseLimitsConfig; import io.stargate.sgv2.jsonapi.config.DocumentLimitsConfig; import io.stargate.sgv2.jsonapi.exception.ErrorCode; import io.stargate.sgv2.jsonapi.exception.JsonApiException; @@ -23,21 +24,24 @@ public class CreateCollectionCommandResolver implements CommandResolver documentLimitsConfig.maxVectorEmbeddingLength()) { throw new JsonApiException( ErrorCode.VECTOR_SEARCH_FIELD_TOO_BIG, @@ -75,15 +79,16 @@ public Operation resolveCommand(CommandContext ctx, CreateCollectionCommand comm return CreateCollectionOperation.withVectorSearch( ctx, + dbLimitsConfig, objectMapper, schemaManager, command.name(), vectorSize, - command.options().vector().function(), + command.options().vector().metric(), vectorize); } else { return CreateCollectionOperation.withoutVectorSearch( - ctx, objectMapper, schemaManager, command.name()); + ctx, dbLimitsConfig, objectMapper, schemaManager, command.name()); } } } diff --git a/src/main/java/io/stargate/sgv2/jsonapi/service/resolver/model/impl/matcher/FilterableResolver.java b/src/main/java/io/stargate/sgv2/jsonapi/service/resolver/model/impl/matcher/FilterableResolver.java index 71240b4903..31ea206875 100644 --- a/src/main/java/io/stargate/sgv2/jsonapi/service/resolver/model/impl/matcher/FilterableResolver.java +++ b/src/main/java/io/stargate/sgv2/jsonapi/service/resolver/model/impl/matcher/FilterableResolver.java @@ -4,6 +4,7 @@ import io.stargate.sgv2.jsonapi.api.model.command.CommandContext; import io.stargate.sgv2.jsonapi.api.model.command.Filterable; import io.stargate.sgv2.jsonapi.api.model.command.clause.filter.*; +import io.stargate.sgv2.jsonapi.config.DocumentLimitsConfig; import io.stargate.sgv2.jsonapi.exception.ErrorCode; import io.stargate.sgv2.jsonapi.exception.JsonApiException; import io.stargate.sgv2.jsonapi.service.operation.model.impl.DBFilterBase; @@ -38,6 +39,7 @@ public abstract class FilterableResolver { private static final Object SIZE_GROUP = new Object(); private static final Object ARRAY_EQUALS = new Object(); private static final Object SUB_DOC_EQUALS = new Object(); + @Inject DocumentLimitsConfig docLimits; @Inject public FilterableResolver() { @@ -87,7 +89,17 @@ public FilterableResolver() { } protected LogicalExpression resolve(CommandContext commandContext, T command) { - return matchRules.apply(commandContext, command); + LogicalExpression filter = matchRules.apply(commandContext, command); + if (filter.getTotalComparisonExpressionCount() > docLimits.maxFilterObjectProperties()) { + throw new JsonApiException( + ErrorCode.FILTER_FIELDS_LIMIT_VIOLATION, + String.format( + "%s: filter has %d fields, exceeds maximum allowed %s", + ErrorCode.FILTER_FIELDS_LIMIT_VIOLATION.getMessage(), + filter.getTotalComparisonExpressionCount(), + docLimits.maxFilterObjectProperties())); + } + return filter; } public static List findById(CaptureExpression captureExpression) { diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 685c865756..e475da55dd 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -3,6 +3,13 @@ stargate: + database: + limits: + max-collections: 5 + + debug: + enabled: false + # disable all sgv2 exception mappers, handled differently exception-mappers: enabled: false @@ -99,3 +106,7 @@ quarkus: # adapt path of the open api definitions smallrye-openapi: path: /api/json/openapi + native: + # Adding com.datastax.oss.driver.internal.core.metadata.MetadataManager to the list of classes that are initialized + # at run time while building the native image. This is for the issue https://github.com/stargate/jsonapi/issues/597 + additional-build-args: --initialize-at-run-time=com.datastax.oss.driver.internal.core.metadata.MetadataManager \ No newline at end of file diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/configuration/ObjectMapperConfigurationTest.java b/src/test/java/io/stargate/sgv2/jsonapi/api/configuration/ObjectMapperConfigurationTest.java index 5955278a2a..6e931feae3 100644 --- a/src/test/java/io/stargate/sgv2/jsonapi/api/configuration/ObjectMapperConfigurationTest.java +++ b/src/test/java/io/stargate/sgv2/jsonapi/api/configuration/ObjectMapperConfigurationTest.java @@ -18,7 +18,7 @@ import io.stargate.sgv2.jsonapi.api.model.command.clause.sort.SortClause; import io.stargate.sgv2.jsonapi.api.model.command.clause.sort.SortExpression; import io.stargate.sgv2.jsonapi.api.model.command.clause.update.UpdateClause; -import io.stargate.sgv2.jsonapi.api.model.command.impl.CountDocumentsCommands; +import io.stargate.sgv2.jsonapi.api.model.command.impl.CountDocumentsCommand; import io.stargate.sgv2.jsonapi.api.model.command.impl.CreateCollectionCommand; import io.stargate.sgv2.jsonapi.api.model.command.impl.CreateEmbeddingServiceCommand; import io.stargate.sgv2.jsonapi.api.model.command.impl.DeleteOneCommand; @@ -365,8 +365,8 @@ public void happyPathVectorSearch() throws Exception { "name": "some_name", "options": { "vector": { - "size": 5, - "function": "cosine" + "dimension": 5, + "metric": "cosine" } } } @@ -383,8 +383,39 @@ public void happyPathVectorSearch() throws Exception { assertThat(name).isNotNull(); assertThat(createCollection.options()).isNotNull(); assertThat(createCollection.options().vector()).isNotNull(); - assertThat(createCollection.options().vector().size()).isEqualTo(5); - assertThat(createCollection.options().vector().function()).isEqualTo("cosine"); + assertThat(createCollection.options().vector().dimension()).isEqualTo(5); + assertThat(createCollection.options().vector().metric()).isEqualTo("cosine"); + }); + } + + @Test + public void happyPathVectorSearchLegacyNames() throws Exception { + Command result = + objectMapper.readValue( + """ + { + "createCollection": { + "name": "some_name", + "options": { + "vector": { + "size": 5, + "function": "cosine" + } + } + } + } + """, + Command.class); + + assertThat(result) + .isInstanceOfSatisfying( + CreateCollectionCommand.class, + createCollection -> { + assertThat(createCollection.name()).isNotNull(); + assertThat(createCollection.options()).isNotNull(); + assertThat(createCollection.options().vector()).isNotNull(); + assertThat(createCollection.options().vector().dimension()).isEqualTo(5); + assertThat(createCollection.options().vector().metric()).isEqualTo("cosine"); }); } @@ -397,8 +428,8 @@ public void happyPathVectorizeSearch() throws Exception { "name": "some_name", "options": { "vector": { - "size": 5, - "function": "cosine" + "dimension": 5, + "metric": "cosine" }, "vectorize" : { "service" : "my_service", @@ -421,8 +452,8 @@ public void happyPathVectorizeSearch() throws Exception { assertThat(name).isNotNull(); assertThat(createCollection.options()).isNotNull(); assertThat(createCollection.options().vector()).isNotNull(); - assertThat(createCollection.options().vector().size()).isEqualTo(5); - assertThat(createCollection.options().vector().function()).isEqualTo("cosine"); + assertThat(createCollection.options().vector().dimension()).isEqualTo(5); + assertThat(createCollection.options().vector().metric()).isEqualTo("cosine"); assertThat(createCollection.options().vectorize()).isNotNull(); assertThat(createCollection.options().vectorize().service()) .isEqualTo("my_service"); @@ -441,7 +472,7 @@ public void happyPathVectorSearchDefaultFunction() throws Exception { "name": "some_name", "options": { "vector": { - "size": 5 + "dimension": 5 } } } @@ -458,8 +489,8 @@ public void happyPathVectorSearchDefaultFunction() throws Exception { assertThat(name).isNotNull(); assertThat(createCollection.options()).isNotNull(); assertThat(createCollection.options().vector()).isNotNull(); - assertThat(createCollection.options().vector().size()).isEqualTo(5); - assertThat(createCollection.options().vector().function()).isEqualTo("cosine"); + assertThat(createCollection.options().vector().dimension()).isEqualTo(5); + assertThat(createCollection.options().vector().metric()).isEqualTo("cosine"); }); } } @@ -586,7 +617,7 @@ public void happyPath() throws Exception { Command result = objectMapper.readValue(json, Command.class); assertThat(result) .isInstanceOfSatisfying( - CountDocumentsCommands.class, + CountDocumentsCommand.class, countCommand -> { FilterClause filterClause = countCommand.filterClause(); assertThat(filterClause).isNotNull(); diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/model/command/serializers/ErrorSerializerTest.java b/src/test/java/io/stargate/sgv2/jsonapi/api/model/command/serializers/ErrorSerializerTest.java index c5734fa198..a5b21b0ad7 100644 --- a/src/test/java/io/stargate/sgv2/jsonapi/api/model/command/serializers/ErrorSerializerTest.java +++ b/src/test/java/io/stargate/sgv2/jsonapi/api/model/command/serializers/ErrorSerializerTest.java @@ -27,7 +27,11 @@ class Serialize { @Test public void happyPath() throws Exception { CommandResult.Error error = - new CommandResult.Error("My message.", Map.of("field", "value"), Response.Status.OK); + new CommandResult.Error( + "My message.", + Map.of("field", "value"), + Map.of("field", "value"), + Response.Status.OK); String result = objectMapper.writeValueAsString(error); @@ -39,7 +43,8 @@ public void happyPath() throws Exception { @Test public void withoutProps() throws Exception { CommandResult.Error error = - new CommandResult.Error("My message.", Collections.emptyMap(), Response.Status.OK); + new CommandResult.Error( + "My message.", Collections.emptyMap(), Collections.emptyMap(), Response.Status.OK); String result = objectMapper.writeValueAsString(error); @@ -53,7 +58,10 @@ public void messageFieldNotAllowed() throws Exception { catchThrowable( () -> new CommandResult.Error( - "My message.", Map.of("message", "value"), Response.Status.OK)); + "My message.", + Map.of("message", "value"), + Map.of("message", "value"), + Response.Status.OK)); assertThat(throwable) .isInstanceOf(IllegalArgumentException.class) @@ -62,7 +70,7 @@ public void messageFieldNotAllowed() throws Exception { @Test public void withNulls() throws Exception { - CommandResult.Error error = new CommandResult.Error(null, null, Response.Status.OK); + CommandResult.Error error = new CommandResult.Error(null, null, null, Response.Status.OK); String result = objectMapper.writeValueAsString(error); diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/AbstractCollectionIntegrationTestBase.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/AbstractCollectionIntegrationTestBase.java index 962df34003..eef6645021 100644 --- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/AbstractCollectionIntegrationTestBase.java +++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/AbstractCollectionIntegrationTestBase.java @@ -8,7 +8,7 @@ import static org.hamcrest.Matchers.nullValue; import io.restassured.http.ContentType; -import io.stargate.sgv2.api.common.config.constants.HttpConstants; +import io.stargate.sgv2.jsonapi.config.constants.HttpConstants; import org.apache.commons.lang3.RandomStringUtils; import org.junit.jupiter.api.BeforeAll; diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/AbstractNamespaceIntegrationTestBase.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/AbstractNamespaceIntegrationTestBase.java index 717f306819..116cabd9e1 100644 --- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/AbstractNamespaceIntegrationTestBase.java +++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/AbstractNamespaceIntegrationTestBase.java @@ -8,7 +8,7 @@ import io.restassured.RestAssured; import io.restassured.http.ContentType; -import io.stargate.sgv2.api.common.config.constants.HttpConstants; +import io.stargate.sgv2.jsonapi.config.constants.HttpConstants; import java.util.List; import org.apache.commons.lang3.RandomStringUtils; import org.eclipse.microprofile.config.ConfigProvider; @@ -38,6 +38,10 @@ public static void enableLog() { @BeforeAll public void createNamespace() { + createNamespace(namespaceName); + } + + protected void createNamespace(String nsToCreate) { String json = """ { @@ -46,7 +50,7 @@ public void createNamespace() { } } """ - .formatted(namespaceName); + .formatted(nsToCreate); given() .port(getTestPort()) diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/CollectionResourceIntegrationTest.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/CollectionResourceIntegrationTest.java index 80997e8818..910f64a87e 100644 --- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/CollectionResourceIntegrationTest.java +++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/CollectionResourceIntegrationTest.java @@ -10,7 +10,7 @@ import io.quarkus.test.common.QuarkusTestResource; import io.quarkus.test.junit.QuarkusIntegrationTest; import io.restassured.http.ContentType; -import io.stargate.sgv2.api.common.config.constants.HttpConstants; +import io.stargate.sgv2.jsonapi.config.constants.HttpConstants; import io.stargate.sgv2.jsonapi.testresource.DseTestResource; import org.apache.commons.lang3.RandomStringUtils; import org.junit.jupiter.api.Nested; @@ -37,7 +37,7 @@ public void tokenMissing() { .body( "errors[0].message", is( - "Role unauthorized for operation: Missing token, expecting one in the X-Cassandra-Token header.")); + "Role unauthorized for operation: Missing token, expecting one in the Token header.")); } @Test diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/CountIntegrationTest.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/CountIntegrationTest.java index d7a6ae0a04..236c6ac322 100644 --- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/CountIntegrationTest.java +++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/CountIntegrationTest.java @@ -9,7 +9,7 @@ import io.quarkus.test.common.QuarkusTestResource; import io.quarkus.test.junit.QuarkusIntegrationTest; import io.restassured.http.ContentType; -import io.stargate.sgv2.api.common.config.constants.HttpConstants; +import io.stargate.sgv2.jsonapi.config.constants.HttpConstants; import io.stargate.sgv2.jsonapi.testresource.DseTestResource; import org.junit.jupiter.api.ClassOrderer; import org.junit.jupiter.api.MethodOrderer; @@ -791,7 +791,7 @@ public void byBooleanColumn() { class Metrics { @Test public void checkMetrics() { - CountIntegrationTest.super.checkMetrics("CountDocumentsCommands"); + CountIntegrationTest.super.checkMetrics("CountDocumentsCommand"); } } } diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/CreateCollectionIntegrationTest.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/CreateCollectionIntegrationTest.java index 09986d4dac..b04dcc1e4e 100644 --- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/CreateCollectionIntegrationTest.java +++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/CreateCollectionIntegrationTest.java @@ -8,7 +8,8 @@ import io.quarkus.test.common.QuarkusTestResource; import io.quarkus.test.junit.QuarkusIntegrationTest; import io.restassured.http.ContentType; -import io.stargate.sgv2.api.common.config.constants.HttpConstants; +import io.stargate.sgv2.jsonapi.config.DatabaseLimitsConfig; +import io.stargate.sgv2.jsonapi.config.constants.HttpConstants; import io.stargate.sgv2.jsonapi.testresource.DseTestResource; import org.apache.commons.lang3.RandomStringUtils; import org.junit.jupiter.api.ClassOrderer; @@ -21,7 +22,6 @@ @QuarkusTestResource(DseTestResource.class) @TestClassOrder(ClassOrderer.OrderAnnotation.class) class CreateCollectionIntegrationTest extends AbstractNamespaceIntegrationTestBase { - @Nested @Order(1) class CreateCollection { @@ -271,6 +271,74 @@ public void duplicateVectorCollectionNameWithDiffSetting() { @Nested @Order(2) + class TooManyCollections { + @Test + public void enforceMaxCollections() { + // Cannot @Inject configs into ITs so rely on constant for default values: + final int MAX_COLLECTIONS = DatabaseLimitsConfig.DEFAULT_MAX_COLLECTIONS; + // Don't use auto-generated namespace that rest of the test uses + final String NS = "ns_too_many_collections"; + createNamespace(NS); + final String createTemplate = + """ + { + "createCollection": { + "name": "tooMany_%d" + } + } + """; + + // First create maximum number of collections + for (int i = 1; i <= MAX_COLLECTIONS; ++i) { + String json = createTemplate.formatted(i); + given() + .header(HttpConstants.AUTHENTICATION_TOKEN_HEADER_NAME, getAuthToken()) + .contentType(ContentType.JSON) + .body(json) + .when() + .post(NamespaceResource.BASE_PATH, NS) + .then() + .statusCode(200) + .body("status.ok", is(1)); + } + // And then failure + String json = createTemplate.formatted(99); + given() + .header(HttpConstants.AUTHENTICATION_TOKEN_HEADER_NAME, getAuthToken()) + .contentType(ContentType.JSON) + .body(json) + .when() + .post(NamespaceResource.BASE_PATH, NS) + .then() + .statusCode(200) + .body("status", is(nullValue())) + .body("data", is(nullValue())) + .body( + "errors[0].message", + is( + "Too many collections: number of collections in database cannot exceed " + + MAX_COLLECTIONS + + ", already have " + + MAX_COLLECTIONS)) + .body("errors[0].errorCode", is("TOO_MANY_COLLECTIONS")) + .body("errors[0].exceptionClass", is("JsonApiException")); + + // But then verify that re-creating an existing one should still succeed + // (if using same settings) + given() + .header(HttpConstants.AUTHENTICATION_TOKEN_HEADER_NAME, getAuthToken()) + .contentType(ContentType.JSON) + .body(createTemplate.formatted(MAX_COLLECTIONS)) + .when() + .post(NamespaceResource.BASE_PATH, NS) + .then() + .statusCode(200) + .body("status.ok", is(1)); + } + } + + @Nested + @Order(99) class Metrics { @Test public void checkMetrics() { diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/CreateNamespaceIntegrationTest.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/CreateNamespaceIntegrationTest.java index 84bc6e4a98..11da7727e6 100644 --- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/CreateNamespaceIntegrationTest.java +++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/CreateNamespaceIntegrationTest.java @@ -10,7 +10,7 @@ import io.quarkus.test.junit.QuarkusIntegrationTest; import io.restassured.RestAssured; import io.restassured.http.ContentType; -import io.stargate.sgv2.api.common.config.constants.HttpConstants; +import io.stargate.sgv2.jsonapi.config.constants.HttpConstants; import io.stargate.sgv2.jsonapi.testresource.DseTestResource; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/DeleteCollectionIntegrationTest.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/DeleteCollectionIntegrationTest.java index 70122f7ca2..a385d9abbd 100644 --- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/DeleteCollectionIntegrationTest.java +++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/DeleteCollectionIntegrationTest.java @@ -9,7 +9,7 @@ import io.quarkus.test.common.QuarkusTestResource; import io.quarkus.test.junit.QuarkusIntegrationTest; import io.restassured.http.ContentType; -import io.stargate.sgv2.api.common.config.constants.HttpConstants; +import io.stargate.sgv2.jsonapi.config.constants.HttpConstants; import io.stargate.sgv2.jsonapi.testresource.DseTestResource; import org.apache.commons.lang3.RandomStringUtils; import org.junit.jupiter.api.ClassOrderer; diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/DeleteManyIntegrationTest.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/DeleteManyIntegrationTest.java index 54ce1c8088..660208b20f 100644 --- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/DeleteManyIntegrationTest.java +++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/DeleteManyIntegrationTest.java @@ -15,7 +15,7 @@ import io.quarkus.test.common.QuarkusTestResource; import io.quarkus.test.junit.QuarkusIntegrationTest; import io.restassured.http.ContentType; -import io.stargate.sgv2.api.common.config.constants.HttpConstants; +import io.stargate.sgv2.jsonapi.config.constants.HttpConstants; import io.stargate.sgv2.jsonapi.testresource.DseTestResource; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicInteger; diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/DeleteOneIntegrationTest.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/DeleteOneIntegrationTest.java index 75d953aed9..ff7d9cb81e 100644 --- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/DeleteOneIntegrationTest.java +++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/DeleteOneIntegrationTest.java @@ -13,7 +13,7 @@ import io.quarkus.test.common.QuarkusTestResource; import io.quarkus.test.junit.QuarkusIntegrationTest; import io.restassured.http.ContentType; -import io.stargate.sgv2.api.common.config.constants.HttpConstants; +import io.stargate.sgv2.jsonapi.config.constants.HttpConstants; import io.stargate.sgv2.jsonapi.testresource.DseTestResource; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicInteger; diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/DropNamespaceIntegrationTest.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/DropNamespaceIntegrationTest.java index 07f56d6b98..8a91bec58f 100644 --- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/DropNamespaceIntegrationTest.java +++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/DropNamespaceIntegrationTest.java @@ -9,7 +9,8 @@ import io.quarkus.test.common.QuarkusTestResource; import io.quarkus.test.junit.QuarkusIntegrationTest; import io.restassured.http.ContentType; -import io.stargate.sgv2.api.common.config.constants.HttpConstants; +// import io.stargate.sgv2.jsonapi.config.constants.HttpConstants; +import io.stargate.sgv2.jsonapi.config.constants.HttpConstants; import io.stargate.sgv2.jsonapi.testresource.DseTestResource; import org.apache.commons.lang3.RandomStringUtils; import org.junit.jupiter.api.ClassOrderer; diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/FindCollectionsIntegrationTest.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/FindCollectionsIntegrationTest.java index b050b283d0..1c4accf3b5 100644 --- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/FindCollectionsIntegrationTest.java +++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/FindCollectionsIntegrationTest.java @@ -12,7 +12,7 @@ import io.quarkus.test.common.QuarkusTestResource; import io.quarkus.test.junit.QuarkusIntegrationTest; import io.restassured.http.ContentType; -import io.stargate.sgv2.api.common.config.constants.HttpConstants; +import io.stargate.sgv2.jsonapi.config.constants.HttpConstants; import io.stargate.sgv2.jsonapi.testresource.DseTestResource; import org.apache.commons.lang3.RandomStringUtils; import org.junit.jupiter.api.ClassOrderer; @@ -88,8 +88,8 @@ public void happyPathWithExplain() { "name": "%s", "options": { "vector": { - "size": 5, - "function": "cosine" + "dimension": 5, + "metric": "cosine" } } } @@ -120,8 +120,8 @@ public void happyPathWithExplain() { "name": "%s", "options": { "vector": { - "size": 5, - "function": "cosine" + "dimension": 5, + "metric": "cosine" } } } diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/FindIntegrationTest.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/FindIntegrationTest.java index f17c705770..7bcdebd16a 100644 --- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/FindIntegrationTest.java +++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/FindIntegrationTest.java @@ -3,17 +3,13 @@ import static io.restassured.RestAssured.given; import static io.stargate.sgv2.common.IntegrationTestUtils.getAuthToken; import static net.javacrumbs.jsonunit.JsonMatchers.jsonEquals; -import static org.hamcrest.Matchers.containsInAnyOrder; -import static org.hamcrest.Matchers.hasSize; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.notNullValue; -import static org.hamcrest.Matchers.nullValue; -import static org.hamcrest.Matchers.startsWith; +import static org.hamcrest.Matchers.*; import io.quarkus.test.common.QuarkusTestResource; import io.quarkus.test.junit.QuarkusIntegrationTest; import io.restassured.http.ContentType; -import io.stargate.sgv2.api.common.config.constants.HttpConstants; +import io.stargate.sgv2.jsonapi.config.DocumentLimitsConfig; +import io.stargate.sgv2.jsonapi.config.constants.HttpConstants; import io.stargate.sgv2.jsonapi.testresource.DseTestResource; import org.junit.jupiter.api.ClassOrderer; import org.junit.jupiter.api.MethodOrderer; @@ -1441,6 +1437,52 @@ public void OrWithIdIn() { .body("errors", is(nullValue())) .body("data.documents", hasSize(3)); } + + @Test + public void exceedMaxFieldInFilter() { + // Max allowed 64, so fail with 65 + String json = createJsonStringWithNFilterFields(65); + given() + .header(HttpConstants.AUTHENTICATION_TOKEN_HEADER_NAME, getAuthToken()) + .contentType(ContentType.JSON) + .body(json) + .when() + .post(CollectionResource.BASE_PATH, namespaceName, collectionName) + .then() + .statusCode(200) + .body("status", is(nullValue())) + .body("data", is(nullValue())) + .body( + "errors[0].message", + endsWith( + " filter has 65 fields, exceeds maximum allowed " + + DocumentLimitsConfig.DEFAULT_MAX_FILTER_SIZE)) + .body("errors[0].errorCode", is("FILTER_FIELDS_LIMIT_VIOLATION")) + .body("errors[0].exceptionClass", is("JsonApiException")); + } + + private static String createJsonStringWithNFilterFields(int numberOfFields) { + StringBuilder sb = new StringBuilder(); + + sb.append("{\n"); + sb.append(" \"find\": {\n"); + sb.append(" \"filter\": {\n"); + + for (int i = 1; i <= numberOfFields; i++) { + sb.append(" \"name").append(i).append("\": \"").append(i).append("\""); + if (i < numberOfFields) { + sb.append(",\n"); + } else { + sb.append("\n"); + } + } + + sb.append(" }\n"); + sb.append(" }\n"); + sb.append("}"); + + return sb.toString(); + } } @Nested diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/FindNamespacesIntegrationTest.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/FindNamespacesIntegrationTest.java index 67cbaf1713..be513ee852 100644 --- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/FindNamespacesIntegrationTest.java +++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/FindNamespacesIntegrationTest.java @@ -9,7 +9,7 @@ import io.quarkus.test.common.QuarkusTestResource; import io.quarkus.test.junit.QuarkusIntegrationTest; import io.restassured.http.ContentType; -import io.stargate.sgv2.api.common.config.constants.HttpConstants; +import io.stargate.sgv2.jsonapi.config.constants.HttpConstants; import io.stargate.sgv2.jsonapi.testresource.DseTestResource; import org.junit.jupiter.api.ClassOrderer; import org.junit.jupiter.api.Nested; diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/FindOneAndDeleteIntegrationTest.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/FindOneAndDeleteIntegrationTest.java index caf69d0d7a..438b34cf5c 100644 --- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/FindOneAndDeleteIntegrationTest.java +++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/FindOneAndDeleteIntegrationTest.java @@ -9,7 +9,7 @@ import io.quarkus.test.common.QuarkusTestResource; import io.quarkus.test.junit.QuarkusIntegrationTest; import io.restassured.http.ContentType; -import io.stargate.sgv2.api.common.config.constants.HttpConstants; +import io.stargate.sgv2.jsonapi.config.constants.HttpConstants; import io.stargate.sgv2.jsonapi.testresource.DseTestResource; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicReferenceArray; diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/FindOneAndReplaceIntegrationTest.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/FindOneAndReplaceIntegrationTest.java index 480e716c16..4a672a8366 100644 --- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/FindOneAndReplaceIntegrationTest.java +++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/FindOneAndReplaceIntegrationTest.java @@ -11,7 +11,7 @@ import io.quarkus.test.common.QuarkusTestResource; import io.quarkus.test.junit.QuarkusIntegrationTest; import io.restassured.http.ContentType; -import io.stargate.sgv2.api.common.config.constants.HttpConstants; +import io.stargate.sgv2.jsonapi.config.constants.HttpConstants; import io.stargate.sgv2.jsonapi.testresource.DseTestResource; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.ClassOrderer; diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/FindOneAndUpdateIntegrationTest.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/FindOneAndUpdateIntegrationTest.java index 4abe609d00..cc874f5678 100644 --- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/FindOneAndUpdateIntegrationTest.java +++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/FindOneAndUpdateIntegrationTest.java @@ -16,7 +16,7 @@ import io.quarkus.test.common.QuarkusTestResource; import io.quarkus.test.junit.QuarkusIntegrationTest; import io.restassured.http.ContentType; -import io.stargate.sgv2.api.common.config.constants.HttpConstants; +import io.stargate.sgv2.jsonapi.config.constants.HttpConstants; import io.stargate.sgv2.jsonapi.testresource.DseTestResource; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.ClassOrderer; diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/FindOneIntegrationTest.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/FindOneIntegrationTest.java index 49d9996178..ab3e1bb55f 100644 --- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/FindOneIntegrationTest.java +++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/FindOneIntegrationTest.java @@ -12,7 +12,7 @@ import io.quarkus.test.common.QuarkusTestResource; import io.quarkus.test.junit.QuarkusIntegrationTest; import io.restassured.http.ContentType; -import io.stargate.sgv2.api.common.config.constants.HttpConstants; +import io.stargate.sgv2.jsonapi.config.constants.HttpConstants; import io.stargate.sgv2.jsonapi.testresource.DseTestResource; import org.junit.jupiter.api.ClassOrderer; import org.junit.jupiter.api.MethodOrderer; diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/FindOneWithProjectionIntegrationTest.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/FindOneWithProjectionIntegrationTest.java index 8d3166e654..038e11c796 100644 --- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/FindOneWithProjectionIntegrationTest.java +++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/FindOneWithProjectionIntegrationTest.java @@ -10,7 +10,7 @@ import io.quarkus.test.common.QuarkusTestResource; import io.quarkus.test.junit.QuarkusIntegrationTest; import io.restassured.http.ContentType; -import io.stargate.sgv2.api.common.config.constants.HttpConstants; +import io.stargate.sgv2.jsonapi.config.constants.HttpConstants; import io.stargate.sgv2.jsonapi.testresource.DseTestResource; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Nested; diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/FindOperationWithSortIntegrationTest.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/FindOperationWithSortIntegrationTest.java index 91fc1e0819..8bc739d613 100644 --- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/FindOperationWithSortIntegrationTest.java +++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/FindOperationWithSortIntegrationTest.java @@ -15,7 +15,7 @@ import io.quarkus.test.common.QuarkusTestResource; import io.quarkus.test.junit.QuarkusIntegrationTest; import io.restassured.http.ContentType; -import io.stargate.sgv2.api.common.config.constants.HttpConstants; +import io.stargate.sgv2.jsonapi.config.constants.HttpConstants; import io.stargate.sgv2.jsonapi.testresource.DseTestResource; import io.stargate.sgv2.jsonapi.util.JsonNodeComparator; import java.util.ArrayList; diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/GeneralResourceIntegrationTest.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/GeneralResourceIntegrationTest.java index fd0cb9e12f..fd9245a035 100644 --- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/GeneralResourceIntegrationTest.java +++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/GeneralResourceIntegrationTest.java @@ -11,7 +11,7 @@ import io.quarkus.test.junit.QuarkusIntegrationTest; import io.restassured.RestAssured; import io.restassured.http.ContentType; -import io.stargate.sgv2.api.common.config.constants.HttpConstants; +import io.stargate.sgv2.jsonapi.config.constants.HttpConstants; import io.stargate.sgv2.jsonapi.testresource.DseTestResource; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Nested; @@ -41,7 +41,7 @@ public void tokenMissing() { .body( "errors[0].message", is( - "Role unauthorized for operation: Missing token, expecting one in the X-Cassandra-Token header.")); + "Role unauthorized for operation: Missing token, expecting one in the Token header.")); } @Test diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/HttpStatusCodeIntegrationTest.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/HttpStatusCodeIntegrationTest.java index 4a29c10fc7..5bb4be092f 100644 --- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/HttpStatusCodeIntegrationTest.java +++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/HttpStatusCodeIntegrationTest.java @@ -11,7 +11,7 @@ import io.quarkus.test.common.QuarkusTestResource; import io.quarkus.test.junit.QuarkusIntegrationTest; import io.restassured.http.ContentType; -import io.stargate.sgv2.api.common.config.constants.HttpConstants; +import io.stargate.sgv2.jsonapi.config.constants.HttpConstants; import io.stargate.sgv2.jsonapi.testresource.DseTestResource; import org.hamcrest.core.AnyOf; import org.junit.jupiter.api.MethodOrderer; @@ -50,6 +50,28 @@ public void unauthenticated() { .body("errors[0].message", endsWith("UNAUTHENTICATED: Invalid token")); } + @Test + public void unauthenticatedNamespaceResource() { + String json = + """ + { + "createNamespace": { + "name": "unAuthenticated" + } + } + """; + given() + .header(HttpConstants.AUTHENTICATION_TOKEN_HEADER_NAME, "invalid token") + .contentType(ContentType.JSON) + .body(json) + .when() + .post(GeneralResource.BASE_PATH) + .then() + .statusCode(401) + .body("errors", is(notNullValue())) + .body("errors[0].message", endsWith("UNAUTHENTICATED: Invalid token")); + } + @Test public void regularError() { String json = @@ -65,7 +87,9 @@ public void regularError() { AnyOf anyOf = AnyOf.anyOf( endsWith("table %s.%s does not exist".formatted(namespaceName, "badCollection")), - endsWith("table %s does not exist".formatted("badCollection"))); + endsWith("table %s does not exist".formatted("badCollection")), + endsWith( + "Collection does not exist, collection name: %s".formatted("badCollection"))); given() .header(HttpConstants.AUTHENTICATION_TOKEN_HEADER_NAME, getAuthToken()) .contentType(ContentType.JSON) @@ -77,7 +101,7 @@ public void regularError() { .body("errors", is(notNullValue())) .body("errors[0].message", is(not(blankString()))) .body("errors[0].message", anyOf) - .body("errors[0].exceptionClass", is("InvalidQueryException")); + .body("errors[0].exceptionClass", is("JsonApiException")); } @Test diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/InsertIntegrationTest.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/InsertIntegrationTest.java index ac1255a930..99b6285e01 100644 --- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/InsertIntegrationTest.java +++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/InsertIntegrationTest.java @@ -19,7 +19,7 @@ import io.quarkus.test.common.QuarkusTestResource; import io.quarkus.test.junit.QuarkusIntegrationTest; import io.restassured.http.ContentType; -import io.stargate.sgv2.api.common.config.constants.HttpConstants; +import io.stargate.sgv2.jsonapi.config.constants.HttpConstants; import io.stargate.sgv2.jsonapi.testresource.DseTestResource; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.ClassOrderer; diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/LwtRetryIntegrationTest.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/LwtRetryIntegrationTest.java index cd13e4b2b2..0c1e47cdd5 100644 --- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/LwtRetryIntegrationTest.java +++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/LwtRetryIntegrationTest.java @@ -10,7 +10,7 @@ import io.quarkus.test.common.QuarkusTestResource; import io.quarkus.test.junit.QuarkusIntegrationTest; import io.restassured.http.ContentType; -import io.stargate.sgv2.api.common.config.constants.HttpConstants; +import io.stargate.sgv2.jsonapi.config.constants.HttpConstants; import io.stargate.sgv2.jsonapi.testresource.DseTestResource; import java.util.concurrent.CountDownLatch; import org.junit.jupiter.api.AfterEach; diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/NamespaceResourceIntegrationTest.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/NamespaceResourceIntegrationTest.java index 0f0564c9a2..341c4ba75f 100644 --- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/NamespaceResourceIntegrationTest.java +++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/NamespaceResourceIntegrationTest.java @@ -10,7 +10,7 @@ import io.quarkus.test.common.QuarkusTestResource; import io.quarkus.test.junit.QuarkusIntegrationTest; import io.restassured.http.ContentType; -import io.stargate.sgv2.api.common.config.constants.HttpConstants; +import io.stargate.sgv2.jsonapi.config.constants.HttpConstants; import io.stargate.sgv2.jsonapi.testresource.DseTestResource; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; @@ -34,7 +34,7 @@ public void tokenMissing() { .body( "errors[0].message", is( - "Role unauthorized for operation: Missing token, expecting one in the X-Cassandra-Token header.")); + "Role unauthorized for operation: Missing token, expecting one in the Token header.")); } @Test diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/UpdateManyIntegrationTest.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/UpdateManyIntegrationTest.java index 6f10f21738..3d06e5128d 100644 --- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/UpdateManyIntegrationTest.java +++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/UpdateManyIntegrationTest.java @@ -11,7 +11,7 @@ import io.quarkus.test.common.QuarkusTestResource; import io.quarkus.test.junit.QuarkusIntegrationTest; import io.restassured.http.ContentType; -import io.stargate.sgv2.api.common.config.constants.HttpConstants; +import io.stargate.sgv2.jsonapi.config.constants.HttpConstants; import io.stargate.sgv2.jsonapi.testresource.DseTestResource; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicReferenceArray; diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/UpdateOneIntegrationTest.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/UpdateOneIntegrationTest.java index 5bc8935270..2321420b0b 100644 --- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/UpdateOneIntegrationTest.java +++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/UpdateOneIntegrationTest.java @@ -10,7 +10,7 @@ import io.quarkus.test.common.QuarkusTestResource; import io.quarkus.test.junit.QuarkusIntegrationTest; import io.restassured.http.ContentType; -import io.stargate.sgv2.api.common.config.constants.HttpConstants; +import io.stargate.sgv2.jsonapi.config.constants.HttpConstants; import io.stargate.sgv2.jsonapi.testresource.DseTestResource; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicReferenceArray; diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/VectorSearchIntegrationTest.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/VectorSearchIntegrationTest.java index 3862bbcd16..d05bce7d9b 100644 --- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/VectorSearchIntegrationTest.java +++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/VectorSearchIntegrationTest.java @@ -8,8 +8,8 @@ import io.quarkus.test.common.QuarkusTestResource; import io.quarkus.test.junit.QuarkusIntegrationTest; import io.restassured.http.ContentType; -import io.stargate.sgv2.api.common.config.constants.HttpConstants; import io.stargate.sgv2.jsonapi.api.v1.metrics.JsonApiMetricsConfig; +import io.stargate.sgv2.jsonapi.config.constants.HttpConstants; import io.stargate.sgv2.jsonapi.exception.ErrorCode; import io.stargate.sgv2.jsonapi.testresource.DseTestResource; import org.junit.jupiter.api.ClassOrderer; @@ -44,8 +44,8 @@ public void happyPathVectorSearch() { "name" : "my_collection", "options": { "vector": { - "size": 5, - "function": "cosine" + "dimension": 5, + "metric": "cosine" } } } @@ -71,7 +71,7 @@ public void happyPathVectorSearchDefaultFunction() { "name" : "my_collection_default_function", "options": { "vector": { - "size": 5 + "dimension": 5 } } } @@ -105,8 +105,8 @@ public void failForTooBigVector() { "name" : "TooBigVectorCollection", "options": { "vector": { - "size": %d, - "function": "cosine" + "dimension": %d, + "metric": "cosine" } } } @@ -1776,8 +1776,8 @@ private static void createVectorCollection( "name" : "%s", "options": { "vector": { - "size": %d, - "function": "cosine" + "dimension": %d, + "metric": "cosine" } } } diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/VectorizeSearchIntegrationTest.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/VectorizeSearchIntegrationTest.java index f590a216d8..0d2fe4a664 100644 --- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/VectorizeSearchIntegrationTest.java +++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/VectorizeSearchIntegrationTest.java @@ -7,7 +7,7 @@ import io.quarkus.test.common.QuarkusTestResource; import io.quarkus.test.junit.QuarkusIntegrationTest; import io.restassured.http.ContentType; -import io.stargate.sgv2.api.common.config.constants.HttpConstants; +import io.stargate.sgv2.jsonapi.config.constants.HttpConstants; import io.stargate.sgv2.jsonapi.exception.ErrorCode; import io.stargate.sgv2.jsonapi.testresource.DseTestResource; import org.junit.jupiter.api.ClassOrderer; @@ -37,8 +37,8 @@ public void happyPathVectorSearch() { "name" : "my_collection_vectorize", "options": { "vector": { - "size": 5, - "function": "cosine" + "dimension": 5, + "metric": "cosine" }, "vectorize": { "service" : "custom", diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/response/CommandResultToRestResponseTest.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/response/CommandResultToRestResponseTest.java index 84a417ae8b..ed406aa9a3 100644 --- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/response/CommandResultToRestResponseTest.java +++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/response/CommandResultToRestResponseTest.java @@ -32,7 +32,10 @@ public void errorWithOkStatus() { new CommandResult( List.of( new CommandResult.Error( - "My message.", Map.of("field", "value"), Response.Status.OK))); + "My message.", + Map.of("field", "value"), + Map.of("field", "value"), + Response.Status.OK))); final RestResponse mappedResult = result.map(); assertThat(mappedResult.getStatus()).isEqualTo(RestResponse.Status.OK.getStatusCode()); } @@ -43,7 +46,10 @@ public void unauthorized() { new CommandResult( List.of( new CommandResult.Error( - "My message.", Map.of("field", "value"), Response.Status.UNAUTHORIZED))); + "My message.", + Map.of("field", "value"), + Map.of("field", "value"), + Response.Status.UNAUTHORIZED))); final RestResponse mappedResult = result.map(); assertThat(mappedResult.getStatus()) .isEqualTo(RestResponse.Status.UNAUTHORIZED.getStatusCode()); @@ -55,7 +61,10 @@ public void badGateway() { new CommandResult( List.of( new CommandResult.Error( - "My message.", Map.of("field", "value"), Response.Status.BAD_GATEWAY))); + "My message.", + Map.of("field", "value"), + Map.of("field", "value"), + Response.Status.BAD_GATEWAY))); final RestResponse mappedResult = result.map(); assertThat(mappedResult.getStatus()) .isEqualTo(RestResponse.Status.BAD_GATEWAY.getStatusCode()); @@ -69,6 +78,7 @@ public void internalError() { new CommandResult.Error( "My message.", Map.of("field", "value"), + Map.of("field", "value"), Response.Status.INTERNAL_SERVER_ERROR))); final RestResponse mappedResult = result.map(); assertThat(mappedResult.getStatus()) @@ -81,7 +91,10 @@ public void gatewayError() { new CommandResult( List.of( new CommandResult.Error( - "My message.", Map.of("field", "value"), Response.Status.GATEWAY_TIMEOUT))); + "My message.", + Map.of("field", "value"), + Map.of("field", "value"), + Response.Status.GATEWAY_TIMEOUT))); final RestResponse mappedResult = result.map(); assertThat(mappedResult.getStatus()) .isEqualTo(RestResponse.Status.GATEWAY_TIMEOUT.getStatusCode()); diff --git a/src/test/java/io/stargate/sgv2/jsonapi/exception/JsonApiExceptionTest.java b/src/test/java/io/stargate/sgv2/jsonapi/exception/JsonApiExceptionTest.java index c5d8bc56b0..de8b0e0e7c 100644 --- a/src/test/java/io/stargate/sgv2/jsonapi/exception/JsonApiExceptionTest.java +++ b/src/test/java/io/stargate/sgv2/jsonapi/exception/JsonApiExceptionTest.java @@ -2,10 +2,15 @@ import static org.assertj.core.api.Assertions.assertThat; +import io.quarkus.test.junit.QuarkusTest; +import io.quarkus.test.junit.TestProfile; +import io.stargate.sgv2.common.testprofiles.NoGlobalResourcesTestProfile; import io.stargate.sgv2.jsonapi.api.model.command.CommandResult; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; +@QuarkusTest +@TestProfile(NoGlobalResourcesTestProfile.Impl.class) class JsonApiExceptionTest { @Nested diff --git a/src/test/java/io/stargate/sgv2/jsonapi/exception/mappers/ThrowableCommandResultSupplierTest.java b/src/test/java/io/stargate/sgv2/jsonapi/exception/mappers/ThrowableCommandResultSupplierTest.java index 9690ee7bda..4f7bad239c 100644 --- a/src/test/java/io/stargate/sgv2/jsonapi/exception/mappers/ThrowableCommandResultSupplierTest.java +++ b/src/test/java/io/stargate/sgv2/jsonapi/exception/mappers/ThrowableCommandResultSupplierTest.java @@ -4,11 +4,16 @@ import io.grpc.Status; import io.grpc.StatusRuntimeException; +import io.quarkus.test.junit.QuarkusTest; +import io.quarkus.test.junit.TestProfile; +import io.stargate.sgv2.common.testprofiles.NoGlobalResourcesTestProfile; import io.stargate.sgv2.jsonapi.api.model.command.CommandResult; import jakarta.ws.rs.core.Response; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; +@QuarkusTest +@TestProfile(NoGlobalResourcesTestProfile.Impl.class) class ThrowableCommandResultSupplierTest { @Nested diff --git a/src/test/java/io/stargate/sgv2/jsonapi/service/operation/model/impl/CreateCollectionOperationTest.java b/src/test/java/io/stargate/sgv2/jsonapi/service/operation/model/impl/CreateCollectionOperationTest.java index 618fba8bb5..407a2b840e 100644 --- a/src/test/java/io/stargate/sgv2/jsonapi/service/operation/model/impl/CreateCollectionOperationTest.java +++ b/src/test/java/io/stargate/sgv2/jsonapi/service/operation/model/impl/CreateCollectionOperationTest.java @@ -13,6 +13,7 @@ import io.stargate.sgv2.jsonapi.api.model.command.CommandContext; import io.stargate.sgv2.jsonapi.api.model.command.CommandResult; import io.stargate.sgv2.jsonapi.api.model.command.CommandStatus; +import io.stargate.sgv2.jsonapi.config.DatabaseLimitsConfig; import io.stargate.sgv2.jsonapi.service.bridge.executor.QueryExecutor; import jakarta.inject.Inject; import java.util.ArrayList; @@ -33,6 +34,7 @@ public class CreateCollectionOperationTest extends AbstractValidatingStargateBri @Inject ObjectMapper objectMapper; @Inject SchemaManager schemaManager; @Inject QueryExecutor queryExecutor; + @Inject DatabaseLimitsConfig dbLimitsConfig; @Nested @Disabled @@ -50,7 +52,7 @@ public void createCollection() throws Exception { CreateCollectionOperation createCollectionOperation = CreateCollectionOperation.withoutVectorSearch( - commandContext, objectMapper, schemaManagerMock, COLLECTION_NAME); + commandContext, dbLimitsConfig, objectMapper, schemaManagerMock, COLLECTION_NAME); final Supplier execute = createCollectionOperation.execute(queryExecutor).subscribeAsCompletionStage().get(); @@ -73,7 +75,11 @@ public void createCollectionCaseSensitive() throws Exception { when(schemaManagerMock.getKeyspaces()).thenReturn(null); CreateCollectionOperation createCollectionOperation = CreateCollectionOperation.withoutVectorSearch( - commandContextUpper, objectMapper, schemaManagerMock, COLLECTION_NAME.toUpperCase()); + commandContextUpper, + dbLimitsConfig, + objectMapper, + schemaManagerMock, + COLLECTION_NAME.toUpperCase()); final Supplier execute = createCollectionOperation.execute(queryExecutor).subscribeAsCompletionStage().get(); @@ -93,7 +99,14 @@ public void createCollectionVector() throws Exception { when(schemaManagerMock.getKeyspaces()).thenReturn(null); CreateCollectionOperation createCollectionOperation = CreateCollectionOperation.withVectorSearch( - commandContext, objectMapper, schemaManagerMock, COLLECTION_NAME, 4, "cosine", null); + commandContext, + dbLimitsConfig, + objectMapper, + schemaManagerMock, + COLLECTION_NAME, + 4, + "cosine", + null); final Supplier execute = createCollectionOperation.execute(queryExecutor).subscribeAsCompletionStage().get(); @@ -120,6 +133,7 @@ public void createCollectionVectorize() throws Exception { CreateCollectionOperation createCollectionOperation = CreateCollectionOperation.withVectorSearch( commandContext, + dbLimitsConfig, objectMapper, schemaManagerMock, COLLECTION_NAME, @@ -146,6 +160,7 @@ public void createCollectionVectorDotProduct() throws Exception { CreateCollectionOperation createCollectionOperation = CreateCollectionOperation.withVectorSearch( commandContext, + dbLimitsConfig, objectMapper, schemaManagerMock, COLLECTION_NAME, diff --git a/src/test/java/io/stargate/sgv2/jsonapi/service/processor/MeteredCommandProcessorTest.java b/src/test/java/io/stargate/sgv2/jsonapi/service/processor/MeteredCommandProcessorTest.java index 53f639ff0d..2b8c2b450c 100644 --- a/src/test/java/io/stargate/sgv2/jsonapi/service/processor/MeteredCommandProcessorTest.java +++ b/src/test/java/io/stargate/sgv2/jsonapi/service/processor/MeteredCommandProcessorTest.java @@ -12,7 +12,7 @@ import io.stargate.sgv2.common.testprofiles.NoGlobalResourcesTestProfile; import io.stargate.sgv2.jsonapi.api.model.command.CommandContext; import io.stargate.sgv2.jsonapi.api.model.command.CommandResult; -import io.stargate.sgv2.jsonapi.api.model.command.impl.CountDocumentsCommands; +import io.stargate.sgv2.jsonapi.api.model.command.impl.CountDocumentsCommand; import io.stargate.sgv2.jsonapi.api.model.command.impl.FindCommand; import jakarta.inject.Inject; import jakarta.ws.rs.core.Response; @@ -47,8 +47,8 @@ public void metrics() throws Exception { } """; - CountDocumentsCommands countCommand = - objectMapper.readValue(json, CountDocumentsCommands.class); + CountDocumentsCommand countCommand = + objectMapper.readValue(json, CountDocumentsCommand.class); CommandContext commandContext = new CommandContext("namespace", "collection"); CommandResult commandResult = new CommandResult(Collections.emptyList()); Mockito.when(commandProcessor.processCommand(commandContext, countCommand)) @@ -74,7 +74,7 @@ public void metrics() throws Exception { assertThat(lines.size()).isEqualTo(3); lines.forEach( line -> { - assertThat(line).contains("command=\"CountDocumentsCommands\""); + assertThat(line).contains("command=\"CountDocumentsCommand\""); assertThat(line).contains("tenant=\"test-tenant\""); assertThat(line).contains("error=\"false\""); assertThat(line).contains("error_code=\"NA\""); @@ -98,7 +98,8 @@ public void errorMetricsWithNoErrorCode() throws Exception { CommandContext commandContext = new CommandContext("namespace", "collection"); Map fields = new HashMap<>(); fields.put("exceptionClass", "TestExceptionClass"); - CommandResult.Error error = new CommandResult.Error("message", fields, Response.Status.OK); + CommandResult.Error error = + new CommandResult.Error("message", fields, fields, Response.Status.OK); CommandResult commandResult = new CommandResult(Collections.singletonList(error)); Mockito.when(commandProcessor.processCommand(commandContext, countCommand)) .thenReturn(Uni.createFrom().item(commandResult)); @@ -145,13 +146,14 @@ public void errorMetrics() throws Exception { } """; - CountDocumentsCommands countCommand = - objectMapper.readValue(json, CountDocumentsCommands.class); + CountDocumentsCommand countCommand = + objectMapper.readValue(json, CountDocumentsCommand.class); CommandContext commandContext = new CommandContext("namespace", "collection"); Map fields = new HashMap<>(); fields.put("exceptionClass", "TestExceptionClass"); fields.put("errorCode", "TestErrorCode"); - CommandResult.Error error = new CommandResult.Error("message", fields, Response.Status.OK); + CommandResult.Error error = + new CommandResult.Error("message", fields, fields, Response.Status.OK); CommandResult commandResult = new CommandResult(Collections.singletonList(error)); Mockito.when(commandProcessor.processCommand(commandContext, countCommand)) .thenReturn(Uni.createFrom().item(commandResult)); @@ -168,7 +170,7 @@ public void errorMetrics() throws Exception { line -> line.startsWith("command_processor_process") && line.contains("error=\"true\"") - && line.contains("command=\"CountDocumentsCommands\"")) + && line.contains("command=\"CountDocumentsCommand\"")) .toList(); assertThat(httpMetrics) @@ -177,7 +179,7 @@ public void errorMetrics() throws Exception { assertThat(lines.size()).isEqualTo(3); lines.forEach( line -> { - assertThat(line).contains("command=\"CountDocumentsCommands\""); + assertThat(line).contains("command=\"CountDocumentsCommand\""); assertThat(line).contains("tenant=\"test-tenant\""); assertThat(line).contains("error=\"true\""); assertThat(line).contains("error_code=\"TestErrorCode\""); diff --git a/src/test/java/io/stargate/sgv2/jsonapi/service/resolver/model/impl/CountCommandResolverTest.java b/src/test/java/io/stargate/sgv2/jsonapi/service/resolver/model/impl/CountCommandResolverTest.java index 7cf2d7b37b..71c8d648ee 100644 --- a/src/test/java/io/stargate/sgv2/jsonapi/service/resolver/model/impl/CountCommandResolverTest.java +++ b/src/test/java/io/stargate/sgv2/jsonapi/service/resolver/model/impl/CountCommandResolverTest.java @@ -9,7 +9,7 @@ import io.stargate.sgv2.jsonapi.api.model.command.CommandContext; import io.stargate.sgv2.jsonapi.api.model.command.clause.filter.ComparisonExpression; import io.stargate.sgv2.jsonapi.api.model.command.clause.filter.LogicalExpression; -import io.stargate.sgv2.jsonapi.api.model.command.impl.CountDocumentsCommands; +import io.stargate.sgv2.jsonapi.api.model.command.impl.CountDocumentsCommand; import io.stargate.sgv2.jsonapi.service.operation.model.CountOperation; import io.stargate.sgv2.jsonapi.service.operation.model.Operation; import io.stargate.sgv2.jsonapi.service.operation.model.impl.DBFilterBase; @@ -34,8 +34,7 @@ public void noFilterCondition() throws Exception { } """; - CountDocumentsCommands countCommand = - objectMapper.readValue(json, CountDocumentsCommands.class); + CountDocumentsCommand countCommand = objectMapper.readValue(json, CountDocumentsCommand.class); final CommandContext commandContext = new CommandContext("namespace", "collection"); final Operation operation = countCommandResolver.resolveCommand(commandContext, countCommand); LogicalExpression implicitAnd = LogicalExpression.and(); @@ -61,8 +60,7 @@ public void dynamicFilterCondition() throws Exception { } """; - CountDocumentsCommands countCommand = - objectMapper.readValue(json, CountDocumentsCommands.class); + CountDocumentsCommand countCommand = objectMapper.readValue(json, CountDocumentsCommand.class); final CommandContext commandContext = new CommandContext("namespace", "collection"); final Operation operation = countCommandResolver.resolveCommand(commandContext, countCommand); diff --git a/src/test/java/io/stargate/sgv2/jsonapi/service/resolver/model/impl/CountDocumentsCommandResolverTest.java b/src/test/java/io/stargate/sgv2/jsonapi/service/resolver/model/impl/CountDocumentsCommandResolverTest.java index 98d66540aa..faf8fe7f1b 100644 --- a/src/test/java/io/stargate/sgv2/jsonapi/service/resolver/model/impl/CountDocumentsCommandResolverTest.java +++ b/src/test/java/io/stargate/sgv2/jsonapi/service/resolver/model/impl/CountDocumentsCommandResolverTest.java @@ -8,7 +8,7 @@ import io.quarkus.test.junit.TestProfile; import io.stargate.sgv2.common.testprofiles.NoGlobalResourcesTestProfile; import io.stargate.sgv2.jsonapi.api.model.command.CommandContext; -import io.stargate.sgv2.jsonapi.api.model.command.impl.CountDocumentsCommands; +import io.stargate.sgv2.jsonapi.api.model.command.impl.CountDocumentsCommand; import io.stargate.sgv2.jsonapi.service.operation.model.CountOperation; import io.stargate.sgv2.jsonapi.service.operation.model.Operation; import io.stargate.sgv2.jsonapi.service.operation.model.impl.DBFilterBase; @@ -39,7 +39,7 @@ public void noFilter() throws Exception { } """; - CountDocumentsCommands command = objectMapper.readValue(json, CountDocumentsCommands.class); + CountDocumentsCommand command = objectMapper.readValue(json, CountDocumentsCommand.class); Operation result = resolver.resolveCommand(context, command); assertThat(result) @@ -64,7 +64,7 @@ public void withFilter() throws Exception { } """; - CountDocumentsCommands command = objectMapper.readValue(json, CountDocumentsCommands.class); + CountDocumentsCommand command = objectMapper.readValue(json, CountDocumentsCommand.class); Operation result = resolver.resolveCommand(context, command); assertThat(result) diff --git a/src/test/java/io/stargate/sgv2/jsonapi/service/resolver/model/impl/CreateCollectionCommandResolverTest.java b/src/test/java/io/stargate/sgv2/jsonapi/service/resolver/model/impl/CreateCollectionCommandResolverTest.java index 2e4c56f69c..11372ebed4 100644 --- a/src/test/java/io/stargate/sgv2/jsonapi/service/resolver/model/impl/CreateCollectionCommandResolverTest.java +++ b/src/test/java/io/stargate/sgv2/jsonapi/service/resolver/model/impl/CreateCollectionCommandResolverTest.java @@ -63,8 +63,8 @@ public void happyPathVectorSearch() throws Exception { "name" : "my_collection", "options": { "vector": { - "size": 4, - "function": "cosine" + "dimension": 4, + "metric": "cosine" } } } @@ -95,8 +95,8 @@ public void happyPathVectorizeSearch() throws Exception { "name" : "my_collection", "options": { "vector": { - "size": 4, - "function": "cosine" + "dimension": 4, + "metric": "cosine" }, "vectorize": { "service" : "openai", @@ -136,7 +136,7 @@ public void happyPathVectorSearchDefaultFunction() throws Exception { "name" : "my_collection", "options": { "vector": { - "size": 4 + "dimension": 4 } } } diff --git a/src/test/java/io/stargate/sgv2/jsonapi/service/resolver/model/impl/CreateCollectionResolverVectorDisabledTest.java b/src/test/java/io/stargate/sgv2/jsonapi/service/resolver/model/impl/CreateCollectionResolverVectorDisabledTest.java index 63f868410a..59843ad7dd 100644 --- a/src/test/java/io/stargate/sgv2/jsonapi/service/resolver/model/impl/CreateCollectionResolverVectorDisabledTest.java +++ b/src/test/java/io/stargate/sgv2/jsonapi/service/resolver/model/impl/CreateCollectionResolverVectorDisabledTest.java @@ -35,8 +35,8 @@ public void vectorSearchDisabled() throws Exception { "name" : "my_collection", "options": { "vector": { - "size": 4, - "function": "cosine" + "dimension": 4, + "metric": "cosine" } } } diff --git a/src/test/java/io/stargate/sgv2/jsonapi/testresource/DseTestResource.java b/src/test/java/io/stargate/sgv2/jsonapi/testresource/DseTestResource.java index 000650137d..aa149093ee 100644 --- a/src/test/java/io/stargate/sgv2/jsonapi/testresource/DseTestResource.java +++ b/src/test/java/io/stargate/sgv2/jsonapi/testresource/DseTestResource.java @@ -16,7 +16,7 @@ public DseTestResource() { if (null == System.getProperty("testing.containers.cassandra-image")) { System.setProperty( - "testing.containers.cassandra-image", "stargateio/dse-next:4.0.7-336cdd7405ee"); + "testing.containers.cassandra-image", "stargateio/dse-next:4.0.11-45d4657e507e"); } if (null == System.getProperty("testing.containers.stargate-image")) { @@ -49,6 +49,7 @@ public Map start() { if (defaultToken != null) { propsBuilder.put(FIXED_TOKEN_PROPERTY_NAME, defaultToken); } + propsBuilder.put("stargate.debug.enabled", "true"); return propsBuilder.build(); } } diff --git a/src/test/resources/application.yaml b/src/test/resources/application.yaml index 981f48b855..6a991f9058 100644 --- a/src/test/resources/application.yaml +++ b/src/test/resources/application.yaml @@ -3,6 +3,8 @@ stargate: data-store: ignore-bridge: true + debug: + enabled: true # change test port from 8081 (used by other SG services) quarkus: From e563915ce0427b57635ce162c6bb764a98aa52d4 Mon Sep 17 00:00:00 2001 From: Tatu Saloranta Date: Thu, 2 Nov 2023 14:54:23 -0700 Subject: [PATCH 2/7] Resolve the last merge conflict --- .../mappers/ThrowableToErrorMapper.java | 40 +++++++------------ .../api/v1/HttpStatusCodeIntegrationTest.java | 2 +- 2 files changed, 15 insertions(+), 27 deletions(-) diff --git a/src/main/java/io/stargate/sgv2/jsonapi/exception/mappers/ThrowableToErrorMapper.java b/src/main/java/io/stargate/sgv2/jsonapi/exception/mappers/ThrowableToErrorMapper.java index 466f8990e6..6a6929ca34 100644 --- a/src/main/java/io/stargate/sgv2/jsonapi/exception/mappers/ThrowableToErrorMapper.java +++ b/src/main/java/io/stargate/sgv2/jsonapi/exception/mappers/ThrowableToErrorMapper.java @@ -31,27 +31,18 @@ public final class ThrowableToErrorMapper { if (throwable instanceof JsonApiException jae) { return jae.getCommandResultError(message); } -<<<<<<< HEAD - // add error code as error field - Map fields = Map.of("exceptionClass", throwable.getClass().getSimpleName()); - if (throwable instanceof StatusRuntimeException sre) { - if (sre.getStatus().getCode() == Status.Code.UNAUTHENTICATED) { - return new CommandResult.Error( - "UNAUTHENTICATED: Invalid token", fields, Response.Status.UNAUTHORIZED); -======= // Override response error code SmallRyeConfig config = ConfigProvider.getConfig().unwrap(SmallRyeConfig.class); DebugModeConfig debugModeConfig = config.getConfigMapping(DebugModeConfig.class); final boolean debugEnabled = debugModeConfig.enabled(); + final Map fields = + debugEnabled ? Map.of("exceptionClass", throwable.getClass().getSimpleName()) : null; + final Map fieldsForMetricsTag = + Map.of("exceptionClass", throwable.getClass().getSimpleName()); if (throwable instanceof StatusRuntimeException sre) { - Map fields = - debugEnabled ? Map.of("exceptionClass", throwable.getClass().getSimpleName()) : null; - Map fieldsForMetricsTag = - Map.of("exceptionClass", throwable.getClass().getSimpleName()); if (sre.getStatus().getCode() == Status.Code.UNAUTHENTICATED) { return new CommandResult.Error( message, fieldsForMetricsTag, fields, Response.Status.UNAUTHORIZED); ->>>>>>> main } else if (sre.getStatus().getCode() == Status.Code.INTERNAL) { return new CommandResult.Error( message, fieldsForMetricsTag, fields, Response.Status.INTERNAL_SERVER_ERROR); @@ -63,36 +54,33 @@ public final class ThrowableToErrorMapper { message, fieldsForMetricsTag, fields, Response.Status.GATEWAY_TIMEOUT); } } -<<<<<<< HEAD if (throwable instanceof UnauthorizedException || throwable instanceof com.datastax.oss.driver.api.core.servererrors.UnauthorizedException) { return new CommandResult.Error( - "UNAUTHENTICATED: Invalid token", fields, Response.Status.UNAUTHORIZED); + "UNAUTHENTICATED: Invalid token", + fieldsForMetricsTag, + fields, + Response.Status.UNAUTHORIZED); } else if (throwable instanceof QueryValidationException) { if (message.contains("vector fields = - debugEnabled ? Map.of("exceptionClass", throwable.getClass().getSimpleName()) : null; - Map fieldsForMetricsTag = - Map.of("exceptionClass", throwable.getClass().getSimpleName()); return new CommandResult.Error(message, fieldsForMetricsTag, fields, Response.Status.OK); ->>>>>>> main }; + private static final Function MAPPER = throwable -> { String message = throwable.getMessage(); diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/HttpStatusCodeIntegrationTest.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/HttpStatusCodeIntegrationTest.java index 5bb4be092f..1d85032630 100644 --- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/HttpStatusCodeIntegrationTest.java +++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/HttpStatusCodeIntegrationTest.java @@ -89,7 +89,7 @@ public void regularError() { endsWith("table %s.%s does not exist".formatted(namespaceName, "badCollection")), endsWith("table %s does not exist".formatted("badCollection")), endsWith( - "Collection does not exist, collection name: %s".formatted("badCollection"))); + "Collection does not exist, collection name: %s".formatted("badCollection"))); given() .header(HttpConstants.AUTHENTICATION_TOKEN_HEADER_NAME, getAuthToken()) .contentType(ContentType.JSON) From 713d79d32159eb1f5fe33a4e9c0a4e76bd740108 Mon Sep 17 00:00:00 2001 From: Tatu Saloranta Date: Thu, 2 Nov 2023 14:57:25 -0700 Subject: [PATCH 3/7] Minor simplification --- .../sgv2/jsonapi/exception/JsonApiException.java | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/main/java/io/stargate/sgv2/jsonapi/exception/JsonApiException.java b/src/main/java/io/stargate/sgv2/jsonapi/exception/JsonApiException.java index 88526d9b99..f67784ab27 100644 --- a/src/main/java/io/stargate/sgv2/jsonapi/exception/JsonApiException.java +++ b/src/main/java/io/stargate/sgv2/jsonapi/exception/JsonApiException.java @@ -63,17 +63,15 @@ public CommandResult get() { public CommandResult.Error getCommandResultError(String message) { Map fieldsForMetricsTag = Map.of("errorCode", errorCode.name(), "exceptionClass", this.getClass().getSimpleName()); - Map fields = null; SmallRyeConfig config = ConfigProvider.getConfig().unwrap(SmallRyeConfig.class); // enable debug mode for unit tests, since it can not be injected DebugModeConfig debugModeConfig = config.getConfigMapping(DebugModeConfig.class); final boolean debugEnabled = debugModeConfig.enabled(); - if (debugEnabled) { - fields = - Map.of("errorCode", errorCode.name(), "exceptionClass", this.getClass().getSimpleName()); - } else { - fields = Map.of("errorCode", errorCode.name()); - } + final Map fields = + debugEnabled + ? Map.of( + "errorCode", errorCode.name(), "exceptionClass", this.getClass().getSimpleName()) + : Map.of("errorCode", errorCode.name()); return new CommandResult.Error(message, fieldsForMetricsTag, fields, Response.Status.OK); } From 84263a03ca51d61afe2471080ac4e4c2b7f28e9c Mon Sep 17 00:00:00 2001 From: Yuqi Du Date: Thu, 2 Nov 2023 19:31:24 -0700 Subject: [PATCH 4/7] error mapping fix --- .../jsonapi/exception/mappers/ThrowableToErrorMapper.java | 5 ++++- .../sgv2/jsonapi/api/v1/DropNamespaceIntegrationTest.java | 1 - 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/io/stargate/sgv2/jsonapi/exception/mappers/ThrowableToErrorMapper.java b/src/main/java/io/stargate/sgv2/jsonapi/exception/mappers/ThrowableToErrorMapper.java index 6a6929ca34..d684477267 100644 --- a/src/main/java/io/stargate/sgv2/jsonapi/exception/mappers/ThrowableToErrorMapper.java +++ b/src/main/java/io/stargate/sgv2/jsonapi/exception/mappers/ThrowableToErrorMapper.java @@ -42,7 +42,10 @@ public final class ThrowableToErrorMapper { if (throwable instanceof StatusRuntimeException sre) { if (sre.getStatus().getCode() == Status.Code.UNAUTHENTICATED) { return new CommandResult.Error( - message, fieldsForMetricsTag, fields, Response.Status.UNAUTHORIZED); + "UNAUTHENTICATED: Invalid token", + fieldsForMetricsTag, + fields, + Response.Status.UNAUTHORIZED); } else if (sre.getStatus().getCode() == Status.Code.INTERNAL) { return new CommandResult.Error( message, fieldsForMetricsTag, fields, Response.Status.INTERNAL_SERVER_ERROR); diff --git a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/DropNamespaceIntegrationTest.java b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/DropNamespaceIntegrationTest.java index 8a91bec58f..437fb4e735 100644 --- a/src/test/java/io/stargate/sgv2/jsonapi/api/v1/DropNamespaceIntegrationTest.java +++ b/src/test/java/io/stargate/sgv2/jsonapi/api/v1/DropNamespaceIntegrationTest.java @@ -9,7 +9,6 @@ import io.quarkus.test.common.QuarkusTestResource; import io.quarkus.test.junit.QuarkusIntegrationTest; import io.restassured.http.ContentType; -// import io.stargate.sgv2.jsonapi.config.constants.HttpConstants; import io.stargate.sgv2.jsonapi.config.constants.HttpConstants; import io.stargate.sgv2.jsonapi.testresource.DseTestResource; import org.apache.commons.lang3.RandomStringUtils; From c18e81ab2a0b3c93f395a564444e54022f385220 Mon Sep 17 00:00:00 2001 From: Tatu Saloranta Date: Fri, 3 Nov 2023 09:32:44 -0700 Subject: [PATCH 5/7] Fix 3 metrics test by filtering out bucketed entries --- .../service/processor/MeteredCommandProcessorTest.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/test/java/io/stargate/sgv2/jsonapi/service/processor/MeteredCommandProcessorTest.java b/src/test/java/io/stargate/sgv2/jsonapi/service/processor/MeteredCommandProcessorTest.java index 2b8c2b450c..fa4336a4cd 100644 --- a/src/test/java/io/stargate/sgv2/jsonapi/service/processor/MeteredCommandProcessorTest.java +++ b/src/test/java/io/stargate/sgv2/jsonapi/service/processor/MeteredCommandProcessorTest.java @@ -64,7 +64,8 @@ public void metrics() throws Exception { .lines() .filter( line -> - line.startsWith("command_processor_process") + line.startsWith("command_processor_process_seconds_") + && !line.contains("seconds_bucket") && line.contains("error=\"false\"")) .toList(); @@ -114,7 +115,8 @@ public void errorMetricsWithNoErrorCode() throws Exception { .lines() .filter( line -> - line.startsWith("command_processor_process") + line.startsWith("command_processor_process_seconds_") + && !line.contains("seconds_bucket") && line.contains("error=\"true\"") && line.contains("command=\"FindCommand\"")) .toList(); @@ -168,7 +170,8 @@ public void errorMetrics() throws Exception { .lines() .filter( line -> - line.startsWith("command_processor_process") + line.startsWith("command_processor_process_seconds_") + && !line.contains("seconds_bucket") && line.contains("error=\"true\"") && line.contains("command=\"CountDocumentsCommand\"")) .toList(); From 11092994f7ad6268d0902e003d1d1d77c0349caa Mon Sep 17 00:00:00 2001 From: Tatu Saloranta Date: Fri, 3 Nov 2023 09:36:08 -0700 Subject: [PATCH 6/7] Try to enable CI for this branch as well --- .github/workflows/continuous-integration.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/continuous-integration.yaml b/.github/workflows/continuous-integration.yaml index eddfc2562f..610d46dd45 100644 --- a/.github/workflows/continuous-integration.yaml +++ b/.github/workflows/continuous-integration.yaml @@ -6,10 +6,10 @@ name: Continuous Integration # * manual trigger on: push: - branches: [ "main" ] + branches: [ "main", "native_cql_changes" ] pull_request: - branches: [ "main" ] + branches: [ "main", "native_cql_changes" ] paths: - 'src/**' - 'pom.xml' From 00500702c0cee54599eb91ce2c3d718caae86e73 Mon Sep 17 00:00:00 2001 From: Tatu Saloranta Date: Fri, 3 Nov 2023 10:11:32 -0700 Subject: [PATCH 7/7] Fix the last unit test failure (wrt CountDocumentsCommand vs trailing -s) --- .../service/processor/MeteredCommandProcessorTest.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/test/java/io/stargate/sgv2/jsonapi/service/processor/MeteredCommandProcessorTest.java b/src/test/java/io/stargate/sgv2/jsonapi/service/processor/MeteredCommandProcessorTest.java index 4b6cd019a2..5a57d3a2fc 100644 --- a/src/test/java/io/stargate/sgv2/jsonapi/service/processor/MeteredCommandProcessorTest.java +++ b/src/test/java/io/stargate/sgv2/jsonapi/service/processor/MeteredCommandProcessorTest.java @@ -173,12 +173,11 @@ public void errorMetrics() throws Exception { .lines() .filter( line -> - line.startsWith("command_processor_process_seconds_") - && !line.contains("seconds_bucket") + line.startsWith("command_processor_process_") && line.contains("error=\"true\"") && !line.startsWith("command_processor_process_seconds_bucket") && !line.contains("quantile") - && line.contains("command=\"CountDocumentsCommands\"")) + && line.contains("command=\"CountDocumentsCommand\"")) .toList(); assertThat(httpMetrics)