mirror of https://github.com/dapr/java-sdk.git
Remove HTTP client and add gRPC interceptor helper. (#1051)
* Remove HTTP client and add gRPC interceptor helper. Signed-off-by: Artur Souza <asouza.pro@gmail.com> * New design for gRPC interceptor and channel proxy. Signed-off-by: Artur Souza <asouza.pro@gmail.com> --------- Signed-off-by: Artur Souza <asouza.pro@gmail.com> Signed-off-by: Artur Souza <artursouza.ms@outlook.com>
This commit is contained in:
parent
9048bc1a5e
commit
502f7c0638
|
@ -100,10 +100,6 @@ jobs:
|
||||||
echo "PATH=$PATH:$HOME/.local/bin" >> $GITHUB_ENV
|
echo "PATH=$PATH:$HOME/.local/bin" >> $GITHUB_ENV
|
||||||
pip3 install setuptools wheel
|
pip3 install setuptools wheel
|
||||||
pip3 install mechanical-markdown
|
pip3 install mechanical-markdown
|
||||||
- name: Install Local mongo database using docker-compose
|
|
||||||
run: |
|
|
||||||
docker-compose -f ./sdk-tests/deploy/local-test.yml up -d mongo
|
|
||||||
docker ps
|
|
||||||
- name: Clean up files
|
- name: Clean up files
|
||||||
run: ./mvnw clean
|
run: ./mvnw clean
|
||||||
- name: Build sdk
|
- name: Build sdk
|
||||||
|
@ -146,14 +142,10 @@ jobs:
|
||||||
working-directory: ./examples
|
working-directory: ./examples
|
||||||
run: |
|
run: |
|
||||||
mm.py ./src/main/java/io/dapr/examples/unittesting/README.md
|
mm.py ./src/main/java/io/dapr/examples/unittesting/README.md
|
||||||
- name: Validate Configuration gRPC API example
|
- name: Validate Configuration API example
|
||||||
working-directory: ./examples
|
working-directory: ./examples
|
||||||
run: |
|
run: |
|
||||||
mm.py ./src/main/java/io/dapr/examples/configuration/grpc/README.md
|
mm.py ./src/main/java/io/dapr/examples/configuration/README.md
|
||||||
- name: Validate Configuration HTTP API example
|
|
||||||
working-directory: ./examples
|
|
||||||
run: |
|
|
||||||
mm.py ./src/main/java/io/dapr/examples/configuration/http/README.md
|
|
||||||
- name: Validate actors example
|
- name: Validate actors example
|
||||||
working-directory: ./examples
|
working-directory: ./examples
|
||||||
run: |
|
run: |
|
||||||
|
|
|
@ -105,6 +105,7 @@ Try the following examples to learn more about Dapr's Java SDK:
|
||||||
* [Binding with input over Http](./examples/src/main/java/io/dapr/examples/bindings/http)
|
* [Binding with input over Http](./examples/src/main/java/io/dapr/examples/bindings/http)
|
||||||
* [Actors](./examples/src/main/java/io/dapr/examples/actors/)
|
* [Actors](./examples/src/main/java/io/dapr/examples/actors/)
|
||||||
* [Secrets management](./examples/src/main/java/io/dapr/examples/secrets)
|
* [Secrets management](./examples/src/main/java/io/dapr/examples/secrets)
|
||||||
|
* [Configuration](./examples/src/main/java/io/dapr/examples/configuration)
|
||||||
* [Distributed tracing with OpenTelemetry SDK](./examples/src/main/java/io/dapr/examples/tracing)
|
* [Distributed tracing with OpenTelemetry SDK](./examples/src/main/java/io/dapr/examples/tracing)
|
||||||
* [Exception handling](./examples/src/main/java/io/dapr/examples/exception)
|
* [Exception handling](./examples/src/main/java/io/dapr/examples/exception)
|
||||||
* [Unit testing](./examples/src/main/java/io/dapr/examples/unittesting)
|
* [Unit testing](./examples/src/main/java/io/dapr/examples/unittesting)
|
||||||
|
|
|
@ -16,15 +16,15 @@ package io.dapr.examples;
|
||||||
import io.opentelemetry.api.OpenTelemetry;
|
import io.opentelemetry.api.OpenTelemetry;
|
||||||
import io.opentelemetry.context.Context;
|
import io.opentelemetry.context.Context;
|
||||||
import io.opentelemetry.context.propagation.TextMapPropagator;
|
import io.opentelemetry.context.propagation.TextMapPropagator;
|
||||||
|
import jakarta.servlet.DispatcherType;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import org.springframework.web.servlet.HandlerInterceptor;
|
import org.springframework.web.servlet.HandlerInterceptor;
|
||||||
import org.springframework.web.servlet.ModelAndView;
|
import org.springframework.web.servlet.ModelAndView;
|
||||||
|
|
||||||
import jakarta.servlet.DispatcherType;
|
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
|
|
|
@ -54,7 +54,7 @@ Run `dapr init` to initialize Dapr in Self-Hosted Mode if it's not already initi
|
||||||
|
|
||||||
Before getting into the application code, follow these steps in order to set up a local instance of Kafka. This is needed for the local instances.
|
Before getting into the application code, follow these steps in order to set up a local instance of Kafka. This is needed for the local instances.
|
||||||
|
|
||||||
1. Run the container locally:
|
1. Run the Kafka locally:
|
||||||
|
|
||||||
<!-- STEP
|
<!-- STEP
|
||||||
name: Setup kafka container
|
name: Setup kafka container
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
version: '2'
|
version: '3'
|
||||||
services:
|
services:
|
||||||
zookeeper:
|
zookeeper:
|
||||||
image: confluentinc/cp-zookeeper:7.4.4
|
image: confluentinc/cp-zookeeper:7.4.4
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.dapr.examples.configuration.grpc;
|
package io.dapr.examples.configuration;
|
||||||
|
|
||||||
import io.dapr.client.DaprClient;
|
import io.dapr.client.DaprClient;
|
||||||
import io.dapr.client.DaprClientBuilder;
|
import io.dapr.client.DaprClientBuilder;
|
|
@ -158,7 +158,7 @@ sleep: 10
|
||||||
-->
|
-->
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
dapr run --components-path ./components/configuration --app-id configgrpc --log-level debug -- java -jar target/dapr-java-sdk-examples-exec.jar io.dapr.examples.configuration.grpc.ConfigurationClient
|
dapr run --components-path ./components/configuration --app-id configgrpc --log-level debug -- java -jar target/dapr-java-sdk-examples-exec.jar io.dapr.examples.configuration.ConfigurationClient
|
||||||
```
|
```
|
||||||
|
|
||||||
<!-- END_STEP -->
|
<!-- END_STEP -->
|
|
@ -1,102 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2022 The Dapr 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.dapr.examples.configuration.http;
|
|
||||||
|
|
||||||
import io.dapr.client.DaprApiProtocol;
|
|
||||||
import io.dapr.client.DaprClient;
|
|
||||||
import io.dapr.client.DaprClientBuilder;
|
|
||||||
import io.dapr.client.domain.ConfigurationItem;
|
|
||||||
import io.dapr.client.domain.GetConfigurationRequest;
|
|
||||||
import io.dapr.client.domain.SubscribeConfigurationRequest;
|
|
||||||
import io.dapr.client.domain.SubscribeConfigurationResponse;
|
|
||||||
import io.dapr.config.Properties;
|
|
||||||
import reactor.core.publisher.Flux;
|
|
||||||
import reactor.core.publisher.Mono;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public class ConfigurationClient {
|
|
||||||
|
|
||||||
private static final String CONFIG_STORE_NAME = "configstore";
|
|
||||||
private static String SUBSCRIPTION_ID;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Executes various methods to check the different apis.
|
|
||||||
* @param args arguments
|
|
||||||
* @throws Exception throws Exception
|
|
||||||
*/
|
|
||||||
public static void main(String[] args) throws Exception {
|
|
||||||
System.getProperties().setProperty(Properties.API_PROTOCOL.getName(), DaprApiProtocol.HTTP.name());
|
|
||||||
try (DaprClient client = (new DaprClientBuilder()).build()) {
|
|
||||||
System.out.println("Using Dapr client...");
|
|
||||||
getConfigurations(client);
|
|
||||||
subscribeConfigurationRequest(client);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets configurations for a list of keys.
|
|
||||||
*
|
|
||||||
* @param client DaprClient object
|
|
||||||
*/
|
|
||||||
public static void getConfigurations(DaprClient client) {
|
|
||||||
System.out.println("*******trying to retrieve configurations for a list of keys********");
|
|
||||||
List<String> keys = new ArrayList<>();
|
|
||||||
keys.add("myconfig1");
|
|
||||||
keys.add("myconfig2");
|
|
||||||
keys.add("myconfig3");
|
|
||||||
|
|
||||||
Map<String, String> hmap = new HashMap<>();
|
|
||||||
hmap.put("meta_key","meta_value");
|
|
||||||
GetConfigurationRequest req = new GetConfigurationRequest(CONFIG_STORE_NAME, keys);
|
|
||||||
req.setMetadata(hmap);
|
|
||||||
|
|
||||||
try {
|
|
||||||
Mono<Map<String, ConfigurationItem>> items = client.getConfiguration(req);
|
|
||||||
items.block().forEach((k,v) -> print(v, k));
|
|
||||||
} catch (Exception ex) {
|
|
||||||
System.out.println(ex.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Subscribe to a list of keys.
|
|
||||||
*
|
|
||||||
* @param client DaprClient object
|
|
||||||
*/
|
|
||||||
public static void subscribeConfigurationRequest(DaprClient client) throws InterruptedException {
|
|
||||||
System.out.println("Subscribing to key: myconfig2");
|
|
||||||
SubscribeConfigurationRequest req = new SubscribeConfigurationRequest(
|
|
||||||
CONFIG_STORE_NAME, Collections.singletonList("myconfig2"));
|
|
||||||
Flux<SubscribeConfigurationResponse> outFlux = client.subscribeConfiguration(req);
|
|
||||||
outFlux.subscribe(
|
|
||||||
cis -> {
|
|
||||||
SUBSCRIPTION_ID = cis.getSubscriptionId();
|
|
||||||
});
|
|
||||||
if (!SUBSCRIPTION_ID.isEmpty()) {
|
|
||||||
System.out.println("subscribing to myconfig2 is successful");
|
|
||||||
} else {
|
|
||||||
System.out.println("error in subscribing to myconfig2");
|
|
||||||
}
|
|
||||||
Thread.sleep(5000);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void print(ConfigurationItem item, String key) {
|
|
||||||
System.out.println(item.getValue() + " : key ->" + key);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,64 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2022 The Dapr 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.dapr.examples.configuration.http;
|
|
||||||
|
|
||||||
import io.dapr.client.domain.SubscribeConfigurationResponse;
|
|
||||||
import io.dapr.examples.DaprApplication;
|
|
||||||
import org.apache.commons.cli.CommandLine;
|
|
||||||
import org.apache.commons.cli.CommandLineParser;
|
|
||||||
import org.apache.commons.cli.DefaultParser;
|
|
||||||
import org.apache.commons.cli.Options;
|
|
||||||
import org.springframework.http.MediaType;
|
|
||||||
import org.springframework.web.bind.annotation.PathVariable;
|
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestBody;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A sample springboot application to register and receive for updates on configuration items sent by Dapr.
|
|
||||||
* Users are free to write their own controllers to handle any specific route suited to the need.
|
|
||||||
* java -jar target/dapr-java-sdk-examples-exec.jar io.dapr.examples.configuration.http.ConfigurationSubscriber -p 3009
|
|
||||||
*/
|
|
||||||
@RestController
|
|
||||||
public class ConfigurationHandler {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Receives a subscription change notification.
|
|
||||||
* @param configStore Path variables for post call
|
|
||||||
* @param key Key whose value has changed
|
|
||||||
* @param response Configuration response
|
|
||||||
*/
|
|
||||||
@PostMapping(path = "/configuration/{configStore}/{key}", produces = MediaType.ALL_VALUE)
|
|
||||||
public void handleConfigUpdate(@PathVariable("configStore") String configStore,
|
|
||||||
@PathVariable("key") String key,
|
|
||||||
@RequestBody SubscribeConfigurationResponse response) {
|
|
||||||
System.out.println("Configuration update received for store: " + configStore);
|
|
||||||
response.getItems().forEach((k,v) -> System.out.println("Key: " + k + " Value :" + v.getValue()));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is entry point for Configuration Subscriber service.
|
|
||||||
* @param args Arguments for main
|
|
||||||
* @throws Exception Throws Exception
|
|
||||||
*/
|
|
||||||
public static void main(String[] args) throws Exception {
|
|
||||||
Options options = new Options();
|
|
||||||
options.addRequiredOption("p", "port", true, "The port this app will listen on");
|
|
||||||
CommandLineParser parser = new DefaultParser();
|
|
||||||
CommandLine cmd = parser.parse(options, args);
|
|
||||||
// If port string is not valid, it will throw an exception.
|
|
||||||
int port = Integer.parseInt(cmd.getOptionValue("port"));
|
|
||||||
DaprApplication.start(port);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,218 +0,0 @@
|
||||||
## Retrieve Configurations via Configuration API
|
|
||||||
|
|
||||||
This example provides the different capabilities provided by Dapr Java SDK for Configuration. For further information about Configuration APIs please refer to [this link](https://docs.dapr.io/developing-applications/building-blocks/configuration/)
|
|
||||||
|
|
||||||
### Using the ConfigurationAPI
|
|
||||||
|
|
||||||
The java SDK exposes several methods for this -
|
|
||||||
* `client.getConfiguration(...)` for getting a configuration for a single/multiple keys.
|
|
||||||
* `client.subscribeConfiguration(...)` for subscribing to a list of keys for any change.
|
|
||||||
* `client.unsubscribeConfiguration(...)` for unsubscribing to changes from subscribed items.
|
|
||||||
|
|
||||||
## Pre-requisites
|
|
||||||
|
|
||||||
* [Dapr CLI](https://docs.dapr.io/getting-started/install-dapr-cli/).
|
|
||||||
* Java JDK 11 (or greater):
|
|
||||||
* [Microsoft JDK 11](https://docs.microsoft.com/en-us/java/openjdk/download#openjdk-11)
|
|
||||||
* [Oracle JDK 11](https://www.oracle.com/technetwork/java/javase/downloads/index.html#JDK11)
|
|
||||||
* [OpenJDK 11](https://jdk.java.net/11/)
|
|
||||||
* [Apache Maven](https://maven.apache.org/install.html) version 3.x.
|
|
||||||
|
|
||||||
### Checking out the code
|
|
||||||
|
|
||||||
Clone this repository:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
git clone https://github.com/dapr/java-sdk.git
|
|
||||||
cd java-sdk
|
|
||||||
```
|
|
||||||
|
|
||||||
Then build the Maven project:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
# make sure you are in the `java-sdk` directory.
|
|
||||||
mvn install
|
|
||||||
```
|
|
||||||
|
|
||||||
Then get into the examples directory:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
cd examples
|
|
||||||
```
|
|
||||||
|
|
||||||
### Initialize Dapr
|
|
||||||
|
|
||||||
Run `dapr init` to initialize Dapr in Self-Hosted Mode if it's not already initialized.
|
|
||||||
|
|
||||||
## Store few dummy configurations in configurationstore
|
|
||||||
<!-- STEP
|
|
||||||
name: Set configuration value
|
|
||||||
expected_stdout_lines:
|
|
||||||
- "OK"
|
|
||||||
timeout_seconds: 20
|
|
||||||
-->
|
|
||||||
|
|
||||||
```bash
|
|
||||||
docker exec dapr_redis redis-cli MSET myconfig1 "val1||1" myconfig2 "val2||1" myconfig3 "val3||1"
|
|
||||||
```
|
|
||||||
<!-- END_STEP -->
|
|
||||||
|
|
||||||
### Running the example
|
|
||||||
|
|
||||||
This example uses the Java SDK Dapr client in order to **Get, Subscribe and Unsubscribe** from configuration items and utilizes `Redis` as configuration store.
|
|
||||||
`ConfigurationClient.java` is the example class demonstrating all 3 features.
|
|
||||||
Check [DaprClient.java](https://github.com/dapr/java-sdk/blob/master/sdk/src/main/java/io/dapr/client/DaprClient.java) for detailed description of the supported APIs.
|
|
||||||
|
|
||||||
```java
|
|
||||||
public class ConfigurationClient {
|
|
||||||
// ...
|
|
||||||
/**
|
|
||||||
* Executes various methods to check the different apis.
|
|
||||||
* @param args arguments
|
|
||||||
* @throws Exception throws Exception
|
|
||||||
*/
|
|
||||||
public static void main(String[] args) throws Exception {
|
|
||||||
System.getProperties().setProperty(Properties.API_PROTOCOL.getName(), DaprApiProtocol.HTTP.name());
|
|
||||||
try (DaprClient client = (new DaprClientBuilder()).build()) {
|
|
||||||
System.out.println("Using Dapr client...");
|
|
||||||
getConfigurations(client);
|
|
||||||
subscribeConfigurationRequest(client);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets configurations for a list of keys.
|
|
||||||
*
|
|
||||||
* @param client DaprClient object
|
|
||||||
*/
|
|
||||||
public static void getConfigurations(DaprClient client) {
|
|
||||||
System.out.println("*******trying to retrieve configurations for a list of keys********");
|
|
||||||
GetConfigurationRequest req = new GetConfigurationRequest(CONFIG_STORE_NAME, keys);
|
|
||||||
try {
|
|
||||||
Mono<List<ConfigurationItem>> items = client.getConfiguration(req);
|
|
||||||
// ...
|
|
||||||
} catch (Exception ex) {
|
|
||||||
// ...
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Subscribe to a list of keys.
|
|
||||||
*
|
|
||||||
* @param client DaprClient object
|
|
||||||
*/
|
|
||||||
public static void subscribeConfigurationRequest(DaprClient client) {
|
|
||||||
// ...
|
|
||||||
SubscribeConfigurationRequest req = new SubscribeConfigurationRequest(
|
|
||||||
CONFIG_STORE_NAME, Collections.singletonList("myconfig2"));
|
|
||||||
Runnable subscribeTask = () -> {
|
|
||||||
Flux<SubscribeConfigurationResponse> outFlux = client.subscribeConfiguration(req);
|
|
||||||
// ...
|
|
||||||
};
|
|
||||||
// ..
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Get into the examples' directory:
|
|
||||||
```sh
|
|
||||||
cd examples
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Running the configuration subscriber app:
|
|
||||||
|
|
||||||
`DaprApplication.start()` Method will run a Spring Boot application containing a `ConfigurationHandler`, a contoller
|
|
||||||
to receive configuration change notifications.
|
|
||||||
|
|
||||||
```java
|
|
||||||
@RestController
|
|
||||||
public class ConfigurationHandler {
|
|
||||||
//...
|
|
||||||
@PostMapping(path = "/configuration/{configStore}/{key}", produces = MediaType.ALL_VALUE)
|
|
||||||
public void handleConfigUpdate(@PathVariable("configStore") String configStore,
|
|
||||||
@PathVariable("key") String key,
|
|
||||||
@RequestBody SubscribeConfigurationResponse response) {
|
|
||||||
System.out.println("Configuration update received for store: " + configStore);
|
|
||||||
response.getItems().forEach((k,v) -> System.out.println("Key: " + k + " Value :" + v.getValue()));
|
|
||||||
}
|
|
||||||
//....
|
|
||||||
}
|
|
||||||
```
|
|
||||||
Execute the following script to run the ConfigSubscriber app:
|
|
||||||
|
|
||||||
<!-- STEP
|
|
||||||
name: Run ConfigurationHandler
|
|
||||||
expected_stdout_lines:
|
|
||||||
- '== APP == Configuration update received for store: configstore'
|
|
||||||
- '== APP == Key: myconfig2 Value :updated_val2'
|
|
||||||
background: true
|
|
||||||
output_match_mode: substring
|
|
||||||
background: true
|
|
||||||
sleep: 5
|
|
||||||
-->
|
|
||||||
|
|
||||||
```bash
|
|
||||||
dapr run --app-id confighandler -- java -jar target/dapr-java-sdk-examples-exec.jar io.dapr.examples.configuration.http.ConfigurationHandler -p 3009
|
|
||||||
```
|
|
||||||
<!-- END_STEP -->
|
|
||||||
|
|
||||||
#### Running the ConfigurationClient app:
|
|
||||||
|
|
||||||
Use the following command to run this example-
|
|
||||||
|
|
||||||
<!-- STEP
|
|
||||||
name: Run ConfigurationClient example
|
|
||||||
expected_stdout_lines:
|
|
||||||
- "== APP == Using Dapr client..."
|
|
||||||
- "== APP == *******trying to retrieve configurations for a list of keys********"
|
|
||||||
- "== APP == val1 : key ->myconfig1"
|
|
||||||
- "== APP == val2 : key ->myconfig2"
|
|
||||||
- "== APP == val3 : key ->myconfig3"
|
|
||||||
- "== APP == Subscribing to key: myconfig2"
|
|
||||||
- "== APP == subscribing to myconfig2 is successful"
|
|
||||||
background: true
|
|
||||||
output_match_mode: substring
|
|
||||||
sleep: 10
|
|
||||||
-->
|
|
||||||
|
|
||||||
```bash
|
|
||||||
dapr run --components-path ./components/configuration --app-id confighttp --log-level debug --app-port 3009 --dapr-http-port 3500 -- java -jar target/dapr-java-sdk-examples-exec.jar io.dapr.examples.configuration.http.ConfigurationClient
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Update myconfig2 key in configurationstore
|
|
||||||
<!-- END_STEP -->
|
|
||||||
|
|
||||||
<!-- STEP
|
|
||||||
name: Update configuration value
|
|
||||||
timeout_seconds: 20
|
|
||||||
-->
|
|
||||||
|
|
||||||
```bash
|
|
||||||
docker exec dapr_redis redis-cli MSET myconfig2 "updated_val2||1"
|
|
||||||
```
|
|
||||||
<!-- END_STEP -->
|
|
||||||
|
|
||||||
### Sample output
|
|
||||||
```
|
|
||||||
== APP == Using Dapr client...
|
|
||||||
== APP == *******trying to retrieve configurations for a list of keys********
|
|
||||||
== APP == val1 : key ->myconfig1
|
|
||||||
== APP == val2 : key ->myconfig2
|
|
||||||
== APP == val3 : key ->myconfig3
|
|
||||||
== APP == Subscribing to key: myconfig2
|
|
||||||
== APP == subscribing to myconfig2 is successful
|
|
||||||
```
|
|
||||||
### Cleanup
|
|
||||||
|
|
||||||
To stop the app, run (or press CTRL+C):
|
|
||||||
|
|
||||||
<!-- STEP
|
|
||||||
name: Cleanup
|
|
||||||
-->
|
|
||||||
|
|
||||||
```bash
|
|
||||||
dapr stop --app-id confighttp
|
|
||||||
dapr stop --app-id confighandler
|
|
||||||
```
|
|
||||||
|
|
||||||
<!-- END_STEP -->
|
|
|
@ -13,17 +13,13 @@ limitations under the License.
|
||||||
|
|
||||||
package io.dapr.examples.invoke.grpc;
|
package io.dapr.examples.invoke.grpc;
|
||||||
|
|
||||||
|
import io.dapr.client.DaprClient;
|
||||||
|
import io.dapr.client.DaprClientBuilder;
|
||||||
import io.dapr.examples.DaprExamplesProtos.HelloReply;
|
import io.dapr.examples.DaprExamplesProtos.HelloReply;
|
||||||
import io.dapr.examples.DaprExamplesProtos.HelloRequest;
|
import io.dapr.examples.DaprExamplesProtos.HelloRequest;
|
||||||
import io.dapr.examples.HelloWorldGrpc;
|
import io.dapr.examples.HelloWorldGrpc;
|
||||||
import io.grpc.Grpc;
|
|
||||||
import io.grpc.InsecureChannelCredentials;
|
|
||||||
import io.grpc.ManagedChannel;
|
|
||||||
import io.grpc.Metadata;
|
|
||||||
import io.grpc.StatusRuntimeException;
|
import io.grpc.StatusRuntimeException;
|
||||||
import io.grpc.stub.MetadataUtils;
|
|
||||||
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
@ -45,22 +41,11 @@ public class HelloWorldClient {
|
||||||
* @param args Array of messages to be sent.
|
* @param args Array of messages to be sent.
|
||||||
*/
|
*/
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
|
|
||||||
String user = "World";
|
String user = "World";
|
||||||
String target = "localhost:" + System.getenv("DAPR_GRPC_PORT");
|
try (DaprClient client = new DaprClientBuilder().build()) {
|
||||||
|
HelloWorldGrpc.HelloWorldBlockingStub blockingStub = client.newGrpcStub(
|
||||||
ManagedChannel channel = Grpc.newChannelBuilder(target, InsecureChannelCredentials.create())
|
"hellogrpc",
|
||||||
.build();
|
channel -> HelloWorldGrpc.newBlockingStub(channel));
|
||||||
|
|
||||||
try {
|
|
||||||
HelloWorldGrpc.HelloWorldBlockingStub blockingStub = HelloWorldGrpc.newBlockingStub(channel);
|
|
||||||
|
|
||||||
Metadata headers = new Metadata();
|
|
||||||
headers.put(Metadata.Key.of("dapr-app-id", Metadata.ASCII_STRING_MARSHALLER),
|
|
||||||
"hellogrpc");
|
|
||||||
|
|
||||||
// MetadataUtils.attachHeaders is deprecated.
|
|
||||||
blockingStub = blockingStub.withInterceptors(MetadataUtils.newAttachHeadersInterceptor(headers));
|
|
||||||
|
|
||||||
logger.info("Will try to greet " + user + " ...");
|
logger.info("Will try to greet " + user + " ...");
|
||||||
try {
|
try {
|
||||||
|
@ -70,10 +55,6 @@ public class HelloWorldClient {
|
||||||
} catch (StatusRuntimeException e) {
|
} catch (StatusRuntimeException e) {
|
||||||
logger.log(Level.WARNING, "RPC failed: {0}", e.getStatus());
|
logger.log(Level.WARNING, "RPC failed: {0}", e.getStatus());
|
||||||
}
|
}
|
||||||
} finally {
|
|
||||||
// To prevent leaking resources like threads and TCP connections
|
|
||||||
// the channel should be shut down when it will no longer be used.
|
|
||||||
channel.shutdownNow().awaitTermination(5, TimeUnit.SECONDS);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,7 +55,7 @@ public class HelloWorldService {
|
||||||
/**
|
/**
|
||||||
* Handling of the 'sayHello' method.
|
* Handling of the 'sayHello' method.
|
||||||
*
|
*
|
||||||
* @param request Request to say something.
|
* @param req Request to say something.
|
||||||
* @return Response with when it was said.
|
* @return Response with when it was said.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -61,7 +61,7 @@ In the `HelloWorldService.java` file, you will find the `HelloWorldService` clas
|
||||||
/**
|
/**
|
||||||
* Handling of the 'sayHello' method.
|
* Handling of the 'sayHello' method.
|
||||||
*
|
*
|
||||||
* @param request Request to say something.
|
* @param req Request to say something.
|
||||||
* @return Response with when it was said.
|
* @return Response with when it was said.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
|
@ -93,27 +93,17 @@ The `app-id` argument is used to identify this service in Dapr's runtime. The `a
|
||||||
|
|
||||||
### Running the example's client
|
### Running the example's client
|
||||||
|
|
||||||
The other component is the client. It will add user name to the grpc request and send it to the server. Open the `HelloWorldClient.java` file, it creates a new grpc channel and sends request directly to the dapr side car through this channel.
|
The other component is the client. It will add user name to the grpc request and send it to the server. Open the `HelloWorldClient.java` file, it uses the DaprClient's grpc channel and sends request directly to the dapr side car through it, including necessary headers.
|
||||||
|
|
||||||
```java
|
```java
|
||||||
private static class HelloWorldClient {
|
private static class HelloWorldClient {
|
||||||
///...
|
///...
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
|
|
||||||
String user = "World";
|
String user = "World";
|
||||||
// Access a service running on the local machine on port 50051
|
try (DaprClient client = new DaprClientBuilder().build()) {
|
||||||
String target = "localhost:50051";
|
HelloWorldGrpc.HelloWorldBlockingStub blockingStub = HelloWorldGrpc.newBlockingStub(client.getGrpcChannel());
|
||||||
|
// Adds Dapr interceptors to populate gRPC metadata automatically.
|
||||||
ManagedChannel channel = Grpc.newChannelBuilder(target, InsecureChannelCredentials.create())
|
blockingStub = DaprClientGrpcInterceptors.intercept("hellogrpc", blockingStub);
|
||||||
.build();
|
|
||||||
|
|
||||||
try {
|
|
||||||
HelloWorldGrpc.HelloWorldBlockingStub blockingStub = HelloWorldGrpc.newBlockingStub(channel);
|
|
||||||
|
|
||||||
Metadata headers = new Metadata();
|
|
||||||
headers.put(Metadata.Key.of("dapr-app-id", Metadata.ASCII_STRING_MARSHALLER),
|
|
||||||
"hellogrpc");
|
|
||||||
blockingStub = MetadataUtils.attachHeaders(blockingStub, headers);
|
|
||||||
|
|
||||||
logger.info("Will try to greet " + user + " ...");
|
logger.info("Will try to greet " + user + " ...");
|
||||||
try {
|
try {
|
||||||
|
@ -123,10 +113,6 @@ private static class HelloWorldClient {
|
||||||
} catch (StatusRuntimeException e) {
|
} catch (StatusRuntimeException e) {
|
||||||
logger.log(Level.WARNING, "RPC failed: {0}", e.getStatus());
|
logger.log(Level.WARNING, "RPC failed: {0}", e.getStatus());
|
||||||
}
|
}
|
||||||
} finally {
|
|
||||||
// To prevent leaking resources like threads and TCP connections
|
|
||||||
// the channel should be shut down when it will no longer be used.
|
|
||||||
channel.shutdownNow().awaitTermination(5, TimeUnit.SECONDS);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
///...
|
///...
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.dapr.examples.lock.grpc;
|
package io.dapr.examples.lock;
|
||||||
|
|
||||||
|
|
||||||
import io.dapr.client.DaprClientBuilder;
|
import io.dapr.client.DaprClientBuilder;
|
|
@ -58,7 +58,7 @@ sleep: 5
|
||||||
-->
|
-->
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
dapr run --components-path ./components/lock --app-id lockgrpc --log-level debug -- java -jar target/dapr-java-sdk-examples-exec.jar io.dapr.examples.lock.grpc.DistributedLockGrpcClient
|
dapr run --components-path ./components/lock --app-id lockgrpc --log-level debug -- java -jar target/dapr-java-sdk-examples-exec.jar io.dapr.examples.lock.DistributedLockGrpcClient
|
||||||
```
|
```
|
||||||
|
|
||||||
<!-- END_STEP -->
|
<!-- END_STEP -->
|
|
@ -1,75 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2022 The Dapr 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.dapr.examples.lock.http;
|
|
||||||
|
|
||||||
|
|
||||||
import io.dapr.client.DaprClientBuilder;
|
|
||||||
import io.dapr.client.DaprPreviewClient;
|
|
||||||
import io.dapr.client.domain.LockRequest;
|
|
||||||
import io.dapr.client.domain.UnlockRequest;
|
|
||||||
import io.dapr.client.domain.UnlockResponseStatus;
|
|
||||||
import reactor.core.publisher.Mono;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* DistributedLockGrpcClient.
|
|
||||||
*/
|
|
||||||
public class DistributedLockHttpClient {
|
|
||||||
private static final String LOCK_STORE_NAME = "lockstore";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Executes various methods to check the different apis.
|
|
||||||
*
|
|
||||||
* @param args arguments
|
|
||||||
* @throws Exception throws Exception
|
|
||||||
*/
|
|
||||||
public static void main(String[] args) throws Exception {
|
|
||||||
try (DaprPreviewClient client = (new DaprClientBuilder()).buildPreviewClient()) {
|
|
||||||
System.out.println("Using preview client...");
|
|
||||||
tryLock(client);
|
|
||||||
unlock(client);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Trying to get lock.
|
|
||||||
*
|
|
||||||
* @param client DaprPreviewClient object
|
|
||||||
*/
|
|
||||||
public static void tryLock(DaprPreviewClient client) {
|
|
||||||
System.out.println("*******trying to get a free distributed lock********");
|
|
||||||
try {
|
|
||||||
LockRequest lockRequest = new LockRequest(LOCK_STORE_NAME, "resouce1", "owner1", 5);
|
|
||||||
Mono<Boolean> result = client.tryLock(lockRequest);
|
|
||||||
System.out.println("Lock result -> " + (Boolean.TRUE.equals(result.block()) ? "SUCCESS" : "FAIL"));
|
|
||||||
} catch (Exception ex) {
|
|
||||||
System.out.println(ex.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unlock a lock.
|
|
||||||
*
|
|
||||||
* @param client DaprPreviewClient object
|
|
||||||
*/
|
|
||||||
public static void unlock(DaprPreviewClient client) {
|
|
||||||
System.out.println("*******unlock a distributed lock********");
|
|
||||||
try {
|
|
||||||
UnlockRequest unlockRequest = new UnlockRequest(LOCK_STORE_NAME, "resouce1", "owner1");
|
|
||||||
Mono<UnlockResponseStatus> result = client.unlock(unlockRequest);
|
|
||||||
System.out.println("Unlock result ->" + result.block().name());
|
|
||||||
} catch (Exception ex) {
|
|
||||||
System.out.println(ex.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,87 +0,0 @@
|
||||||
## Distributed Lock API Example
|
|
||||||
|
|
||||||
This example provides the different capabilities provided by Dapr Java SDK for Distributed Lock. For further information about Distributed Lock APIs please refer to [this link](https://docs.dapr.io/developing-applications/building-blocks/distributed-lock/)
|
|
||||||
**This API is available in Preview Mode**.
|
|
||||||
|
|
||||||
### Using the Distributed Lock API
|
|
||||||
|
|
||||||
The java SDK exposes several methods for this -
|
|
||||||
* `client.tryLock(...)` for getting a free distributed lock
|
|
||||||
* `client.unlock(...)` for unlocking a lock
|
|
||||||
|
|
||||||
## Pre-requisites
|
|
||||||
|
|
||||||
* [Dapr CLI](https://docs.dapr.io/getting-started/install-dapr-cli/).
|
|
||||||
* Java JDK 11 (or greater):
|
|
||||||
* [Microsoft JDK 11](https://docs.microsoft.com/en-us/java/openjdk/download#openjdk-11)
|
|
||||||
* [Oracle JDK 11](https://www.oracle.com/technetwork/java/javase/downloads/index.html#JDK11)
|
|
||||||
* [OpenJDK 11](https://jdk.java.net/11/)
|
|
||||||
* [Apache Maven](https://maven.apache.org/install.html) version 3.x.
|
|
||||||
|
|
||||||
### Checking out the code
|
|
||||||
|
|
||||||
Clone this repository:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
git clone https://github.com/dapr/java-sdk.git
|
|
||||||
cd java-sdk
|
|
||||||
```
|
|
||||||
|
|
||||||
Then build the Maven project:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
# make sure you are in the `java-sdk` directory.
|
|
||||||
mvn install
|
|
||||||
```
|
|
||||||
|
|
||||||
<!-- END_STEP -->
|
|
||||||
|
|
||||||
### Running the example
|
|
||||||
|
|
||||||
Get into the examples' directory:
|
|
||||||
```sh
|
|
||||||
cd examples
|
|
||||||
```
|
|
||||||
|
|
||||||
Use the following command to run this example-
|
|
||||||
|
|
||||||
<!-- STEP
|
|
||||||
name: Run DistributedLockHttpClient example
|
|
||||||
expected_stdout_lines:
|
|
||||||
- "== APP == Using preview client..."
|
|
||||||
- "== APP == *******trying to get a free distributed lock********"
|
|
||||||
- "== APP == Lock result -> SUCCESS"
|
|
||||||
- "== APP == *******unlock a distributed lock********"
|
|
||||||
- "== APP == Unlock result -> SUCCESS"
|
|
||||||
background: true
|
|
||||||
sleep: 5
|
|
||||||
-->
|
|
||||||
|
|
||||||
```bash
|
|
||||||
dapr run --components-path ./components/lock --app-id lockhttp --log-level debug -- java -Ddapr.api.protocol=HTTP -jar target/dapr-java-sdk-examples-exec.jar io.dapr.examples.lock.http.DistributedLockHttpClient
|
|
||||||
```
|
|
||||||
|
|
||||||
<!-- END_STEP -->
|
|
||||||
|
|
||||||
### Sample output
|
|
||||||
```
|
|
||||||
== APP == Using preview client...
|
|
||||||
== APP == *******trying to get a free distributed lock********
|
|
||||||
== APP == Lock result -> SUCCESS
|
|
||||||
== APP == *******unlock a distributed lock********
|
|
||||||
== APP == Unlock result -> SUCCESS
|
|
||||||
```
|
|
||||||
### Cleanup
|
|
||||||
|
|
||||||
To stop the app, run (or press CTRL+C):
|
|
||||||
|
|
||||||
<!-- STEP
|
|
||||||
name: Cleanup
|
|
||||||
-->
|
|
||||||
|
|
||||||
```bash
|
|
||||||
dapr stop --app-id lockhttp
|
|
||||||
```
|
|
||||||
|
|
||||||
<!-- END_STEP -->
|
|
||||||
|
|
|
@ -36,6 +36,20 @@ cd examples
|
||||||
|
|
||||||
Run `dapr init` to initialize Dapr in Self-Hosted Mode if it's not already initialized.
|
Run `dapr init` to initialize Dapr in Self-Hosted Mode if it's not already initialized.
|
||||||
|
|
||||||
|
### Run MongoDB
|
||||||
|
|
||||||
|
<!-- STEP
|
||||||
|
name: Setup mongo container
|
||||||
|
sleep: 5
|
||||||
|
-->
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker-compose -f ./src/main/java/io/dapr/examples/querystate/docker-compose-single-mongo.yml up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
<!-- END_STEP -->
|
||||||
|
|
||||||
|
|
||||||
### Running the State Client
|
### Running the State Client
|
||||||
This example uses the Java SDK Dapr client in order to save bulk state and query state, in this case, an instance of a class. See the code snippets below:
|
This example uses the Java SDK Dapr client in order to save bulk state and query state, in this case, an instance of a class. See the code snippets below:
|
||||||
|
|
||||||
|
@ -282,5 +296,16 @@ name: Cleanup
|
||||||
```bash
|
```bash
|
||||||
dapr stop --app-id query-state-example
|
dapr stop --app-id query-state-example
|
||||||
```
|
```
|
||||||
|
<!-- END_STEP -->
|
||||||
|
|
||||||
|
Then, stop MongoDB container.
|
||||||
|
|
||||||
|
<!-- STEP
|
||||||
|
name: Cleanup MongoDB containers
|
||||||
|
-->
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker-compose -f ./src/main/java/io/dapr/examples/querystate/docker-compose-single-mongo.yml down
|
||||||
|
```
|
||||||
|
|
||||||
<!-- END_STEP -->
|
<!-- END_STEP -->
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
version: '3'
|
||||||
|
services:
|
||||||
|
mongo:
|
||||||
|
image: mongo
|
||||||
|
ports:
|
||||||
|
- "27017:27017"
|
|
@ -36,6 +36,19 @@ cd examples
|
||||||
|
|
||||||
Run `dapr init` to initialize Dapr in Self-Hosted Mode if it's not already initialized.
|
Run `dapr init` to initialize Dapr in Self-Hosted Mode if it's not already initialized.
|
||||||
|
|
||||||
|
### Run MongoDB
|
||||||
|
|
||||||
|
<!-- STEP
|
||||||
|
name: Setup mongo container
|
||||||
|
sleep: 5
|
||||||
|
-->
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker-compose -f ./src/main/java/io/dapr/examples/state/docker-compose-single-mongo.yml up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
<!-- END_STEP -->
|
||||||
|
|
||||||
### Running the StateClient
|
### Running the StateClient
|
||||||
This example uses the Java SDK Dapr client in order to save, retrieve and delete a state, in this case, an instance of a class. Multiple state stores are supported since Dapr 0.4. See the code snippet bellow:
|
This example uses the Java SDK Dapr client in order to save, retrieve and delete a state, in this case, an instance of a class. Multiple state stores are supported since Dapr 0.4. See the code snippet bellow:
|
||||||
|
|
||||||
|
@ -206,3 +219,15 @@ dapr stop --app-id state-example
|
||||||
```
|
```
|
||||||
|
|
||||||
<!-- END_STEP -->
|
<!-- END_STEP -->
|
||||||
|
|
||||||
|
Then, stop MongoDB container.
|
||||||
|
|
||||||
|
<!-- STEP
|
||||||
|
name: Cleanup MongoDB container
|
||||||
|
-->
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker-compose -f ./src/main/java/io/dapr/examples/state/docker-compose-single-mongo.yml down
|
||||||
|
```
|
||||||
|
|
||||||
|
<!-- END_STEP -->
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
version: '3'
|
||||||
|
services:
|
||||||
|
mongo:
|
||||||
|
image: mongo
|
||||||
|
ports:
|
||||||
|
- "27017:27017"
|
|
@ -16,7 +16,6 @@ package io.dapr.examples.workflows.chain;
|
||||||
import io.dapr.workflows.client.DaprWorkflowClient;
|
import io.dapr.workflows.client.DaprWorkflowClient;
|
||||||
import io.dapr.workflows.client.WorkflowInstanceStatus;
|
import io.dapr.workflows.client.WorkflowInstanceStatus;
|
||||||
|
|
||||||
import java.time.Duration;
|
|
||||||
import java.util.concurrent.TimeoutException;
|
import java.util.concurrent.TimeoutException;
|
||||||
|
|
||||||
public class DemoChainClient {
|
public class DemoChainClient {
|
||||||
|
|
|
@ -14,6 +14,7 @@ limitations under the License.
|
||||||
package io.dapr.examples.workflows.continueasnew;
|
package io.dapr.examples.workflows.continueasnew;
|
||||||
|
|
||||||
import io.dapr.workflows.client.DaprWorkflowClient;
|
import io.dapr.workflows.client.DaprWorkflowClient;
|
||||||
|
|
||||||
import java.util.concurrent.TimeoutException;
|
import java.util.concurrent.TimeoutException;
|
||||||
|
|
||||||
public class DemoContinueAsNewClient {
|
public class DemoContinueAsNewClient {
|
||||||
|
|
|
@ -14,6 +14,7 @@ limitations under the License.
|
||||||
package io.dapr.examples.workflows.externalevent;
|
package io.dapr.examples.workflows.externalevent;
|
||||||
|
|
||||||
import io.dapr.workflows.client.DaprWorkflowClient;
|
import io.dapr.workflows.client.DaprWorkflowClient;
|
||||||
|
|
||||||
import java.util.concurrent.TimeoutException;
|
import java.util.concurrent.TimeoutException;
|
||||||
|
|
||||||
public class DemoExternalEventClient {
|
public class DemoExternalEventClient {
|
||||||
|
|
|
@ -13,7 +13,6 @@ limitations under the License.
|
||||||
|
|
||||||
package io.dapr.examples.workflows.subworkflow;
|
package io.dapr.examples.workflows.subworkflow;
|
||||||
|
|
||||||
import io.dapr.examples.workflows.chain.ToUpperCaseActivity;
|
|
||||||
import io.dapr.workflows.runtime.WorkflowActivity;
|
import io.dapr.workflows.runtime.WorkflowActivity;
|
||||||
import io.dapr.workflows.runtime.WorkflowActivityContext;
|
import io.dapr.workflows.runtime.WorkflowActivityContext;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
|
|
@ -13,8 +13,6 @@ limitations under the License.
|
||||||
|
|
||||||
package io.dapr.actors.client;
|
package io.dapr.actors.client;
|
||||||
|
|
||||||
import io.dapr.client.DaprApiProtocol;
|
|
||||||
import io.dapr.client.DaprHttpBuilder;
|
|
||||||
import io.dapr.client.resiliency.ResiliencyOptions;
|
import io.dapr.client.resiliency.ResiliencyOptions;
|
||||||
import io.dapr.config.Properties;
|
import io.dapr.config.Properties;
|
||||||
import io.dapr.utils.Version;
|
import io.dapr.utils.Version;
|
||||||
|
@ -55,33 +53,21 @@ public class ActorClient implements AutoCloseable {
|
||||||
*
|
*
|
||||||
* @param resiliencyOptions Client resiliency options.
|
* @param resiliencyOptions Client resiliency options.
|
||||||
*/
|
*/
|
||||||
public ActorClient(ResiliencyOptions resiliencyOptions) {
|
private ActorClient(ResiliencyOptions resiliencyOptions) {
|
||||||
this(Properties.API_PROTOCOL.get(), resiliencyOptions);
|
this(buildManagedChannel(), resiliencyOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiates a new channel for Dapr sidecar communication.
|
* Instantiates a new channel for Dapr sidecar communication.
|
||||||
*
|
*
|
||||||
* @param apiProtocol Dapr's API protocol.
|
|
||||||
* @param resiliencyOptions Client resiliency options.
|
|
||||||
*/
|
|
||||||
private ActorClient(DaprApiProtocol apiProtocol, ResiliencyOptions resiliencyOptions) {
|
|
||||||
this(apiProtocol, buildManagedChannel(apiProtocol), resiliencyOptions);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Instantiates a new channel for Dapr sidecar communication.
|
|
||||||
*
|
|
||||||
* @param apiProtocol Dapr's API protocol.
|
|
||||||
* @param grpcManagedChannel gRPC channel.
|
* @param grpcManagedChannel gRPC channel.
|
||||||
* @param resiliencyOptions Client resiliency options.
|
* @param resiliencyOptions Client resiliency options.
|
||||||
*/
|
*/
|
||||||
private ActorClient(
|
private ActorClient(
|
||||||
DaprApiProtocol apiProtocol,
|
|
||||||
ManagedChannel grpcManagedChannel,
|
ManagedChannel grpcManagedChannel,
|
||||||
ResiliencyOptions resiliencyOptions) {
|
ResiliencyOptions resiliencyOptions) {
|
||||||
this.grpcManagedChannel = grpcManagedChannel;
|
this.grpcManagedChannel = grpcManagedChannel;
|
||||||
this.daprClient = buildDaprClient(apiProtocol, grpcManagedChannel, resiliencyOptions);
|
this.daprClient = buildDaprClient(grpcManagedChannel, resiliencyOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -110,14 +96,9 @@ public class ActorClient implements AutoCloseable {
|
||||||
/**
|
/**
|
||||||
* Creates a GRPC managed channel (or null, if not applicable).
|
* Creates a GRPC managed channel (or null, if not applicable).
|
||||||
*
|
*
|
||||||
* @param apiProtocol Dapr's API protocol.
|
|
||||||
* @return GRPC managed channel or null.
|
* @return GRPC managed channel or null.
|
||||||
*/
|
*/
|
||||||
private static ManagedChannel buildManagedChannel(DaprApiProtocol apiProtocol) {
|
private static ManagedChannel buildManagedChannel() {
|
||||||
if (apiProtocol != DaprApiProtocol.GRPC) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
int port = Properties.GRPC_PORT.get();
|
int port = Properties.GRPC_PORT.get();
|
||||||
if (port <= 0) {
|
if (port <= 0) {
|
||||||
throw new IllegalArgumentException("Invalid port.");
|
throw new IllegalArgumentException("Invalid port.");
|
||||||
|
@ -136,16 +117,8 @@ public class ActorClient implements AutoCloseable {
|
||||||
* @throws java.lang.IllegalStateException if any required field is missing
|
* @throws java.lang.IllegalStateException if any required field is missing
|
||||||
*/
|
*/
|
||||||
private static DaprClient buildDaprClient(
|
private static DaprClient buildDaprClient(
|
||||||
DaprApiProtocol apiProtocol,
|
|
||||||
Channel grpcManagedChannel,
|
Channel grpcManagedChannel,
|
||||||
ResiliencyOptions resiliencyOptions) {
|
ResiliencyOptions resiliencyOptions) {
|
||||||
switch (apiProtocol) {
|
return new DaprClientImpl(DaprGrpc.newStub(grpcManagedChannel), resiliencyOptions);
|
||||||
case GRPC: return new DaprGrpcClient(DaprGrpc.newStub(grpcManagedChannel), resiliencyOptions);
|
|
||||||
case HTTP: {
|
|
||||||
LOGGER.warn("HTTP client protocol is deprecated and will be removed in Dapr's Java SDK version 1.10.");
|
|
||||||
return new DaprHttpClient(new DaprHttpBuilder().build());
|
|
||||||
}
|
|
||||||
default: throw new IllegalStateException("Unsupported protocol: " + apiProtocol.name());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ import com.google.protobuf.ByteString;
|
||||||
import io.dapr.client.resiliency.ResiliencyOptions;
|
import io.dapr.client.resiliency.ResiliencyOptions;
|
||||||
import io.dapr.config.Properties;
|
import io.dapr.config.Properties;
|
||||||
import io.dapr.exceptions.DaprException;
|
import io.dapr.exceptions.DaprException;
|
||||||
import io.dapr.internal.opencensus.GrpcWrapper;
|
import io.dapr.internal.grpc.DaprClientGrpcInterceptors;
|
||||||
import io.dapr.internal.resiliency.RetryPolicy;
|
import io.dapr.internal.resiliency.RetryPolicy;
|
||||||
import io.dapr.internal.resiliency.TimeoutPolicy;
|
import io.dapr.internal.resiliency.TimeoutPolicy;
|
||||||
import io.dapr.v1.DaprGrpc;
|
import io.dapr.v1.DaprGrpc;
|
||||||
|
@ -40,7 +40,7 @@ import java.util.function.Consumer;
|
||||||
/**
|
/**
|
||||||
* A DaprClient over GRPC for Actor.
|
* A DaprClient over GRPC for Actor.
|
||||||
*/
|
*/
|
||||||
class DaprGrpcClient implements DaprClient {
|
class DaprClientImpl implements DaprClient {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Timeout policy for SDK calls to Dapr API.
|
* Timeout policy for SDK calls to Dapr API.
|
||||||
|
@ -63,7 +63,7 @@ class DaprGrpcClient implements DaprClient {
|
||||||
* @param grpcClient Dapr's GRPC client.
|
* @param grpcClient Dapr's GRPC client.
|
||||||
* @param resiliencyOptions Client resiliency options (optional)
|
* @param resiliencyOptions Client resiliency options (optional)
|
||||||
*/
|
*/
|
||||||
DaprGrpcClient(DaprGrpc.DaprStub grpcClient, ResiliencyOptions resiliencyOptions) {
|
DaprClientImpl(DaprGrpc.DaprStub grpcClient, ResiliencyOptions resiliencyOptions) {
|
||||||
this.client = intercept(grpcClient);
|
this.client = intercept(grpcClient);
|
||||||
this.timeoutPolicy = new TimeoutPolicy(
|
this.timeoutPolicy = new TimeoutPolicy(
|
||||||
resiliencyOptions == null ? null : resiliencyOptions.getTimeout());
|
resiliencyOptions == null ? null : resiliencyOptions.getTimeout());
|
||||||
|
@ -85,7 +85,7 @@ class DaprGrpcClient implements DaprClient {
|
||||||
.build();
|
.build();
|
||||||
return Mono.deferContextual(
|
return Mono.deferContextual(
|
||||||
context -> this.<DaprProtos.InvokeActorResponse>createMono(
|
context -> this.<DaprProtos.InvokeActorResponse>createMono(
|
||||||
it -> intercept(context, client).invokeActor(req, it)
|
it -> intercept(context, this.timeoutPolicy, client).invokeActor(req, it)
|
||||||
)
|
)
|
||||||
).map(r -> r.getData().toByteArray());
|
).map(r -> r.getData().toByteArray());
|
||||||
}
|
}
|
||||||
|
@ -124,11 +124,13 @@ class DaprGrpcClient implements DaprClient {
|
||||||
* Populates GRPC client with interceptors for telemetry.
|
* Populates GRPC client with interceptors for telemetry.
|
||||||
*
|
*
|
||||||
* @param context Reactor's context.
|
* @param context Reactor's context.
|
||||||
|
* @param timeoutPolicy Timeout policy for gRPC call.
|
||||||
* @param client GRPC client for Dapr.
|
* @param client GRPC client for Dapr.
|
||||||
* @return Client after adding interceptors.
|
* @return Client after adding interceptors.
|
||||||
*/
|
*/
|
||||||
private static DaprGrpc.DaprStub intercept(ContextView context, DaprGrpc.DaprStub client) {
|
private static DaprGrpc.DaprStub intercept(
|
||||||
return GrpcWrapper.intercept(context, client);
|
ContextView context, TimeoutPolicy timeoutPolicy, DaprGrpc.DaprStub client) {
|
||||||
|
return DaprClientGrpcInterceptors.intercept(client, timeoutPolicy, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
private <T> Mono<T> createMono(Consumer<StreamObserver<T>> consumer) {
|
private <T> Mono<T> createMono(Consumer<StreamObserver<T>> consumer) {
|
|
@ -1,53 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2021 The Dapr 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.dapr.actors.client;
|
|
||||||
|
|
||||||
import io.dapr.client.DaprHttp;
|
|
||||||
import reactor.core.publisher.Mono;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* DaprClient over HTTP for actor client.
|
|
||||||
* @deprecated This class will be deleted at SDK release version 1.10.
|
|
||||||
* @see DaprHttp
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
class DaprHttpClient implements DaprClient {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The HTTP client to be used.
|
|
||||||
*
|
|
||||||
* @see DaprHttp
|
|
||||||
*/
|
|
||||||
private final DaprHttp client;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Instantiates a new Dapr Http Client to invoke Actors.
|
|
||||||
*
|
|
||||||
* @param client Dapr's http client.
|
|
||||||
*/
|
|
||||||
DaprHttpClient(DaprHttp client) {
|
|
||||||
this.client = client;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Mono<byte[]> invoke(String actorType, String actorId, String methodName, byte[] jsonPayload) {
|
|
||||||
String[] pathSegments = new String[] { DaprHttp.API_VERSION, "actors", actorType, actorId, "method", methodName };
|
|
||||||
Mono<DaprHttp.Response> responseMono =
|
|
||||||
this.client.invokeApi(DaprHttp.HttpMethods.POST.name(), pathSegments, null, jsonPayload, null, null);
|
|
||||||
return responseMono.map(r -> r.getBody());
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -15,8 +15,6 @@ package io.dapr.actors.runtime;
|
||||||
|
|
||||||
import io.dapr.actors.ActorId;
|
import io.dapr.actors.ActorId;
|
||||||
import io.dapr.actors.ActorTrace;
|
import io.dapr.actors.ActorTrace;
|
||||||
import io.dapr.client.DaprApiProtocol;
|
|
||||||
import io.dapr.client.DaprHttpBuilder;
|
|
||||||
import io.dapr.config.Properties;
|
import io.dapr.config.Properties;
|
||||||
import io.dapr.serializer.DaprObjectSerializer;
|
import io.dapr.serializer.DaprObjectSerializer;
|
||||||
import io.dapr.serializer.DefaultObjectSerializer;
|
import io.dapr.serializer.DefaultObjectSerializer;
|
||||||
|
@ -312,16 +310,12 @@ public class ActorRuntime implements Closeable {
|
||||||
/**
|
/**
|
||||||
* Build an instance of the Client based on the provided setup.
|
* Build an instance of the Client based on the provided setup.
|
||||||
*
|
*
|
||||||
* @param channel GRPC managed channel (or null, if not using GRPC).
|
* @param channel GRPC managed channel.
|
||||||
* @return an instance of the setup Client
|
* @return an instance of the setup Client
|
||||||
* @throws java.lang.IllegalStateException if any required field is missing
|
* @throws java.lang.IllegalStateException if any required field is missing
|
||||||
*/
|
*/
|
||||||
private static DaprClient buildDaprClient(ManagedChannel channel) {
|
private static DaprClient buildDaprClient(ManagedChannel channel) {
|
||||||
if (Properties.API_PROTOCOL.get() == DaprApiProtocol.GRPC) {
|
return new DaprGrpcClient(channel);
|
||||||
return new DaprGrpcClient(channel);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new DaprHttpClient(new DaprHttpBuilder().build());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -330,10 +324,6 @@ public class ActorRuntime implements Closeable {
|
||||||
* @return GRPC managed channel or null.
|
* @return GRPC managed channel or null.
|
||||||
*/
|
*/
|
||||||
private static ManagedChannel buildManagedChannel() {
|
private static ManagedChannel buildManagedChannel() {
|
||||||
if (Properties.API_PROTOCOL.get() != DaprApiProtocol.GRPC) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
int port = Properties.GRPC_PORT.get();
|
int port = Properties.GRPC_PORT.get();
|
||||||
if (port <= 0) {
|
if (port <= 0) {
|
||||||
throw new IllegalStateException("Invalid port.");
|
throw new IllegalStateException("Invalid port.");
|
||||||
|
|
|
@ -14,9 +14,9 @@ limitations under the License.
|
||||||
package io.dapr.actors;
|
package io.dapr.actors;
|
||||||
|
|
||||||
import io.dapr.exceptions.DaprException;
|
import io.dapr.exceptions.DaprException;
|
||||||
|
import org.apache.commons.validator.routines.InetAddressValidator;
|
||||||
import org.junit.jupiter.api.Assertions;
|
import org.junit.jupiter.api.Assertions;
|
||||||
import org.junit.jupiter.api.function.Executable;
|
import org.junit.jupiter.api.function.Executable;
|
||||||
import org.apache.commons.validator.routines.InetAddressValidator;
|
|
||||||
|
|
||||||
public final class TestUtils {
|
public final class TestUtils {
|
||||||
|
|
||||||
|
|
|
@ -32,9 +32,10 @@ import java.io.IOException;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
|
|
||||||
import static io.dapr.actors.TestUtils.assertThrowsDaprException;
|
import static io.dapr.actors.TestUtils.assertThrowsDaprException;
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.mockito.AdditionalAnswers.delegatesTo;
|
import static org.mockito.AdditionalAnswers.delegatesTo;
|
||||||
import static org.mockito.Mockito.*;
|
import static org.mockito.Mockito.mock;
|
||||||
|
|
||||||
public class DaprGrpcClientTest {
|
public class DaprGrpcClientTest {
|
||||||
|
|
||||||
|
@ -89,7 +90,7 @@ public class DaprGrpcClientTest {
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
private DaprGrpcClient client;
|
private DaprClientImpl client;
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
public void setup() throws IOException {
|
public void setup() throws IOException {
|
||||||
|
@ -105,7 +106,7 @@ public class DaprGrpcClientTest {
|
||||||
InProcessChannelBuilder.forName(serverName).directExecutor().build());
|
InProcessChannelBuilder.forName(serverName).directExecutor().build());
|
||||||
|
|
||||||
// Create a HelloWorldClient using the in-process channel;
|
// Create a HelloWorldClient using the in-process channel;
|
||||||
client = new DaprGrpcClient(DaprGrpc.newStub(channel), null);
|
client = new DaprClientImpl(DaprGrpc.newStub(channel), null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -1,98 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2021 The Dapr 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.dapr.actors.client;
|
|
||||||
|
|
||||||
import io.dapr.client.DaprHttp;
|
|
||||||
import io.dapr.client.DaprHttpProxy;
|
|
||||||
import io.dapr.config.Properties;
|
|
||||||
import okhttp3.OkHttpClient;
|
|
||||||
import okhttp3.ResponseBody;
|
|
||||||
import okhttp3.mock.Behavior;
|
|
||||||
import okhttp3.mock.MediaTypes;
|
|
||||||
import okhttp3.mock.MockInterceptor;
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import reactor.core.publisher.Mono;
|
|
||||||
|
|
||||||
import static io.dapr.actors.TestUtils.formatIpAddress;
|
|
||||||
import static io.dapr.actors.TestUtils.assertThrowsDaprException;
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
|
||||||
|
|
||||||
public class DaprHttpClientTest {
|
|
||||||
|
|
||||||
private DaprHttpClient DaprHttpClient;
|
|
||||||
|
|
||||||
private OkHttpClient okHttpClient;
|
|
||||||
|
|
||||||
private MockInterceptor mockInterceptor;
|
|
||||||
|
|
||||||
private String sidecarIp;
|
|
||||||
|
|
||||||
private final String EXPECTED_RESULT = "{\"data\":\"ewoJCSJwcm9wZXJ0eUEiOiAidmFsdWVBIiwKCQkicHJvcGVydHlCIjogInZhbHVlQiIKCX0=\"}";
|
|
||||||
|
|
||||||
@BeforeEach
|
|
||||||
public void setUp() {
|
|
||||||
sidecarIp = formatIpAddress(Properties.SIDECAR_IP.get());
|
|
||||||
mockInterceptor = new MockInterceptor(Behavior.UNORDERED);
|
|
||||||
okHttpClient = new OkHttpClient.Builder().addInterceptor(mockInterceptor).build();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void invokeActorMethod() {
|
|
||||||
mockInterceptor.addRule()
|
|
||||||
.post("http://" + sidecarIp + ":3000/v1.0/actors/DemoActor/1/method/Payment")
|
|
||||||
.respond(EXPECTED_RESULT);
|
|
||||||
DaprHttp daprHttp = new DaprHttpProxy(sidecarIp, 3000, okHttpClient);
|
|
||||||
DaprHttpClient = new DaprHttpClient(daprHttp);
|
|
||||||
Mono<byte[]> mono =
|
|
||||||
DaprHttpClient.invoke("DemoActor", "1", "Payment", "".getBytes());
|
|
||||||
assertEquals(new String(mono.block()), EXPECTED_RESULT);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void invokeActorMethodIPv6() {
|
|
||||||
String prevSidecarIp = sidecarIp;
|
|
||||||
System.setProperty(Properties.SIDECAR_IP.getName(), "2001:db8:3333:4444:5555:6666:7777:8888");
|
|
||||||
sidecarIp = formatIpAddress(Properties.SIDECAR_IP.get());
|
|
||||||
mockInterceptor.addRule()
|
|
||||||
.post("http://" + sidecarIp + ":3000/v1.0/actors/DemoActor/1/method/Payment")
|
|
||||||
.respond(EXPECTED_RESULT);
|
|
||||||
DaprHttp daprHttp = new DaprHttpProxy(sidecarIp, 3000, okHttpClient);
|
|
||||||
DaprHttpClient = new DaprHttpClient(daprHttp);
|
|
||||||
System.setProperty(Properties.SIDECAR_IP.getName(), prevSidecarIp);
|
|
||||||
Mono<byte[]> mono =
|
|
||||||
DaprHttpClient.invoke("DemoActor", "1", "Payment", "".getBytes());
|
|
||||||
assertEquals(new String(mono.block()), EXPECTED_RESULT);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void invokeActorMethodError() {
|
|
||||||
mockInterceptor.addRule()
|
|
||||||
.post("http://" + sidecarIp + ":3000/v1.0/actors/DemoActor/1/method/Payment")
|
|
||||||
.respond(404,
|
|
||||||
ResponseBody.create("" +
|
|
||||||
"{\"errorCode\":\"ERR_SOMETHING\"," +
|
|
||||||
"\"message\":\"error message\"}", MediaTypes.MEDIATYPE_JSON));
|
|
||||||
DaprHttp daprHttp = new DaprHttpProxy(sidecarIp, 3000, okHttpClient);
|
|
||||||
DaprHttpClient = new DaprHttpClient(daprHttp);
|
|
||||||
Mono<byte[]> mono =
|
|
||||||
DaprHttpClient.invoke("DemoActor", "1", "Payment", "".getBytes());
|
|
||||||
|
|
||||||
assertThrowsDaprException(
|
|
||||||
"ERR_SOMETHING",
|
|
||||||
"ERR_SOMETHING: error message",
|
|
||||||
() -> mono.block());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -19,7 +19,6 @@ import io.dapr.serializer.DefaultObjectSerializer;
|
||||||
import io.dapr.utils.TypeRef;
|
import io.dapr.utils.TypeRef;
|
||||||
import org.junit.jupiter.api.Assertions;
|
import org.junit.jupiter.api.Assertions;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.Assertions;
|
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
|
@ -39,8 +39,10 @@ import java.util.List;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
|
|
||||||
import static io.dapr.actors.TestUtils.assertThrowsDaprException;
|
import static io.dapr.actors.TestUtils.assertThrowsDaprException;
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
public class DaprGrpcClientTest {
|
public class DaprGrpcClientTest {
|
||||||
|
|
||||||
|
|
|
@ -35,10 +35,10 @@ import java.util.Base64;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import static io.dapr.actors.TestUtils.formatIpAddress;
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||||
import static org.junit.jupiter.api.Assertions.fail;
|
import static org.junit.jupiter.api.Assertions.fail;
|
||||||
import static io.dapr.actors.TestUtils.formatIpAddress;
|
|
||||||
|
|
||||||
public class DaprHttpClientTest {
|
public class DaprHttpClientTest {
|
||||||
|
|
||||||
|
|
|
@ -25,8 +25,12 @@ import reactor.core.publisher.Mono;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
import static org.mockito.ArgumentMatchers.*;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
import static org.mockito.Mockito.*;
|
import static org.mockito.ArgumentMatchers.argThat;
|
||||||
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests for the state store facade.
|
* Tests for the state store facade.
|
||||||
|
|
|
@ -19,7 +19,6 @@ import io.dapr.actors.client.ActorProxy;
|
||||||
import io.dapr.actors.client.ActorProxyImplForTests;
|
import io.dapr.actors.client.ActorProxyImplForTests;
|
||||||
import io.dapr.actors.client.DaprClientStub;
|
import io.dapr.actors.client.DaprClientStub;
|
||||||
import io.dapr.serializer.DefaultObjectSerializer;
|
import io.dapr.serializer.DefaultObjectSerializer;
|
||||||
import org.junit.jupiter.api.Assertions;
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,3 @@ services:
|
||||||
image: mongo
|
image: mongo
|
||||||
ports:
|
ports:
|
||||||
- "27017:27017"
|
- "27017:27017"
|
||||||
redis:
|
|
||||||
image: redis
|
|
||||||
ports:
|
|
||||||
- "6379:6379"
|
|
||||||
|
|
|
@ -13,7 +13,6 @@ limitations under the License.
|
||||||
|
|
||||||
package io.dapr.it;
|
package io.dapr.it;
|
||||||
|
|
||||||
import io.dapr.client.DaprApiProtocol;
|
|
||||||
import io.dapr.config.Properties;
|
import io.dapr.config.Properties;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -28,7 +27,7 @@ import static io.dapr.it.Retry.callWithRetry;
|
||||||
public class AppRun implements Stoppable {
|
public class AppRun implements Stoppable {
|
||||||
|
|
||||||
private static final String APP_COMMAND =
|
private static final String APP_COMMAND =
|
||||||
"mvn exec:java -B -D exec.mainClass=%s -D exec.classpathScope=test -D exec.args=\"%s\" -D %s=%s -D %s=%s";
|
"mvn exec:java -B -D exec.mainClass=%s -D exec.classpathScope=test -D exec.args=\"%s\"";
|
||||||
|
|
||||||
private final DaprPorts ports;
|
private final DaprPorts ports;
|
||||||
|
|
||||||
|
@ -39,11 +38,10 @@ public class AppRun implements Stoppable {
|
||||||
AppRun(DaprPorts ports,
|
AppRun(DaprPorts ports,
|
||||||
String successMessage,
|
String successMessage,
|
||||||
Class serviceClass,
|
Class serviceClass,
|
||||||
int maxWaitMilliseconds,
|
int maxWaitMilliseconds) {
|
||||||
DaprApiProtocol protocol) {
|
|
||||||
this.command = new Command(
|
this.command = new Command(
|
||||||
successMessage,
|
successMessage,
|
||||||
buildCommand(serviceClass, ports, protocol),
|
buildCommand(serviceClass, ports),
|
||||||
new HashMap<>() {{
|
new HashMap<>() {{
|
||||||
put("DAPR_HTTP_PORT", ports.getHttpPort().toString());
|
put("DAPR_HTTP_PORT", ports.getHttpPort().toString());
|
||||||
put("DAPR_GRPC_PORT", ports.getGrpcPort().toString());
|
put("DAPR_GRPC_PORT", ports.getGrpcPort().toString());
|
||||||
|
@ -81,11 +79,9 @@ public class AppRun implements Stoppable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String buildCommand(Class serviceClass, DaprPorts ports, DaprApiProtocol protocol) {
|
private static String buildCommand(Class serviceClass, DaprPorts ports) {
|
||||||
return String.format(APP_COMMAND, serviceClass.getCanonicalName(),
|
return String.format(APP_COMMAND, serviceClass.getCanonicalName(),
|
||||||
ports.getAppPort() != null ? ports.getAppPort().toString() : "",
|
ports.getAppPort() != null ? ports.getAppPort().toString() : "");
|
||||||
Properties.API_PROTOCOL.getName(), protocol,
|
|
||||||
Properties.API_METHOD_INVOCATION_PROTOCOL.getName(), protocol);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void assertListeningOnPort(int port) {
|
private static void assertListeningOnPort(int port) {
|
||||||
|
@ -101,4 +97,7 @@ public class AppRun implements Stoppable {
|
||||||
System.out.printf("Confirmed listening on port %d.\n", port);
|
System.out.printf("Confirmed listening on port %d.\n", port);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public enum AppProtocol {
|
||||||
|
HTTP, GRPC;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,18 +14,19 @@ limitations under the License.
|
||||||
package io.dapr.it;
|
package io.dapr.it;
|
||||||
|
|
||||||
import io.dapr.actors.client.ActorClient;
|
import io.dapr.actors.client.ActorClient;
|
||||||
import io.dapr.client.DaprApiProtocol;
|
|
||||||
import io.dapr.client.resiliency.ResiliencyOptions;
|
import io.dapr.client.resiliency.ResiliencyOptions;
|
||||||
import org.apache.commons.lang3.tuple.ImmutablePair;
|
import org.apache.commons.lang3.tuple.ImmutablePair;
|
||||||
import org.junit.jupiter.api.AfterAll;
|
import org.junit.jupiter.api.AfterAll;
|
||||||
|
|
||||||
|
import java.lang.reflect.Constructor;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Queue;
|
import java.util.Queue;
|
||||||
|
|
||||||
import static io.dapr.client.DaprApiProtocol.GRPC;
|
import static io.dapr.it.AppRun.AppProtocol.GRPC;
|
||||||
import static io.dapr.client.DaprApiProtocol.HTTP;
|
import static io.dapr.it.AppRun.AppProtocol.HTTP;
|
||||||
|
|
||||||
public abstract class BaseIT {
|
public abstract class BaseIT {
|
||||||
|
|
||||||
|
@ -52,7 +53,7 @@ public abstract class BaseIT {
|
||||||
String testName,
|
String testName,
|
||||||
String successMessage,
|
String successMessage,
|
||||||
Class serviceClass,
|
Class serviceClass,
|
||||||
DaprApiProtocol appProtocol,
|
AppRun.AppProtocol appProtocol,
|
||||||
int maxWaitMilliseconds) throws Exception {
|
int maxWaitMilliseconds) throws Exception {
|
||||||
return startDaprApp(testName, successMessage, serviceClass, true, maxWaitMilliseconds, GRPC, appProtocol);
|
return startDaprApp(testName, successMessage, serviceClass, true, maxWaitMilliseconds, GRPC, appProtocol);
|
||||||
}
|
}
|
||||||
|
@ -63,7 +64,7 @@ public abstract class BaseIT {
|
||||||
Class serviceClass,
|
Class serviceClass,
|
||||||
Boolean useAppPort,
|
Boolean useAppPort,
|
||||||
int maxWaitMilliseconds,
|
int maxWaitMilliseconds,
|
||||||
DaprApiProtocol protocol) throws Exception {
|
AppRun.AppProtocol protocol) throws Exception {
|
||||||
return startDaprApp(
|
return startDaprApp(
|
||||||
testName,
|
testName,
|
||||||
successMessage,
|
successMessage,
|
||||||
|
@ -81,8 +82,8 @@ public abstract class BaseIT {
|
||||||
Class serviceClass,
|
Class serviceClass,
|
||||||
Boolean useAppPort,
|
Boolean useAppPort,
|
||||||
int maxWaitMilliseconds,
|
int maxWaitMilliseconds,
|
||||||
DaprApiProtocol protocol,
|
AppRun.AppProtocol protocol,
|
||||||
DaprApiProtocol appProtocol) throws Exception {
|
AppRun.AppProtocol appProtocol) throws Exception {
|
||||||
return startDaprApp(
|
return startDaprApp(
|
||||||
testName,
|
testName,
|
||||||
successMessage,
|
successMessage,
|
||||||
|
@ -115,14 +116,13 @@ public abstract class BaseIT {
|
||||||
Boolean useAppPort,
|
Boolean useAppPort,
|
||||||
Boolean useDaprPorts,
|
Boolean useDaprPorts,
|
||||||
int maxWaitMilliseconds,
|
int maxWaitMilliseconds,
|
||||||
DaprApiProtocol protocol,
|
AppRun.AppProtocol protocol,
|
||||||
DaprApiProtocol appProtocol) throws Exception {
|
AppRun.AppProtocol appProtocol) throws Exception {
|
||||||
DaprRun.Builder builder = new DaprRun.Builder(
|
DaprRun.Builder builder = new DaprRun.Builder(
|
||||||
testName,
|
testName,
|
||||||
() -> DaprPorts.build(useAppPort, useDaprPorts, useDaprPorts),
|
() -> DaprPorts.build(useAppPort, useDaprPorts, useDaprPorts),
|
||||||
successMessage,
|
successMessage,
|
||||||
maxWaitMilliseconds,
|
maxWaitMilliseconds,
|
||||||
protocol,
|
|
||||||
appProtocol).withServiceClass(serviceClass);
|
appProtocol).withServiceClass(serviceClass);
|
||||||
DaprRun run = builder.build();
|
DaprRun run = builder.build();
|
||||||
TO_BE_STOPPED.add(run);
|
TO_BE_STOPPED.add(run);
|
||||||
|
@ -139,7 +139,7 @@ public abstract class BaseIT {
|
||||||
Boolean useAppPort,
|
Boolean useAppPort,
|
||||||
int maxWaitMilliseconds) throws Exception {
|
int maxWaitMilliseconds) throws Exception {
|
||||||
return startSplitDaprAndApp(
|
return startSplitDaprAndApp(
|
||||||
testName, successMessage, serviceClass, useAppPort, maxWaitMilliseconds, DaprApiProtocol.GRPC);
|
testName, successMessage, serviceClass, useAppPort, maxWaitMilliseconds, AppRun.AppProtocol.GRPC);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static ImmutablePair<AppRun, DaprRun> startSplitDaprAndApp(
|
protected static ImmutablePair<AppRun, DaprRun> startSplitDaprAndApp(
|
||||||
|
@ -148,7 +148,7 @@ public abstract class BaseIT {
|
||||||
Class serviceClass,
|
Class serviceClass,
|
||||||
Boolean useAppPort,
|
Boolean useAppPort,
|
||||||
int maxWaitMilliseconds,
|
int maxWaitMilliseconds,
|
||||||
DaprApiProtocol protocol) throws Exception {
|
AppRun.AppProtocol protocol) throws Exception {
|
||||||
return startSplitDaprAndApp(
|
return startSplitDaprAndApp(
|
||||||
testName,
|
testName,
|
||||||
successMessage,
|
successMessage,
|
||||||
|
@ -165,14 +165,13 @@ public abstract class BaseIT {
|
||||||
Class serviceClass,
|
Class serviceClass,
|
||||||
Boolean useAppPort,
|
Boolean useAppPort,
|
||||||
int maxWaitMilliseconds,
|
int maxWaitMilliseconds,
|
||||||
DaprApiProtocol protocol,
|
AppRun.AppProtocol protocol,
|
||||||
DaprApiProtocol appProtocol) throws Exception {
|
AppRun.AppProtocol appProtocol) throws Exception {
|
||||||
DaprRun.Builder builder = new DaprRun.Builder(
|
DaprRun.Builder builder = new DaprRun.Builder(
|
||||||
testName,
|
testName,
|
||||||
() -> DaprPorts.build(useAppPort, true, true),
|
() -> DaprPorts.build(useAppPort, true, true),
|
||||||
successMessage,
|
successMessage,
|
||||||
maxWaitMilliseconds,
|
maxWaitMilliseconds,
|
||||||
protocol,
|
|
||||||
appProtocol).withServiceClass(serviceClass);
|
appProtocol).withServiceClass(serviceClass);
|
||||||
ImmutablePair<AppRun, DaprRun> runs = builder.splitBuild();
|
ImmutablePair<AppRun, DaprRun> runs = builder.splitBuild();
|
||||||
TO_BE_STOPPED.add(runs.left);
|
TO_BE_STOPPED.add(runs.left);
|
||||||
|
@ -199,9 +198,21 @@ public abstract class BaseIT {
|
||||||
return newActorClient(null);
|
return newActorClient(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static ActorClient newActorClient(ResiliencyOptions resiliencyOptions) {
|
protected static ActorClient newActorClient(ResiliencyOptions resiliencyOptions) throws RuntimeException {
|
||||||
ActorClient client = new ActorClient(resiliencyOptions);
|
try {
|
||||||
TO_BE_CLOSED.add(client);
|
Constructor<ActorClient> constructor = ActorClient.class.getDeclaredConstructor(ResiliencyOptions.class);
|
||||||
return client;
|
constructor.setAccessible(true);
|
||||||
|
ActorClient client = constructor.newInstance(resiliencyOptions);
|
||||||
|
TO_BE_CLOSED.add(client);
|
||||||
|
return client;
|
||||||
|
} catch (NoSuchMethodException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
} catch (InvocationTargetException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
} catch (InstantiationException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,6 @@ limitations under the License.
|
||||||
package io.dapr.it;
|
package io.dapr.it;
|
||||||
|
|
||||||
import com.google.protobuf.Empty;
|
import com.google.protobuf.Empty;
|
||||||
import io.dapr.client.DaprApiProtocol;
|
|
||||||
import io.dapr.config.Properties;
|
import io.dapr.config.Properties;
|
||||||
import io.dapr.v1.AppCallbackHealthCheckGrpc;
|
import io.dapr.v1.AppCallbackHealthCheckGrpc;
|
||||||
import io.grpc.ManagedChannel;
|
import io.grpc.ManagedChannel;
|
||||||
|
@ -42,13 +41,13 @@ public class DaprRun implements Stoppable {
|
||||||
|
|
||||||
// the arg in -Dexec.args is the app's port
|
// the arg in -Dexec.args is the app's port
|
||||||
private static final String DAPR_COMMAND =
|
private static final String DAPR_COMMAND =
|
||||||
" -- mvn exec:java -D exec.mainClass=%s -D exec.classpathScope=test -D exec.args=\"%s\" -D %s=%s -D %s=%s";
|
" -- mvn exec:java -D exec.mainClass=%s -D exec.classpathScope=test -D exec.args=\"%s\"";
|
||||||
|
|
||||||
private final DaprPorts ports;
|
private final DaprPorts ports;
|
||||||
|
|
||||||
private final String appName;
|
private final String appName;
|
||||||
|
|
||||||
private final DaprApiProtocol appProtocol;
|
private final AppRun.AppProtocol appProtocol;
|
||||||
|
|
||||||
private final int maxWaitMilliseconds;
|
private final int maxWaitMilliseconds;
|
||||||
|
|
||||||
|
@ -67,15 +66,14 @@ public class DaprRun implements Stoppable {
|
||||||
String successMessage,
|
String successMessage,
|
||||||
Class serviceClass,
|
Class serviceClass,
|
||||||
int maxWaitMilliseconds,
|
int maxWaitMilliseconds,
|
||||||
DaprApiProtocol protocol,
|
AppRun.AppProtocol appProtocol) {
|
||||||
DaprApiProtocol appProtocol) {
|
|
||||||
// The app name needs to be deterministic since we depend on it to kill previous runs.
|
// The app name needs to be deterministic since we depend on it to kill previous runs.
|
||||||
this.appName = serviceClass == null ?
|
this.appName = serviceClass == null ?
|
||||||
testName.toLowerCase() :
|
testName.toLowerCase() :
|
||||||
String.format("%s-%s", testName, serviceClass.getSimpleName()).toLowerCase();
|
String.format("%s-%s", testName, serviceClass.getSimpleName()).toLowerCase();
|
||||||
this.appProtocol = appProtocol;
|
this.appProtocol = appProtocol;
|
||||||
this.startCommand =
|
this.startCommand =
|
||||||
new Command(successMessage, buildDaprCommand(this.appName, serviceClass, ports, protocol, appProtocol));
|
new Command(successMessage, buildDaprCommand(this.appName, serviceClass, ports, appProtocol));
|
||||||
this.listCommand = new Command(
|
this.listCommand = new Command(
|
||||||
this.appName,
|
this.appName,
|
||||||
"dapr list");
|
"dapr list");
|
||||||
|
@ -145,29 +143,6 @@ public class DaprRun implements Stoppable {
|
||||||
|
|
||||||
public void use() {
|
public void use() {
|
||||||
this.ports.use();
|
this.ports.use();
|
||||||
System.getProperties().setProperty(Properties.API_PROTOCOL.getName(), DaprApiProtocol.GRPC.name());
|
|
||||||
System.getProperties().setProperty(
|
|
||||||
Properties.API_METHOD_INVOCATION_PROTOCOL.getName(),
|
|
||||||
DaprApiProtocol.GRPC.name());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void switchToGRPC() {
|
|
||||||
System.getProperties().setProperty(Properties.API_PROTOCOL.getName(), DaprApiProtocol.GRPC.name());
|
|
||||||
System.getProperties().setProperty(
|
|
||||||
Properties.API_METHOD_INVOCATION_PROTOCOL.getName(),
|
|
||||||
DaprApiProtocol.GRPC.name());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void switchToHTTP() {
|
|
||||||
System.getProperties().setProperty(Properties.API_PROTOCOL.getName(), DaprApiProtocol.HTTP.name());
|
|
||||||
System.getProperties().setProperty(
|
|
||||||
Properties.API_METHOD_INVOCATION_PROTOCOL.getName(),
|
|
||||||
DaprApiProtocol.HTTP.name());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void switchToProtocol(DaprApiProtocol protocol) {
|
|
||||||
System.getProperties().setProperty(Properties.API_PROTOCOL.getName(), protocol.name());
|
|
||||||
System.getProperties().setProperty(Properties.API_METHOD_INVOCATION_PROTOCOL.getName(), protocol.name());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void waitForAppHealth(int maxWaitMilliseconds) throws InterruptedException {
|
public void waitForAppHealth(int maxWaitMilliseconds) throws InterruptedException {
|
||||||
|
@ -175,7 +150,7 @@ public class DaprRun implements Stoppable {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DaprApiProtocol.GRPC.equals(this.appProtocol)) {
|
if (AppRun.AppProtocol.GRPC.equals(this.appProtocol)) {
|
||||||
ManagedChannel channel = ManagedChannelBuilder.forAddress("127.0.0.1", this.getAppPort())
|
ManagedChannel channel = ManagedChannelBuilder.forAddress("127.0.0.1", this.getAppPort())
|
||||||
.usePlaintext()
|
.usePlaintext()
|
||||||
.build();
|
.build();
|
||||||
|
@ -263,7 +238,7 @@ public class DaprRun implements Stoppable {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String buildDaprCommand(
|
private static String buildDaprCommand(
|
||||||
String appName, Class serviceClass, DaprPorts ports, DaprApiProtocol protocol, DaprApiProtocol appProtocol) {
|
String appName, Class serviceClass, DaprPorts ports, AppRun.AppProtocol appProtocol) {
|
||||||
StringBuilder stringBuilder =
|
StringBuilder stringBuilder =
|
||||||
new StringBuilder(String.format(DAPR_RUN, appName, appProtocol.toString().toLowerCase()))
|
new StringBuilder(String.format(DAPR_RUN, appName, appProtocol.toString().toLowerCase()))
|
||||||
.append(ports.getAppPort() != null ? " --app-port " + ports.getAppPort() : "")
|
.append(ports.getAppPort() != null ? " --app-port " + ports.getAppPort() : "")
|
||||||
|
@ -273,9 +248,7 @@ public class DaprRun implements Stoppable {
|
||||||
" --enable-app-health-check --app-health-probe-interval=1" : "")
|
" --enable-app-health-check --app-health-probe-interval=1" : "")
|
||||||
.append(serviceClass == null ? "" :
|
.append(serviceClass == null ? "" :
|
||||||
String.format(DAPR_COMMAND, serviceClass.getCanonicalName(),
|
String.format(DAPR_COMMAND, serviceClass.getCanonicalName(),
|
||||||
ports.getAppPort() != null ? ports.getAppPort().toString() : "",
|
ports.getAppPort() != null ? ports.getAppPort().toString() : ""));
|
||||||
Properties.API_PROTOCOL.getName(), protocol,
|
|
||||||
Properties.API_METHOD_INVOCATION_PROTOCOL.getName(), protocol));
|
|
||||||
return stringBuilder.toString();
|
return stringBuilder.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -315,22 +288,18 @@ public class DaprRun implements Stoppable {
|
||||||
|
|
||||||
private Class serviceClass;
|
private Class serviceClass;
|
||||||
|
|
||||||
private DaprApiProtocol protocol;
|
private AppRun.AppProtocol appProtocol;
|
||||||
|
|
||||||
private DaprApiProtocol appProtocol;
|
|
||||||
|
|
||||||
Builder(
|
Builder(
|
||||||
String testName,
|
String testName,
|
||||||
Supplier<DaprPorts> portsSupplier,
|
Supplier<DaprPorts> portsSupplier,
|
||||||
String successMessage,
|
String successMessage,
|
||||||
int maxWaitMilliseconds,
|
int maxWaitMilliseconds,
|
||||||
DaprApiProtocol protocol,
|
AppRun.AppProtocol appProtocol) {
|
||||||
DaprApiProtocol appProtocol) {
|
|
||||||
this.testName = testName;
|
this.testName = testName;
|
||||||
this.portsSupplier = portsSupplier;
|
this.portsSupplier = portsSupplier;
|
||||||
this.successMessage = successMessage;
|
this.successMessage = successMessage;
|
||||||
this.maxWaitMilliseconds = maxWaitMilliseconds;
|
this.maxWaitMilliseconds = maxWaitMilliseconds;
|
||||||
this.protocol = protocol;
|
|
||||||
this.appProtocol = appProtocol;
|
this.appProtocol = appProtocol;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -346,7 +315,6 @@ public class DaprRun implements Stoppable {
|
||||||
this.successMessage,
|
this.successMessage,
|
||||||
this.serviceClass,
|
this.serviceClass,
|
||||||
this.maxWaitMilliseconds,
|
this.maxWaitMilliseconds,
|
||||||
this.protocol,
|
|
||||||
this.appProtocol);
|
this.appProtocol);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -360,8 +328,7 @@ public class DaprRun implements Stoppable {
|
||||||
ports,
|
ports,
|
||||||
this.successMessage,
|
this.successMessage,
|
||||||
this.serviceClass,
|
this.serviceClass,
|
||||||
this.maxWaitMilliseconds,
|
this.maxWaitMilliseconds);
|
||||||
this.protocol);
|
|
||||||
|
|
||||||
DaprRun daprRun = new DaprRun(
|
DaprRun daprRun = new DaprRun(
|
||||||
this.testName,
|
this.testName,
|
||||||
|
@ -369,7 +336,6 @@ public class DaprRun implements Stoppable {
|
||||||
DAPR_SUCCESS_MESSAGE,
|
DAPR_SUCCESS_MESSAGE,
|
||||||
null,
|
null,
|
||||||
this.maxWaitMilliseconds,
|
this.maxWaitMilliseconds,
|
||||||
this.protocol,
|
|
||||||
this.appProtocol);
|
this.appProtocol);
|
||||||
|
|
||||||
return new ImmutablePair<>(appRun, daprRun);
|
return new ImmutablePair<>(appRun, daprRun);
|
||||||
|
|
|
@ -22,22 +22,24 @@ import io.dapr.it.DaprRun;
|
||||||
import io.dapr.it.actors.app.ActorReminderDataParam;
|
import io.dapr.it.actors.app.ActorReminderDataParam;
|
||||||
import io.dapr.it.actors.app.MyActorService;
|
import io.dapr.it.actors.app.MyActorService;
|
||||||
import org.apache.commons.lang3.tuple.ImmutablePair;
|
import org.apache.commons.lang3.tuple.ImmutablePair;
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.jupiter.api.AfterEach;
|
import org.junit.jupiter.api.AfterEach;
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import org.junit.jupiter.params.ParameterizedTest;
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
import org.junit.jupiter.params.provider.Arguments;
|
import org.junit.jupiter.params.provider.Arguments;
|
||||||
import org.junit.jupiter.params.provider.MethodSource;
|
import org.junit.jupiter.params.provider.MethodSource;
|
||||||
import org.junit.runners.Parameterized;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.util.*;
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import static io.dapr.it.Retry.callWithRetry;
|
import static io.dapr.it.Retry.callWithRetry;
|
||||||
import static io.dapr.it.actors.MyActorTestUtils.*;
|
import static io.dapr.it.actors.MyActorTestUtils.countMethodCalls;
|
||||||
|
import static io.dapr.it.actors.MyActorTestUtils.fetchMethodCallLogs;
|
||||||
|
import static io.dapr.it.actors.MyActorTestUtils.validateMessageContent;
|
||||||
|
import static io.dapr.it.actors.MyActorTestUtils.validateMethodCalls;
|
||||||
|
|
||||||
public class ActorReminderRecoveryIT extends BaseIT {
|
public class ActorReminderRecoveryIT extends BaseIT {
|
||||||
|
|
||||||
|
|
|
@ -75,10 +75,6 @@ public class ActorSdkResiliencytIT extends BaseIT {
|
||||||
true,
|
true,
|
||||||
60000);
|
60000);
|
||||||
|
|
||||||
ActorId actorId = new ActorId(UUID.randomUUID().toString());
|
|
||||||
|
|
||||||
// HTTP client is deprecated, so SDK resiliency is for gRPC client only.
|
|
||||||
daprRun.switchToGRPC();
|
|
||||||
demoActor = buildDemoActorProxy(null);
|
demoActor = buildDemoActorProxy(null);
|
||||||
daprClient = new DaprClientBuilder().build();
|
daprClient = new DaprClientBuilder().build();
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ package io.dapr.it.actors;
|
||||||
import io.dapr.actors.ActorId;
|
import io.dapr.actors.ActorId;
|
||||||
import io.dapr.actors.client.ActorProxy;
|
import io.dapr.actors.client.ActorProxy;
|
||||||
import io.dapr.actors.client.ActorProxyBuilder;
|
import io.dapr.actors.client.ActorProxyBuilder;
|
||||||
import io.dapr.client.DaprApiProtocol;
|
import io.dapr.it.AppRun;
|
||||||
import io.dapr.it.BaseIT;
|
import io.dapr.it.BaseIT;
|
||||||
import io.dapr.it.DaprRun;
|
import io.dapr.it.DaprRun;
|
||||||
import io.dapr.it.actors.services.springboot.StatefulActor;
|
import io.dapr.it.actors.services.springboot.StatefulActor;
|
||||||
|
@ -45,16 +45,14 @@ public class ActorStateIT extends BaseIT {
|
||||||
*/
|
*/
|
||||||
public static Stream<Arguments> data() {
|
public static Stream<Arguments> data() {
|
||||||
return Stream.of(
|
return Stream.of(
|
||||||
Arguments.of(DaprApiProtocol.HTTP, DaprApiProtocol.HTTP ),
|
Arguments.of(AppRun.AppProtocol.HTTP ),
|
||||||
Arguments.of(DaprApiProtocol.HTTP, DaprApiProtocol.GRPC ),
|
Arguments.of(AppRun.AppProtocol.GRPC )
|
||||||
Arguments.of(DaprApiProtocol.GRPC, DaprApiProtocol.HTTP ),
|
|
||||||
Arguments.of(DaprApiProtocol.GRPC, DaprApiProtocol.GRPC )
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
@MethodSource("data")
|
@MethodSource("data")
|
||||||
public void writeReadState(DaprApiProtocol daprClientProtocol, DaprApiProtocol serviceAppProtocol) throws Exception {
|
public void writeReadState(AppRun.AppProtocol serviceAppProtocol) throws Exception {
|
||||||
logger.debug("Starting actor runtime ...");
|
logger.debug("Starting actor runtime ...");
|
||||||
// The call below will fail if service cannot start successfully.
|
// The call below will fail if service cannot start successfully.
|
||||||
DaprRun runtime = startDaprApp(
|
DaprRun runtime = startDaprApp(
|
||||||
|
@ -65,13 +63,11 @@ public class ActorStateIT extends BaseIT {
|
||||||
60000,
|
60000,
|
||||||
serviceAppProtocol);
|
serviceAppProtocol);
|
||||||
|
|
||||||
runtime.switchToProtocol(daprClientProtocol);
|
|
||||||
|
|
||||||
String message = "This is a message to be saved and retrieved.";
|
String message = "This is a message to be saved and retrieved.";
|
||||||
String name = "Jon Doe";
|
String name = "Jon Doe";
|
||||||
byte[] bytes = new byte[] { 0x1 };
|
byte[] bytes = new byte[] { 0x1 };
|
||||||
ActorId actorId = new ActorId(
|
ActorId actorId = new ActorId(
|
||||||
String.format("%d-%b-%b", System.currentTimeMillis(), daprClientProtocol, serviceAppProtocol));
|
String.format("%d-%b", System.currentTimeMillis(), serviceAppProtocol));
|
||||||
String actorType = "StatefulActorTest";
|
String actorType = "StatefulActorTest";
|
||||||
logger.debug("Building proxy ...");
|
logger.debug("Building proxy ...");
|
||||||
ActorProxyBuilder<ActorProxy> proxyBuilder =
|
ActorProxyBuilder<ActorProxy> proxyBuilder =
|
||||||
|
@ -161,8 +157,6 @@ public class ActorStateIT extends BaseIT {
|
||||||
60000,
|
60000,
|
||||||
serviceAppProtocol);
|
serviceAppProtocol);
|
||||||
|
|
||||||
runtime.switchToProtocol(daprClientProtocol);
|
|
||||||
|
|
||||||
// Need new proxy builder because the proxy builder holds the channel.
|
// Need new proxy builder because the proxy builder holds the channel.
|
||||||
proxyBuilder = new ActorProxyBuilder(actorType, ActorProxy.class, newActorClient());
|
proxyBuilder = new ActorProxyBuilder(actorType, ActorProxy.class, newActorClient());
|
||||||
ActorProxy newProxy = proxyBuilder.build(actorId);
|
ActorProxy newProxy = proxyBuilder.build(actorId);
|
||||||
|
|
|
@ -20,7 +20,9 @@ import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
import static org.junit.jupiter.api.Assertions.fail;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utility class for tests that use MyActor class.
|
* Utility class for tests that use MyActor class.
|
||||||
|
|
|
@ -24,7 +24,13 @@ import reactor.core.publisher.Mono;
|
||||||
import java.text.DateFormat;
|
import java.text.DateFormat;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.util.*;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Base64;
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.TimeZone;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
public abstract class MyActorBase<T> extends AbstractActor implements MyActor, Remindable<T> {
|
public abstract class MyActorBase<T> extends AbstractActor implements MyActor, Remindable<T> {
|
||||||
|
|
|
@ -4,34 +4,19 @@ import io.dapr.client.DaprClient;
|
||||||
import io.dapr.client.DaprClientBuilder;
|
import io.dapr.client.DaprClientBuilder;
|
||||||
import io.dapr.it.BaseIT;
|
import io.dapr.it.BaseIT;
|
||||||
import io.dapr.it.DaprRun;
|
import io.dapr.it.DaprRun;
|
||||||
import io.dapr.it.actors.ActorReminderRecoveryIT;
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.params.ParameterizedTest;
|
|
||||||
import org.junit.jupiter.params.provider.ValueSource;
|
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
import org.junit.runners.Parameterized;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collection;
|
|
||||||
|
|
||||||
public class ApiIT extends BaseIT {
|
public class ApiIT extends BaseIT {
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(ApiIT.class);
|
private static final Logger logger = LoggerFactory.getLogger(ApiIT.class);
|
||||||
private static final int DEFAULT_TIMEOUT = 60000;
|
private static final int DEFAULT_TIMEOUT = 60000;
|
||||||
|
|
||||||
@ParameterizedTest
|
@Test
|
||||||
@ValueSource(booleans = {true, false})
|
public void testShutdownAPI() throws Exception {
|
||||||
public void testShutdownAPI(boolean useGrpc) throws Exception {
|
|
||||||
DaprRun run = startDaprApp(this.getClass().getSimpleName(), DEFAULT_TIMEOUT);
|
DaprRun run = startDaprApp(this.getClass().getSimpleName(), DEFAULT_TIMEOUT);
|
||||||
|
|
||||||
if (useGrpc) {
|
|
||||||
run.switchToGRPC();
|
|
||||||
} else {
|
|
||||||
run.switchToHTTP();
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO(artursouza): change this to wait for the sidecar to be healthy (new method needed in DaprClient).
|
// TODO(artursouza): change this to wait for the sidecar to be healthy (new method needed in DaprClient).
|
||||||
Thread.sleep(3000);
|
Thread.sleep(3000);
|
||||||
try (DaprClient client = new DaprClientBuilder().build()) {
|
try (DaprClient client = new DaprClientBuilder().build()) {
|
||||||
|
|
|
@ -20,8 +20,6 @@ import io.dapr.client.domain.HttpExtension;
|
||||||
import io.dapr.it.BaseIT;
|
import io.dapr.it.BaseIT;
|
||||||
import io.dapr.it.DaprRun;
|
import io.dapr.it.DaprRun;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.params.ParameterizedTest;
|
|
||||||
import org.junit.jupiter.params.provider.ValueSource;
|
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -46,24 +44,14 @@ public class BindingIT extends BaseIT {
|
||||||
public String message;
|
public String message;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ParameterizedTest
|
@Test
|
||||||
@ValueSource(booleans = {true, false})
|
public void inputOutputBinding() throws Exception {
|
||||||
public void inputOutputBinding(boolean useGrpc) throws Exception {
|
|
||||||
System.out.println("Working Directory = " + System.getProperty("user.dir"));
|
|
||||||
String serviceNameVariant = useGrpc ? "-grpc" : "-http";
|
|
||||||
|
|
||||||
DaprRun daprRun = startDaprApp(
|
DaprRun daprRun = startDaprApp(
|
||||||
this.getClass().getSimpleName() + serviceNameVariant,
|
this.getClass().getSimpleName() + "-grpc",
|
||||||
InputBindingService.SUCCESS_MESSAGE,
|
InputBindingService.SUCCESS_MESSAGE,
|
||||||
InputBindingService.class,
|
InputBindingService.class,
|
||||||
true,
|
true,
|
||||||
60000);
|
60000);
|
||||||
// At this point, it is guaranteed that the service above is running and all ports being listened to.
|
|
||||||
if (useGrpc) {
|
|
||||||
daprRun.switchToGRPC();
|
|
||||||
} else {
|
|
||||||
daprRun.switchToHTTP();
|
|
||||||
}
|
|
||||||
|
|
||||||
try(DaprClient client = new DaprClientBuilder().build()) {
|
try(DaprClient client = new DaprClientBuilder().build()) {
|
||||||
callWithRetry(() -> {
|
callWithRetry(() -> {
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.dapr.it.configuration.grpc;
|
package io.dapr.it.configuration;
|
||||||
|
|
||||||
import io.dapr.client.DaprClient;
|
import io.dapr.client.DaprClient;
|
||||||
import io.dapr.client.DaprClientBuilder;
|
import io.dapr.client.DaprClientBuilder;
|
||||||
|
@ -20,7 +20,6 @@ import io.dapr.client.domain.SubscribeConfigurationResponse;
|
||||||
import io.dapr.client.domain.UnsubscribeConfigurationResponse;
|
import io.dapr.client.domain.UnsubscribeConfigurationResponse;
|
||||||
import io.dapr.it.BaseIT;
|
import io.dapr.it.BaseIT;
|
||||||
import io.dapr.it.DaprRun;
|
import io.dapr.it.DaprRun;
|
||||||
|
|
||||||
import org.junit.jupiter.api.AfterAll;
|
import org.junit.jupiter.api.AfterAll;
|
||||||
import org.junit.jupiter.api.BeforeAll;
|
import org.junit.jupiter.api.BeforeAll;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
@ -29,10 +28,14 @@ import reactor.core.Disposable;
|
||||||
import reactor.core.publisher.Flux;
|
import reactor.core.publisher.Flux;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.*;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
public class ConfigurationClientIT extends BaseIT {
|
public class ConfigurationClientIT extends BaseIT {
|
||||||
|
|
||||||
|
@ -65,7 +68,6 @@ public class ConfigurationClientIT extends BaseIT {
|
||||||
@BeforeAll
|
@BeforeAll
|
||||||
public static void init() throws Exception {
|
public static void init() throws Exception {
|
||||||
daprRun = startDaprApp(ConfigurationClientIT.class.getSimpleName(), 5000);
|
daprRun = startDaprApp(ConfigurationClientIT.class.getSimpleName(), 5000);
|
||||||
daprRun.switchToGRPC();
|
|
||||||
daprClient = new DaprClientBuilder().build();
|
daprClient = new DaprClientBuilder().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -198,6 +200,9 @@ public class ConfigurationClientIT extends BaseIT {
|
||||||
try {
|
try {
|
||||||
process = processBuilder.start();
|
process = processBuilder.start();
|
||||||
process.waitFor();
|
process.waitFor();
|
||||||
|
if (process.exitValue() != 0) {
|
||||||
|
throw new RuntimeException("Not zero exit code for Redis command: " + process.exitValue());
|
||||||
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
|
@ -1,65 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2022 The Dapr 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.dapr.it.configuration.http;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
import io.dapr.client.domain.ConfigurationItem;
|
|
||||||
import io.dapr.client.domain.SubscribeConfigurationResponse;
|
|
||||||
import org.springframework.http.MediaType;
|
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
|
||||||
import org.springframework.web.bind.annotation.PathVariable;
|
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestBody;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
import reactor.core.publisher.Mono;
|
|
||||||
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Spring boot Controller class for api endpoints.
|
|
||||||
*/
|
|
||||||
@RestController
|
|
||||||
public class ConfigSubscriberController {
|
|
||||||
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Api mapping for subscribe configuration.
|
|
||||||
* @param pathVarsMap Path variables for post call
|
|
||||||
* @param obj request Body
|
|
||||||
* @return Returns void
|
|
||||||
*/
|
|
||||||
@PostMapping(path = "/configuration/{configStore}/{key}", produces = MediaType.APPLICATION_JSON_VALUE)
|
|
||||||
public Mono<Void> handleMessage(
|
|
||||||
@PathVariable Map<String, String> pathVarsMap,
|
|
||||||
@RequestBody SubscribeConfigurationResponse obj) {
|
|
||||||
return Mono.fromRunnable(
|
|
||||||
() -> {
|
|
||||||
try {
|
|
||||||
Map<String, ConfigurationItem> items = obj.getItems();
|
|
||||||
for (Map.Entry<String, ConfigurationItem> entry : items.entrySet()) {
|
|
||||||
System.out.println(entry.getValue().getValue() + " : key ->" + entry.getKey());
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping(path = "/health")
|
|
||||||
public void health() {
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,83 +0,0 @@
|
||||||
package io.dapr.it.configuration.http;
|
|
||||||
|
|
||||||
import io.dapr.client.DaprClient;
|
|
||||||
import io.dapr.client.DaprClientBuilder;
|
|
||||||
import io.dapr.client.domain.ConfigurationItem;
|
|
||||||
import io.dapr.it.BaseIT;
|
|
||||||
import io.dapr.it.DaprRun;
|
|
||||||
|
|
||||||
import org.junit.jupiter.api.AfterAll;
|
|
||||||
import org.junit.jupiter.api.BeforeAll;
|
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
|
||||||
|
|
||||||
public class ConfigurationIT extends BaseIT {
|
|
||||||
private static final String CONFIG_STORE_NAME = "redisconfigstore";
|
|
||||||
|
|
||||||
private static DaprRun daprRun;
|
|
||||||
|
|
||||||
private static DaprClient daprClient;
|
|
||||||
|
|
||||||
private static String key = "myconfig1";
|
|
||||||
|
|
||||||
private static List<String> keys = new ArrayList<>(Arrays.asList("myconfig1", "myconfig2", "myconfig3"));
|
|
||||||
|
|
||||||
private static String[] insertCmd = new String[] {
|
|
||||||
"docker", "exec", "dapr_redis", "redis-cli",
|
|
||||||
"MSET",
|
|
||||||
"myconfigkey1", "myconfigvalue1||1",
|
|
||||||
"myconfigkey2", "myconfigvalue2||1",
|
|
||||||
"myconfigkey3", "myconfigvalue3||1"
|
|
||||||
};
|
|
||||||
|
|
||||||
@BeforeAll
|
|
||||||
public static void init() throws Exception {
|
|
||||||
daprRun = startDaprApp(ConfigurationIT.class.getSimpleName(), 5000);
|
|
||||||
daprRun.switchToHTTP();
|
|
||||||
daprClient = new DaprClientBuilder().build();
|
|
||||||
}
|
|
||||||
|
|
||||||
@AfterAll
|
|
||||||
public static void tearDown() throws Exception {
|
|
||||||
daprClient.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
@BeforeEach
|
|
||||||
public void setupConfigStore() {
|
|
||||||
executeDockerCommand(insertCmd);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void getConfiguration() {
|
|
||||||
ConfigurationItem ci = daprClient.getConfiguration(CONFIG_STORE_NAME, "myconfigkey1").block();
|
|
||||||
assertEquals(ci.getKey(), "myconfigkey1");
|
|
||||||
assertEquals(ci.getValue(), "myconfigvalue1");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void getConfigurations() {
|
|
||||||
Map<String, ConfigurationItem> cis = daprClient.getConfiguration(CONFIG_STORE_NAME, "myconfigkey1", "myconfigkey2").block();
|
|
||||||
assertTrue(cis.size() == 2);
|
|
||||||
assertTrue(cis.containsKey("myconfigkey1"));
|
|
||||||
assertTrue(cis.containsKey("myconfigkey2"));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void executeDockerCommand(String[] command) {
|
|
||||||
ProcessBuilder processBuilder = new ProcessBuilder(command);
|
|
||||||
Process process = null;
|
|
||||||
try {
|
|
||||||
process = processBuilder.start();
|
|
||||||
process.waitFor();
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,91 +0,0 @@
|
||||||
package io.dapr.it.configuration.http;
|
|
||||||
|
|
||||||
import io.dapr.client.DaprClient;
|
|
||||||
import io.dapr.client.DaprClientBuilder;
|
|
||||||
import io.dapr.client.domain.SubscribeConfigurationResponse;
|
|
||||||
import io.dapr.client.domain.UnsubscribeConfigurationResponse;
|
|
||||||
import io.dapr.it.BaseIT;
|
|
||||||
import io.dapr.it.DaprRun;
|
|
||||||
import org.junit.jupiter.api.AfterAll;
|
|
||||||
import org.junit.jupiter.api.BeforeAll;
|
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import reactor.core.publisher.Flux;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
|
||||||
|
|
||||||
public class ConfigurationSubscribeIT extends BaseIT {
|
|
||||||
private static final String CONFIG_STORE_NAME = "redisconfigstore";
|
|
||||||
|
|
||||||
private static DaprRun daprRun;
|
|
||||||
|
|
||||||
private static DaprClient daprClient;
|
|
||||||
|
|
||||||
private static String key = "myconfig1";
|
|
||||||
|
|
||||||
private static List<String> keys = new ArrayList<>(Arrays.asList("myconfig1", "myconfig2", "myconfig3"));
|
|
||||||
|
|
||||||
private static String[] insertCmd = new String[] {
|
|
||||||
"docker", "exec", "dapr_redis", "redis-cli",
|
|
||||||
"MSET",
|
|
||||||
"myconfigkey1", "myconfigvalue1||1",
|
|
||||||
"myconfigkey2", "myconfigvalue2||1",
|
|
||||||
"myconfigkey3", "myconfigvalue3||1"
|
|
||||||
};
|
|
||||||
|
|
||||||
@BeforeAll
|
|
||||||
public static void init() throws Exception {
|
|
||||||
daprRun = startDaprApp(
|
|
||||||
ConfigurationIT.class.getSimpleName(),
|
|
||||||
ConfigurationSubscriberService.SUCCESS_MESSAGE,
|
|
||||||
ConfigurationSubscriberService.class,
|
|
||||||
true,
|
|
||||||
60000);
|
|
||||||
daprRun.switchToHTTP();
|
|
||||||
daprClient = new DaprClientBuilder().build();
|
|
||||||
}
|
|
||||||
|
|
||||||
@AfterAll
|
|
||||||
public static void tearDown() throws Exception {
|
|
||||||
daprClient.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
@BeforeEach
|
|
||||||
public void setupConfigStore() {
|
|
||||||
executeDockerCommand(insertCmd);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void subscribeAndUnsubscribeConfiguration() {
|
|
||||||
AtomicReference<String> subId= new AtomicReference<>("");
|
|
||||||
Flux<SubscribeConfigurationResponse> outFlux = daprClient
|
|
||||||
.subscribeConfiguration(CONFIG_STORE_NAME, "myconfigkey1", "myconfigkey2");
|
|
||||||
outFlux.subscribe(items -> {
|
|
||||||
subId.set(items.getSubscriptionId());
|
|
||||||
});
|
|
||||||
assertTrue(subId.get().length() > 0);
|
|
||||||
|
|
||||||
UnsubscribeConfigurationResponse res = daprClient.unsubscribeConfiguration(
|
|
||||||
subId.get(),
|
|
||||||
CONFIG_STORE_NAME
|
|
||||||
).block();
|
|
||||||
assertTrue(res.getIsUnsubscribed());
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void executeDockerCommand(String[] command) {
|
|
||||||
ProcessBuilder processBuilder = new ProcessBuilder(command);
|
|
||||||
Process process = null;
|
|
||||||
try {
|
|
||||||
process = processBuilder.start();
|
|
||||||
process.waitFor();
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,52 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2022 The Dapr 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.dapr.it.configuration.http;
|
|
||||||
|
|
||||||
import org.springframework.boot.SpringApplication;
|
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Service for ConfigurationSubscriber.
|
|
||||||
* dapr run --components-path ./components/configuration --app-id configsubscriber --app-port 3000 -- \
|
|
||||||
* java -jar target/dapr-java-sdk-examples-exec.jar io.dapr.examples.configuration.http.ConfigurationSubscriber -p 3000
|
|
||||||
*/
|
|
||||||
@SpringBootApplication
|
|
||||||
public class ConfigurationSubscriberService {
|
|
||||||
|
|
||||||
public static final String SUCCESS_MESSAGE = "dapr initialized. Status: Running";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is entry point for Configuration Subscriber service.
|
|
||||||
* @param args Arguments for main
|
|
||||||
* @throws Exception Throws Exception
|
|
||||||
*/
|
|
||||||
public static void main(String[] args) throws Exception {
|
|
||||||
int port = Integer.parseInt(args[0]);
|
|
||||||
|
|
||||||
System.out.printf("Service starting on port %d ...\n", port);
|
|
||||||
|
|
||||||
// Start Dapr's callback endpoint.
|
|
||||||
start(port);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Starts Dapr's callback in a given port.
|
|
||||||
*
|
|
||||||
* @param port Port to listen to.
|
|
||||||
*/
|
|
||||||
private static void start(int port) {
|
|
||||||
SpringApplication app = new SpringApplication(ConfigurationSubscriberService.class);
|
|
||||||
app.run(String.format("--server.port=%d", port));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,12 +1,14 @@
|
||||||
package io.dapr.it.methodinvoke.grpc;
|
package io.dapr.it.methodinvoke.grpc;
|
||||||
|
|
||||||
import io.dapr.client.DaprApiProtocol;
|
|
||||||
import io.dapr.client.DaprClient;
|
import io.dapr.client.DaprClient;
|
||||||
import io.dapr.client.DaprClientBuilder;
|
import io.dapr.client.DaprClientBuilder;
|
||||||
import io.dapr.client.domain.HttpExtension;
|
import io.dapr.client.resiliency.ResiliencyOptions;
|
||||||
import io.dapr.exceptions.DaprException;
|
import io.dapr.it.AppRun;
|
||||||
import io.dapr.it.BaseIT;
|
import io.dapr.it.BaseIT;
|
||||||
import io.dapr.it.DaprRun;
|
import io.dapr.it.DaprRun;
|
||||||
|
import io.dapr.it.MethodInvokeServiceGrpc;
|
||||||
|
import io.grpc.Status;
|
||||||
|
import io.grpc.StatusRuntimeException;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
@ -15,7 +17,6 @@ import java.util.Map;
|
||||||
|
|
||||||
import static io.dapr.it.MethodInvokeServiceProtos.DeleteMessageRequest;
|
import static io.dapr.it.MethodInvokeServiceProtos.DeleteMessageRequest;
|
||||||
import static io.dapr.it.MethodInvokeServiceProtos.GetMessagesRequest;
|
import static io.dapr.it.MethodInvokeServiceProtos.GetMessagesRequest;
|
||||||
import static io.dapr.it.MethodInvokeServiceProtos.GetMessagesResponse;
|
|
||||||
import static io.dapr.it.MethodInvokeServiceProtos.PostMessageRequest;
|
import static io.dapr.it.MethodInvokeServiceProtos.PostMessageRequest;
|
||||||
import static io.dapr.it.MethodInvokeServiceProtos.SleepRequest;
|
import static io.dapr.it.MethodInvokeServiceProtos.SleepRequest;
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
@ -38,15 +39,17 @@ public class MethodInvokeIT extends BaseIT {
|
||||||
MethodInvokeIT.class.getSimpleName() + "grpc",
|
MethodInvokeIT.class.getSimpleName() + "grpc",
|
||||||
MethodInvokeService.SUCCESS_MESSAGE,
|
MethodInvokeService.SUCCESS_MESSAGE,
|
||||||
MethodInvokeService.class,
|
MethodInvokeService.class,
|
||||||
DaprApiProtocol.GRPC, // appProtocol
|
AppRun.AppProtocol.GRPC, // appProtocol
|
||||||
60000);
|
60000);
|
||||||
daprRun.switchToGRPC();
|
|
||||||
daprRun.waitForAppHealth(40000);
|
daprRun.waitForAppHealth(40000);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testInvoke() throws Exception {
|
public void testInvoke() throws Exception {
|
||||||
try (DaprClient client = new DaprClientBuilder().build()) {
|
try (DaprClient client = new DaprClientBuilder().build()) {
|
||||||
|
MethodInvokeServiceGrpc.MethodInvokeServiceBlockingStub stub = client.newGrpcStub(
|
||||||
|
daprRun.getAppName(),
|
||||||
|
channel -> MethodInvokeServiceGrpc.newBlockingStub(channel));
|
||||||
client.waitForSidecar(10000).block();
|
client.waitForSidecar(10000).block();
|
||||||
daprRun.waitForAppHealth(10000);
|
daprRun.waitForAppHealth(10000);
|
||||||
|
|
||||||
|
@ -54,59 +57,43 @@ public class MethodInvokeIT extends BaseIT {
|
||||||
String message = String.format("This is message #%d", i);
|
String message = String.format("This is message #%d", i);
|
||||||
|
|
||||||
PostMessageRequest req = PostMessageRequest.newBuilder().setId(i).setMessage(message).build();
|
PostMessageRequest req = PostMessageRequest.newBuilder().setId(i).setMessage(message).build();
|
||||||
client.invokeMethod(daprRun.getAppName(), "postMessage", req, HttpExtension.POST).block();
|
stub.postMessage(req);
|
||||||
|
|
||||||
System.out.println("Invoke method messages : " + message);
|
System.out.println("Invoke method messages : " + message);
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<Integer, String> messages = client.invokeMethod(
|
Map<Integer, String> messages = stub.getMessages(GetMessagesRequest.newBuilder().build()).getMessagesMap();
|
||||||
daprRun.getAppName(),
|
|
||||||
"getMessages",
|
|
||||||
GetMessagesRequest.newBuilder().build(),
|
|
||||||
HttpExtension.POST, GetMessagesResponse.class).block().getMessagesMap();
|
|
||||||
assertEquals(10, messages.size());
|
assertEquals(10, messages.size());
|
||||||
|
|
||||||
// Delete one message.
|
// Delete one message.
|
||||||
client.invokeMethod(
|
stub.deleteMessage(DeleteMessageRequest.newBuilder().setId(1).build());
|
||||||
daprRun.getAppName(),
|
messages = stub.getMessages(GetMessagesRequest.newBuilder().build()).getMessagesMap();
|
||||||
"deleteMessage",
|
|
||||||
DeleteMessageRequest.newBuilder().setId(1).build(),
|
|
||||||
HttpExtension.POST).block();
|
|
||||||
messages = client.invokeMethod(
|
|
||||||
daprRun.getAppName(),
|
|
||||||
"getMessages",
|
|
||||||
GetMessagesRequest.newBuilder().build(),
|
|
||||||
HttpExtension.POST, GetMessagesResponse.class).block().getMessagesMap();
|
|
||||||
assertEquals(9, messages.size());
|
assertEquals(9, messages.size());
|
||||||
|
|
||||||
// Now update one message.
|
// Now update one message.
|
||||||
client.invokeMethod(
|
stub.postMessage(PostMessageRequest.newBuilder().setId(2).setMessage("updated message").build());
|
||||||
daprRun.getAppName(),
|
messages = stub.getMessages(GetMessagesRequest.newBuilder().build()).getMessagesMap();
|
||||||
"postMessage",
|
|
||||||
PostMessageRequest.newBuilder().setId(2).setMessage("updated message").build(),
|
|
||||||
HttpExtension.POST).block();
|
|
||||||
messages = client.invokeMethod(
|
|
||||||
daprRun.getAppName(),
|
|
||||||
"getMessages",
|
|
||||||
GetMessagesRequest.newBuilder().build(),
|
|
||||||
HttpExtension.POST, GetMessagesResponse.class).block().getMessagesMap();
|
|
||||||
assertEquals("updated message", messages.get(2));
|
assertEquals("updated message", messages.get(2));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testInvokeTimeout() throws Exception {
|
public void testInvokeTimeout() throws Exception {
|
||||||
try (DaprClient client = new DaprClientBuilder().build()) {
|
long timeoutMs = 100;
|
||||||
|
ResiliencyOptions resiliencyOptions = new ResiliencyOptions().setTimeout(Duration.ofMillis(timeoutMs));
|
||||||
|
try (DaprClient client = new DaprClientBuilder().withResiliencyOptions(resiliencyOptions).build()) {
|
||||||
|
MethodInvokeServiceGrpc.MethodInvokeServiceBlockingStub stub = client.newGrpcStub(
|
||||||
|
daprRun.getAppName(),
|
||||||
|
channel -> MethodInvokeServiceGrpc.newBlockingStub(channel));
|
||||||
client.waitForSidecar(10000).block();
|
client.waitForSidecar(10000).block();
|
||||||
daprRun.waitForAppHealth(10000);
|
daprRun.waitForAppHealth(10000);
|
||||||
|
|
||||||
long started = System.currentTimeMillis();
|
long started = System.currentTimeMillis();
|
||||||
SleepRequest req = SleepRequest.newBuilder().setSeconds(1).build();
|
SleepRequest req = SleepRequest.newBuilder().setSeconds(1).build();
|
||||||
String message = assertThrows(IllegalStateException.class, () ->
|
String message = assertThrows(StatusRuntimeException.class, () -> stub.sleep(req)).getMessage();
|
||||||
client.invokeMethod(daprRun.getAppName(), "sleep", req.toByteArray(), HttpExtension.POST)
|
|
||||||
.block(Duration.ofMillis(10))).getMessage();
|
|
||||||
long delay = System.currentTimeMillis() - started;
|
long delay = System.currentTimeMillis() - started;
|
||||||
assertTrue(delay <= 500); // 500 ms is a reasonable delay if the request timed out.
|
assertTrue(delay >= timeoutMs);
|
||||||
assertEquals("Timeout on blocking read for 10000000 NANOSECONDS", message);
|
assertTrue(message.startsWith("DEADLINE_EXCEEDED: deadline exceeded after"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,17 +102,20 @@ public class MethodInvokeIT extends BaseIT {
|
||||||
try (DaprClient client = new DaprClientBuilder().build()) {
|
try (DaprClient client = new DaprClientBuilder().build()) {
|
||||||
client.waitForSidecar(10000).block();
|
client.waitForSidecar(10000).block();
|
||||||
daprRun.waitForAppHealth(10000);
|
daprRun.waitForAppHealth(10000);
|
||||||
|
|
||||||
|
MethodInvokeServiceGrpc.MethodInvokeServiceBlockingStub stub = client.newGrpcStub(
|
||||||
|
daprRun.getAppName(),
|
||||||
|
channel -> MethodInvokeServiceGrpc.newBlockingStub(channel));
|
||||||
|
|
||||||
SleepRequest req = SleepRequest.newBuilder().setSeconds(-9).build();
|
SleepRequest req = SleepRequest.newBuilder().setSeconds(-9).build();
|
||||||
DaprException exception = assertThrows(DaprException.class, () ->
|
StatusRuntimeException exception = assertThrows(StatusRuntimeException.class, () -> stub.sleep(req));
|
||||||
client.invokeMethod(daprRun.getAppName(), "sleep", req.toByteArray(), HttpExtension.POST).block());
|
|
||||||
|
|
||||||
// The error messages should be improved once runtime has standardized error serialization in the API.
|
// The error messages should be improved once runtime has standardized error serialization in the API.
|
||||||
// This message is not ideal but last time it was improved, there was side effects reported by users.
|
// This message is not ideal but last time it was improved, there was side effects reported by users.
|
||||||
// If this test fails, there might be a regression in runtime (like we had in 1.10.0).
|
// If this test fails, there might be a regression in runtime (like we had in 1.10.0).
|
||||||
// The expectations below are as per 1.9 release and (later on) hotfixed in 1.10.
|
// The expectations below are as per 1.9 release and (later on) hotfixed in 1.10.
|
||||||
assertEquals("UNKNOWN", exception.getErrorCode());
|
assertEquals(Status.UNKNOWN.getCode(), exception.getStatus().getCode());
|
||||||
assertEquals("UNKNOWN: ", exception.getMessage());
|
assertEquals("", exception.getStatus().getDescription());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,26 +13,18 @@ limitations under the License.
|
||||||
|
|
||||||
package io.dapr.it.methodinvoke.grpc;
|
package io.dapr.it.methodinvoke.grpc;
|
||||||
|
|
||||||
import com.google.protobuf.Any;
|
|
||||||
import io.dapr.grpc.GrpcHealthCheckService;
|
import io.dapr.grpc.GrpcHealthCheckService;
|
||||||
import io.dapr.it.DaprRunConfig;
|
import io.dapr.it.DaprRunConfig;
|
||||||
import io.dapr.v1.AppCallbackGrpc;
|
import io.dapr.it.MethodInvokeServiceGrpc;
|
||||||
import io.dapr.v1.CommonProtos;
|
|
||||||
import io.grpc.Server;
|
import io.grpc.Server;
|
||||||
import io.grpc.ServerBuilder;
|
import io.grpc.ServerBuilder;
|
||||||
import io.grpc.stub.StreamObserver;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import static io.dapr.it.MethodInvokeServiceProtos.DeleteMessageRequest;
|
|
||||||
import static io.dapr.it.MethodInvokeServiceProtos.DeleteMessageResponse;
|
|
||||||
import static io.dapr.it.MethodInvokeServiceProtos.GetMessagesRequest;
|
|
||||||
import static io.dapr.it.MethodInvokeServiceProtos.GetMessagesResponse;
|
import static io.dapr.it.MethodInvokeServiceProtos.GetMessagesResponse;
|
||||||
import static io.dapr.it.MethodInvokeServiceProtos.PostMessageRequest;
|
|
||||||
import static io.dapr.it.MethodInvokeServiceProtos.PostMessageResponse;
|
|
||||||
import static io.dapr.it.MethodInvokeServiceProtos.SleepRequest;
|
import static io.dapr.it.MethodInvokeServiceProtos.SleepRequest;
|
||||||
import static io.dapr.it.MethodInvokeServiceProtos.SleepResponse;
|
import static io.dapr.it.MethodInvokeServiceProtos.SleepResponse;
|
||||||
|
|
||||||
|
@ -48,7 +40,7 @@ public class MethodInvokeService {
|
||||||
/**
|
/**
|
||||||
* Server mode: class that encapsulates all server-side logic for Grpc.
|
* Server mode: class that encapsulates all server-side logic for Grpc.
|
||||||
*/
|
*/
|
||||||
private static class MyDaprService extends AppCallbackGrpc.AppCallbackImplBase {
|
private static class MyDaprService extends MethodInvokeServiceGrpc.MethodInvokeServiceImplBase {
|
||||||
|
|
||||||
private final Map<Integer, String> messages = Collections.synchronizedMap(new HashMap<>());
|
private final Map<Integer, String> messages = Collections.synchronizedMap(new HashMap<>());
|
||||||
|
|
||||||
|
@ -92,57 +84,55 @@ public class MethodInvokeService {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Server mode: this is the Dapr method to receive Invoke operations via Grpc.
|
* {@inheritDoc}
|
||||||
*
|
|
||||||
* @param request Dapr envelope request,
|
|
||||||
* @param responseObserver Dapr envelope response.
|
|
||||||
*/
|
*/
|
||||||
@Override
|
public void postMessage(io.dapr.it.MethodInvokeServiceProtos.PostMessageRequest request,
|
||||||
public void onInvoke(CommonProtos.InvokeRequest request,
|
io.grpc.stub.StreamObserver<io.dapr.it.MethodInvokeServiceProtos.PostMessageResponse> responseObserver) {
|
||||||
StreamObserver<CommonProtos.InvokeResponse> responseObserver) {
|
this.messages.put(request.getId(), request.getMessage());
|
||||||
System.out.println("Server: received " + request.getMethod() + " ...");
|
|
||||||
try {
|
|
||||||
if ("postMessage".equals(request.getMethod())) {
|
|
||||||
PostMessageRequest req = PostMessageRequest.parseFrom(request.getData().getValue().toByteArray());
|
|
||||||
|
|
||||||
this.messages.put(req.getId(), req.getMessage());
|
io.dapr.it.MethodInvokeServiceProtos.PostMessageResponse.Builder responseBuilder =
|
||||||
|
io.dapr.it.MethodInvokeServiceProtos.PostMessageResponse.newBuilder();
|
||||||
|
responseObserver.onNext(responseBuilder.build());
|
||||||
|
responseObserver.onCompleted();
|
||||||
|
}
|
||||||
|
|
||||||
CommonProtos.InvokeResponse.Builder responseBuilder = CommonProtos.InvokeResponse.newBuilder();
|
/**
|
||||||
responseBuilder.setData(Any.pack(PostMessageResponse.newBuilder().build()));
|
* {@inheritDoc}
|
||||||
responseObserver.onNext(responseBuilder.build());
|
*/
|
||||||
}
|
public void deleteMessage(io.dapr.it.MethodInvokeServiceProtos.DeleteMessageRequest request,
|
||||||
if ("deleteMessage".equals(request.getMethod())) {
|
io.grpc.stub.StreamObserver<io.dapr.it.MethodInvokeServiceProtos.DeleteMessageResponse> responseObserver) {
|
||||||
DeleteMessageRequest req = DeleteMessageRequest.parseFrom(request.getData().getValue().toByteArray());
|
this.messages.remove(request.getId());
|
||||||
|
|
||||||
this.messages.remove(req.getId());
|
io.dapr.it.MethodInvokeServiceProtos.DeleteMessageResponse.Builder responseBuilder =
|
||||||
|
io.dapr.it.MethodInvokeServiceProtos.DeleteMessageResponse.newBuilder();
|
||||||
|
responseObserver.onNext(responseBuilder.build());
|
||||||
|
responseObserver.onCompleted();
|
||||||
|
}
|
||||||
|
|
||||||
CommonProtos.InvokeResponse.Builder responseBuilder = CommonProtos.InvokeResponse.newBuilder();
|
/**
|
||||||
responseBuilder.setData(Any.pack(DeleteMessageResponse.newBuilder().build()));
|
* {@inheritDoc}
|
||||||
responseObserver.onNext(responseBuilder.build());
|
*/
|
||||||
}
|
public void getMessages(io.dapr.it.MethodInvokeServiceProtos.GetMessagesRequest request,
|
||||||
if ("getMessages".equals(request.getMethod())) {
|
io.grpc.stub.StreamObserver<io.dapr.it.MethodInvokeServiceProtos.GetMessagesResponse> responseObserver) {
|
||||||
GetMessagesRequest.parseFrom(request.getData().getValue().toByteArray());
|
GetMessagesResponse res = GetMessagesResponse.newBuilder().putAllMessages(this.messages).build();
|
||||||
|
|
||||||
GetMessagesResponse res = GetMessagesResponse.newBuilder().putAllMessages(this.messages).build();
|
io.dapr.it.MethodInvokeServiceProtos.GetMessagesResponse.Builder responseBuilder
|
||||||
|
= io.dapr.it.MethodInvokeServiceProtos.GetMessagesResponse.newBuilder();
|
||||||
|
responseObserver.onNext(res);
|
||||||
|
responseObserver.onCompleted();
|
||||||
|
}
|
||||||
|
|
||||||
CommonProtos.InvokeResponse.Builder responseBuilder = CommonProtos.InvokeResponse.newBuilder();
|
/**
|
||||||
responseBuilder.setData(Any.pack(res));
|
* {@inheritDoc}
|
||||||
responseObserver.onNext(responseBuilder.build());
|
*/
|
||||||
}
|
public void sleep(io.dapr.it.MethodInvokeServiceProtos.SleepRequest request,
|
||||||
if ("sleep".equals(request.getMethod())) {
|
io.grpc.stub.StreamObserver<io.dapr.it.MethodInvokeServiceProtos.SleepResponse> responseObserver) {
|
||||||
SleepRequest req = SleepRequest.parseFrom(request.getData().getValue().toByteArray());
|
SleepResponse res = this.sleep(request);
|
||||||
|
|
||||||
SleepResponse res = this.sleep(req);
|
io.dapr.it.MethodInvokeServiceProtos.SleepResponse.Builder responseBuilder =
|
||||||
|
io.dapr.it.MethodInvokeServiceProtos.SleepResponse.newBuilder();
|
||||||
CommonProtos.InvokeResponse.Builder responseBuilder = CommonProtos.InvokeResponse.newBuilder();
|
responseObserver.onNext(responseBuilder.build());
|
||||||
responseBuilder.setData(Any.pack(res));
|
responseObserver.onCompleted();
|
||||||
responseObserver.onNext(responseBuilder.build());
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
responseObserver.onError(e);
|
|
||||||
} finally {
|
|
||||||
responseObserver.onCompleted();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public SleepResponse sleep(SleepRequest request) {
|
public SleepResponse sleep(SleepRequest request) {
|
||||||
|
|
|
@ -40,7 +40,6 @@ public class MethodInvokeIT extends BaseIT {
|
||||||
MethodInvokeService.class,
|
MethodInvokeService.class,
|
||||||
true,
|
true,
|
||||||
30000);
|
30000);
|
||||||
daprRun.switchToHTTP();
|
|
||||||
daprRun.waitForAppHealth(20000);
|
daprRun.waitForAppHealth(20000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,8 +34,7 @@ import io.dapr.serializer.DaprObjectSerializer;
|
||||||
import io.dapr.utils.TypeRef;
|
import io.dapr.utils.TypeRef;
|
||||||
import org.junit.jupiter.api.AfterEach;
|
import org.junit.jupiter.api.AfterEach;
|
||||||
import org.junit.jupiter.api.Assertions;
|
import org.junit.jupiter.api.Assertions;
|
||||||
import org.junit.jupiter.params.ParameterizedTest;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.params.provider.ValueSource;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -99,49 +98,26 @@ public class PubSubIT extends BaseIT {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ParameterizedTest
|
@Test
|
||||||
@ValueSource(booleans = {true, false})
|
public void publishPubSubNotFound() throws Exception {
|
||||||
public void publishPubSubNotFound(boolean useGrpc) throws Exception {
|
|
||||||
DaprRun daprRun = closeLater(startDaprApp(
|
DaprRun daprRun = closeLater(startDaprApp(
|
||||||
this.getClass().getSimpleName(),
|
this.getClass().getSimpleName(),
|
||||||
60000));
|
60000));
|
||||||
if (useGrpc) {
|
|
||||||
daprRun.switchToGRPC();
|
|
||||||
} else {
|
|
||||||
daprRun.switchToHTTP();
|
|
||||||
}
|
|
||||||
|
|
||||||
try (DaprClient client = new DaprClientBuilder().build()) {
|
try (DaprClient client = new DaprClientBuilder().build()) {
|
||||||
|
assertThrowsDaprExceptionWithReason(
|
||||||
if (useGrpc) {
|
"INVALID_ARGUMENT",
|
||||||
assertThrowsDaprExceptionWithReason(
|
"INVALID_ARGUMENT: pubsub unknown pubsub is not found",
|
||||||
"INVALID_ARGUMENT",
|
"DAPR_PUBSUB_NOT_FOUND",
|
||||||
"INVALID_ARGUMENT: pubsub unknown pubsub is not found",
|
() -> client.publishEvent("unknown pubsub", "mytopic", "payload").block());
|
||||||
"DAPR_PUBSUB_NOT_FOUND",
|
|
||||||
() -> client.publishEvent("unknown pubsub", "mytopic", "payload").block());
|
|
||||||
} else {
|
|
||||||
assertThrowsDaprExceptionWithReason(
|
|
||||||
"ERR_PUBSUB_NOT_FOUND",
|
|
||||||
"ERR_PUBSUB_NOT_FOUND: pubsub unknown pubsub is not found",
|
|
||||||
"DAPR_PUBSUB_NOT_FOUND",
|
|
||||||
() -> client.publishEvent("unknown pubsub", "mytopic", "payload").block());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ParameterizedTest
|
@Test
|
||||||
@ValueSource(booleans = {true, false})
|
public void testBulkPublishPubSubNotFound() throws Exception {
|
||||||
public void testBulkPublishPubSubNotFound(boolean useGrpc) throws Exception {
|
|
||||||
DaprRun daprRun = closeLater(startDaprApp(
|
DaprRun daprRun = closeLater(startDaprApp(
|
||||||
this.getClass().getSimpleName(),
|
this.getClass().getSimpleName(),
|
||||||
60000));
|
60000));
|
||||||
if (useGrpc) {
|
|
||||||
daprRun.switchToGRPC();
|
|
||||||
} else {
|
|
||||||
// No HTTP implementation for bulk publish
|
|
||||||
System.out.println("no HTTP impl for bulkPublish");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try (DaprPreviewClient client = new DaprClientBuilder().buildPreviewClient()) {
|
try (DaprPreviewClient client = new DaprClientBuilder().buildPreviewClient()) {
|
||||||
assertThrowsDaprException(
|
assertThrowsDaprException(
|
||||||
|
@ -151,22 +127,14 @@ public class PubSubIT extends BaseIT {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ParameterizedTest
|
@Test
|
||||||
@ValueSource(booleans = {true, false})
|
public void testBulkPublish() throws Exception {
|
||||||
public void testBulkPublish(boolean useGrpc) throws Exception {
|
|
||||||
final DaprRun daprRun = closeLater(startDaprApp(
|
final DaprRun daprRun = closeLater(startDaprApp(
|
||||||
this.getClass().getSimpleName(),
|
this.getClass().getSimpleName(),
|
||||||
SubscriberService.SUCCESS_MESSAGE,
|
SubscriberService.SUCCESS_MESSAGE,
|
||||||
SubscriberService.class,
|
SubscriberService.class,
|
||||||
true,
|
true,
|
||||||
60000));
|
60000));
|
||||||
// At this point, it is guaranteed that the service above is running and all ports being listened to.
|
|
||||||
if (useGrpc) {
|
|
||||||
daprRun.switchToGRPC();
|
|
||||||
} else {
|
|
||||||
System.out.println("HTTP BulkPublish is not implemented. So skipping tests");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
DaprObjectSerializer serializer = new DaprObjectSerializer() {
|
DaprObjectSerializer serializer = new DaprObjectSerializer() {
|
||||||
@Override
|
@Override
|
||||||
public byte[] serialize(Object o) throws JsonProcessingException {
|
public byte[] serialize(Object o) throws JsonProcessingException {
|
||||||
|
@ -287,21 +255,14 @@ public class PubSubIT extends BaseIT {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ParameterizedTest
|
@Test
|
||||||
@ValueSource(booleans = {true, false})
|
public void testPubSub() throws Exception {
|
||||||
public void testPubSub(boolean useGrpc) throws Exception {
|
|
||||||
final DaprRun daprRun = closeLater(startDaprApp(
|
final DaprRun daprRun = closeLater(startDaprApp(
|
||||||
this.getClass().getSimpleName(),
|
this.getClass().getSimpleName(),
|
||||||
SubscriberService.SUCCESS_MESSAGE,
|
SubscriberService.SUCCESS_MESSAGE,
|
||||||
SubscriberService.class,
|
SubscriberService.class,
|
||||||
true,
|
true,
|
||||||
60000));
|
60000));
|
||||||
// At this point, it is guaranteed that the service above is running and all ports being listened to.
|
|
||||||
if (useGrpc) {
|
|
||||||
daprRun.switchToGRPC();
|
|
||||||
} else {
|
|
||||||
daprRun.switchToHTTP();
|
|
||||||
}
|
|
||||||
|
|
||||||
DaprObjectSerializer serializer = new DaprObjectSerializer() {
|
DaprObjectSerializer serializer = new DaprObjectSerializer() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -508,21 +469,14 @@ public class PubSubIT extends BaseIT {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ParameterizedTest
|
@Test
|
||||||
@ValueSource(booleans = {true, false})
|
public void testPubSubBinary() throws Exception {
|
||||||
public void testPubSubBinary(boolean useGrpc) throws Exception {
|
|
||||||
final DaprRun daprRun = closeLater(startDaprApp(
|
final DaprRun daprRun = closeLater(startDaprApp(
|
||||||
this.getClass().getSimpleName(),
|
this.getClass().getSimpleName(),
|
||||||
SubscriberService.SUCCESS_MESSAGE,
|
SubscriberService.SUCCESS_MESSAGE,
|
||||||
SubscriberService.class,
|
SubscriberService.class,
|
||||||
true,
|
true,
|
||||||
60000));
|
60000));
|
||||||
// At this point, it is guaranteed that the service above is running and all ports being listened to.
|
|
||||||
if (useGrpc) {
|
|
||||||
daprRun.switchToGRPC();
|
|
||||||
} else {
|
|
||||||
daprRun.switchToHTTP();
|
|
||||||
}
|
|
||||||
|
|
||||||
DaprObjectSerializer serializer = new DaprObjectSerializer() {
|
DaprObjectSerializer serializer = new DaprObjectSerializer() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -565,17 +519,11 @@ public class PubSubIT extends BaseIT {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ParameterizedTest
|
@Test
|
||||||
@ValueSource(booleans = {true, false})
|
public void testPubSubTTLMetadata() throws Exception {
|
||||||
public void testPubSubTTLMetadata(boolean useGrpc) throws Exception {
|
|
||||||
DaprRun daprRun = closeLater(startDaprApp(
|
DaprRun daprRun = closeLater(startDaprApp(
|
||||||
this.getClass().getSimpleName(),
|
this.getClass().getSimpleName(),
|
||||||
60000));
|
60000));
|
||||||
if (useGrpc) {
|
|
||||||
daprRun.switchToGRPC();
|
|
||||||
} else {
|
|
||||||
daprRun.switchToHTTP();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send a batch of messages on one topic, all to be expired in 1 second.
|
// Send a batch of messages on one topic, all to be expired in 1 second.
|
||||||
try (DaprClient client = new DaprClientBuilder().build()) {
|
try (DaprClient client = new DaprClientBuilder().build()) {
|
||||||
|
@ -602,11 +550,6 @@ public class PubSubIT extends BaseIT {
|
||||||
SubscriberService.class,
|
SubscriberService.class,
|
||||||
true,
|
true,
|
||||||
60000));
|
60000));
|
||||||
if (useGrpc) {
|
|
||||||
daprRun.switchToGRPC();
|
|
||||||
} else {
|
|
||||||
daprRun.switchToHTTP();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sleeps for five seconds to give subscriber a chance to receive messages.
|
// Sleeps for five seconds to give subscriber a chance to receive messages.
|
||||||
Thread.sleep(5000);
|
Thread.sleep(5000);
|
||||||
|
@ -623,20 +566,14 @@ public class PubSubIT extends BaseIT {
|
||||||
daprRun.stop();
|
daprRun.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ParameterizedTest
|
@Test
|
||||||
@ValueSource(booleans = {true, false})
|
public void testPubSubBulkSubscribe() throws Exception {
|
||||||
public void testPubSubBulkSubscribe(boolean useGrpc) throws Exception {
|
|
||||||
DaprRun daprRun = closeLater(startDaprApp(
|
DaprRun daprRun = closeLater(startDaprApp(
|
||||||
this.getClass().getSimpleName(),
|
this.getClass().getSimpleName(),
|
||||||
SubscriberService.SUCCESS_MESSAGE,
|
SubscriberService.SUCCESS_MESSAGE,
|
||||||
SubscriberService.class,
|
SubscriberService.class,
|
||||||
true,
|
true,
|
||||||
60000));
|
60000));
|
||||||
if (useGrpc) {
|
|
||||||
daprRun.switchToGRPC();
|
|
||||||
} else {
|
|
||||||
daprRun.switchToHTTP();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send a batch of messages on one topic.
|
// Send a batch of messages on one topic.
|
||||||
try (DaprClient client = new DaprClientBuilder().build()) {
|
try (DaprClient client = new DaprClientBuilder().build()) {
|
||||||
|
@ -686,21 +623,14 @@ public class PubSubIT extends BaseIT {
|
||||||
daprRun.stop();
|
daprRun.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ParameterizedTest
|
@Test
|
||||||
@ValueSource(booleans = {true, false})
|
public void testLongValues() throws Exception {
|
||||||
public void testLongValues(boolean useGrpc) throws Exception {
|
|
||||||
final DaprRun daprRun = closeLater(startDaprApp(
|
final DaprRun daprRun = closeLater(startDaprApp(
|
||||||
this.getClass().getSimpleName(),
|
this.getClass().getSimpleName(),
|
||||||
SubscriberService.SUCCESS_MESSAGE,
|
SubscriberService.SUCCESS_MESSAGE,
|
||||||
SubscriberService.class,
|
SubscriberService.class,
|
||||||
true,
|
true,
|
||||||
60000));
|
60000));
|
||||||
// At this point, it is guaranteed that the service above is running and all ports being listened to.
|
|
||||||
if (useGrpc) {
|
|
||||||
daprRun.switchToGRPC();
|
|
||||||
} else {
|
|
||||||
daprRun.switchToHTTP();
|
|
||||||
}
|
|
||||||
|
|
||||||
Random random = new Random(590518626939830271L);
|
Random random = new Random(590518626939830271L);
|
||||||
Set<ConvertToLong> values = new HashSet<>();
|
Set<ConvertToLong> values = new HashSet<>();
|
||||||
|
|
|
@ -15,7 +15,12 @@ package io.dapr.it.pubsub.http;
|
||||||
|
|
||||||
import io.dapr.Rule;
|
import io.dapr.Rule;
|
||||||
import io.dapr.Topic;
|
import io.dapr.Topic;
|
||||||
import io.dapr.client.domain.*;
|
import io.dapr.client.domain.BulkSubscribeAppResponse;
|
||||||
|
import io.dapr.client.domain.BulkSubscribeAppResponseEntry;
|
||||||
|
import io.dapr.client.domain.BulkSubscribeAppResponseStatus;
|
||||||
|
import io.dapr.client.domain.BulkSubscribeMessage;
|
||||||
|
import io.dapr.client.domain.BulkSubscribeMessageEntry;
|
||||||
|
import io.dapr.client.domain.CloudEvent;
|
||||||
import io.dapr.springboot.annotations.BulkSubscribe;
|
import io.dapr.springboot.annotations.BulkSubscribe;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.PathVariable;
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
|
|
|
@ -15,7 +15,7 @@ package io.dapr.it.resiliency;
|
||||||
|
|
||||||
import io.dapr.client.DaprClient;
|
import io.dapr.client.DaprClient;
|
||||||
import io.dapr.client.DaprClientBuilder;
|
import io.dapr.client.DaprClientBuilder;
|
||||||
import io.dapr.client.DaprClientGrpc;
|
import io.dapr.client.DaprClientImpl;
|
||||||
import io.dapr.client.resiliency.ResiliencyOptions;
|
import io.dapr.client.resiliency.ResiliencyOptions;
|
||||||
import io.dapr.it.BaseIT;
|
import io.dapr.it.BaseIT;
|
||||||
import io.dapr.it.DaprRun;
|
import io.dapr.it.DaprRun;
|
||||||
|
@ -65,8 +65,6 @@ public class SdkResiliencytIT extends BaseIT {
|
||||||
@BeforeAll
|
@BeforeAll
|
||||||
public static void init() throws Exception {
|
public static void init() throws Exception {
|
||||||
daprRun = startDaprApp(SdkResiliencytIT.class.getSimpleName(), 5000);
|
daprRun = startDaprApp(SdkResiliencytIT.class.getSimpleName(), 5000);
|
||||||
// HTTP client is deprecated, so SDK resiliency is for gRPC client only.
|
|
||||||
daprRun.switchToGRPC();
|
|
||||||
daprClient = new DaprClientBuilder().build();
|
daprClient = new DaprClientBuilder().build();
|
||||||
daprClient.waitForSidecar(8000).block();
|
daprClient.waitForSidecar(8000).block();
|
||||||
|
|
||||||
|
@ -87,10 +85,10 @@ public class SdkResiliencytIT extends BaseIT {
|
||||||
new ResiliencyOptions().setTimeout(TIMEOUT).setMaxRetries(1))
|
new ResiliencyOptions().setTimeout(TIMEOUT).setMaxRetries(1))
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
assertTrue(daprClient instanceof DaprClientGrpc);
|
assertTrue(daprClient instanceof DaprClientImpl);
|
||||||
assertTrue(daprToxiClient instanceof DaprClientGrpc);
|
assertTrue(daprToxiClient instanceof DaprClientImpl);
|
||||||
assertTrue(daprResilientClient instanceof DaprClientGrpc);
|
assertTrue(daprResilientClient instanceof DaprClientImpl);
|
||||||
assertTrue(daprRetriesOnceClient instanceof DaprClientGrpc);
|
assertTrue(daprRetriesOnceClient instanceof DaprClientImpl);
|
||||||
}
|
}
|
||||||
|
|
||||||
@AfterAll
|
@AfterAll
|
||||||
|
|
|
@ -19,23 +19,14 @@ import io.dapr.client.DaprClientBuilder;
|
||||||
import io.dapr.it.BaseIT;
|
import io.dapr.it.BaseIT;
|
||||||
import io.dapr.it.DaprRun;
|
import io.dapr.it.DaprRun;
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.junit.After;
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.BeforeClass;
|
|
||||||
import org.junit.jupiter.api.AfterEach;
|
import org.junit.jupiter.api.AfterEach;
|
||||||
import org.junit.jupiter.api.BeforeAll;
|
import org.junit.jupiter.api.BeforeAll;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.params.ParameterizedTest;
|
|
||||||
import org.junit.jupiter.params.provider.ValueSource;
|
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
import org.junit.runners.Parameterized;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
@ -82,13 +73,8 @@ public class SecretsClientIT extends BaseIT {
|
||||||
daprRun = startDaprApp(SecretsClientIT.class.getSimpleName(), 5000);
|
daprRun = startDaprApp(SecretsClientIT.class.getSimpleName(), 5000);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setup(boolean useGrpc) {
|
@BeforeEach
|
||||||
if (useGrpc) {
|
public void setup() {
|
||||||
daprRun.switchToGRPC();
|
|
||||||
} else {
|
|
||||||
daprRun.switchToHTTP();
|
|
||||||
}
|
|
||||||
|
|
||||||
this.daprClient = new DaprClientBuilder().build();
|
this.daprClient = new DaprClientBuilder().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,22 +84,16 @@ public class SecretsClientIT extends BaseIT {
|
||||||
clearSecretFile();
|
clearSecretFile();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ParameterizedTest
|
@Test
|
||||||
@ValueSource(booleans = {true, false})
|
public void getSecret() throws Exception {
|
||||||
public void getSecret(boolean useGrpc) throws Exception {
|
|
||||||
setup(useGrpc);
|
|
||||||
|
|
||||||
Map<String, String> data = daprClient.getSecret(SECRETS_STORE_NAME, KEY1).block();
|
Map<String, String> data = daprClient.getSecret(SECRETS_STORE_NAME, KEY1).block();
|
||||||
assertEquals(2, data.size());
|
assertEquals(2, data.size());
|
||||||
assertEquals("The Metrics IV", data.get("title"));
|
assertEquals("The Metrics IV", data.get("title"));
|
||||||
assertEquals("2020", data.get("year"));
|
assertEquals("2020", data.get("year"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ParameterizedTest
|
@Test
|
||||||
@ValueSource(booleans = {true, false})
|
public void getBulkSecret() throws Exception {
|
||||||
public void getBulkSecret(boolean useGrpc) throws Exception {
|
|
||||||
setup(useGrpc);
|
|
||||||
|
|
||||||
Map<String, Map<String, String>> data = daprClient.getBulkSecret(SECRETS_STORE_NAME).block();
|
Map<String, Map<String, String>> data = daprClient.getBulkSecret(SECRETS_STORE_NAME).block();
|
||||||
// There can be other keys from other runs or test cases, so we are good with at least two.
|
// There can be other keys from other runs or test cases, so we are good with at least two.
|
||||||
assertTrue(data.size() >= 2);
|
assertTrue(data.size() >= 2);
|
||||||
|
@ -124,19 +104,13 @@ public class SecretsClientIT extends BaseIT {
|
||||||
assertEquals("Jon Doe", data.get(KYE2).get("name"));
|
assertEquals("Jon Doe", data.get(KYE2).get("name"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ParameterizedTest
|
@Test
|
||||||
@ValueSource(booleans = {true, false})
|
public void getSecretKeyNotFound() {
|
||||||
public void getSecretKeyNotFound(boolean useGrpc) {
|
|
||||||
setup(useGrpc);
|
|
||||||
|
|
||||||
assertThrows(RuntimeException.class, () -> daprClient.getSecret(SECRETS_STORE_NAME, "unknownKey").block());
|
assertThrows(RuntimeException.class, () -> daprClient.getSecret(SECRETS_STORE_NAME, "unknownKey").block());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ParameterizedTest
|
@Test
|
||||||
@ValueSource(booleans = {true, false})
|
public void getSecretStoreNotFound() {
|
||||||
public void getSecretStoreNotFound(boolean useGrpc) throws Exception {
|
|
||||||
setup(useGrpc);
|
|
||||||
|
|
||||||
assertThrows(RuntimeException.class, () -> daprClient.getSecret("unknownStore", "unknownKey").block());
|
assertThrows(RuntimeException.class, () -> daprClient.getSecret("unknownStore", "unknownKey").block());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,6 @@ public class GRPCStateClientIT extends AbstractStateClientIT {
|
||||||
@BeforeAll
|
@BeforeAll
|
||||||
public static void init() throws Exception {
|
public static void init() throws Exception {
|
||||||
daprRun = startDaprApp(GRPCStateClientIT.class.getSimpleName(), 5000);
|
daprRun = startDaprApp(GRPCStateClientIT.class.getSimpleName(), 5000);
|
||||||
daprRun.switchToGRPC();
|
|
||||||
daprClient = new DaprClientBuilder().build();
|
daprClient = new DaprClientBuilder().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,9 +13,9 @@ limitations under the License.
|
||||||
|
|
||||||
package io.dapr.it.state;
|
package io.dapr.it.state;
|
||||||
|
|
||||||
|
import io.dapr.config.Properties;
|
||||||
import io.dapr.it.BaseIT;
|
import io.dapr.it.BaseIT;
|
||||||
import io.dapr.it.DaprRun;
|
import io.dapr.it.DaprRun;
|
||||||
import io.dapr.config.Properties;
|
|
||||||
import io.dapr.v1.DaprGrpc;
|
import io.dapr.v1.DaprGrpc;
|
||||||
import io.dapr.v1.DaprProtos;
|
import io.dapr.v1.DaprProtos;
|
||||||
import io.grpc.ManagedChannel;
|
import io.grpc.ManagedChannel;
|
||||||
|
|
|
@ -1,94 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2021 The Dapr 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.dapr.it.state;
|
|
||||||
|
|
||||||
import io.dapr.client.DaprClient;
|
|
||||||
import io.dapr.client.DaprClientBuilder;
|
|
||||||
import io.dapr.client.DaprClientHttp;
|
|
||||||
import io.dapr.client.domain.State;
|
|
||||||
import io.dapr.it.DaprRun;
|
|
||||||
import org.junit.jupiter.api.AfterAll;
|
|
||||||
import org.junit.jupiter.api.BeforeAll;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
|
|
||||||
import static io.dapr.it.TestUtils.assertThrowsDaprException;
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test State HTTP DAPR capabilities using a DAPR instance with an empty service running
|
|
||||||
*/
|
|
||||||
public class HttpStateClientIT extends AbstractStateClientIT {
|
|
||||||
|
|
||||||
private static DaprRun daprRun;
|
|
||||||
|
|
||||||
private static DaprClient daprClient;
|
|
||||||
|
|
||||||
@BeforeAll
|
|
||||||
public static void init() throws Exception {
|
|
||||||
daprRun = startDaprApp(HttpStateClientIT.class.getSimpleName(), 5000);
|
|
||||||
daprRun.switchToHTTP();
|
|
||||||
daprClient = new DaprClientBuilder().build();
|
|
||||||
assertTrue(daprClient instanceof DaprClientHttp);
|
|
||||||
}
|
|
||||||
|
|
||||||
@AfterAll
|
|
||||||
public static void tearDown() throws Exception {
|
|
||||||
daprClient.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected DaprClient buildDaprClient() {
|
|
||||||
return daprClient;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Tests where HTTP and GRPC behavior differ in Dapr runtime. **/
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void getStateStoreNotFound() {
|
|
||||||
final String stateKey = "key";
|
|
||||||
|
|
||||||
DaprClient daprClient = buildDaprClient();
|
|
||||||
|
|
||||||
// DaprException is guaranteed in the Dapr SDK but getCause() is null in HTTP while present in GRPC implementation.
|
|
||||||
assertThrowsDaprException(
|
|
||||||
"ERR_STATE_STORE_NOT_FOUND",
|
|
||||||
"ERR_STATE_STORE_NOT_FOUND: state store unknown state store is not found",
|
|
||||||
() -> daprClient.getState("unknown state store", new State(stateKey), byte[].class).block());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void getStatesStoreNotFound() {
|
|
||||||
final String stateKey = "key";
|
|
||||||
|
|
||||||
DaprClient daprClient = buildDaprClient();
|
|
||||||
|
|
||||||
// DaprException is guaranteed in the Dapr SDK but getCause() is null in HTTP while present in GRPC implementation.
|
|
||||||
assertThrowsDaprException(
|
|
||||||
"ERR_STATE_STORE_NOT_FOUND",
|
|
||||||
"ERR_STATE_STORE_NOT_FOUND: state store unknown state store is not found",
|
|
||||||
() -> daprClient.getBulkState(
|
|
||||||
"unknown state store",
|
|
||||||
Collections.singletonList(stateKey),
|
|
||||||
byte[].class).block());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void publishPubSubNotFound() {
|
|
||||||
DaprClient daprClient = buildDaprClient();
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,9 +1,9 @@
|
||||||
package io.dapr.it.tracing.grpc;
|
package io.dapr.it.tracing.grpc;
|
||||||
|
|
||||||
import io.dapr.client.DaprApiProtocol;
|
|
||||||
import io.dapr.client.DaprClient;
|
import io.dapr.client.DaprClient;
|
||||||
import io.dapr.client.DaprClientBuilder;
|
import io.dapr.client.DaprClientBuilder;
|
||||||
import io.dapr.client.domain.HttpExtension;
|
import io.dapr.client.domain.HttpExtension;
|
||||||
|
import io.dapr.it.AppRun;
|
||||||
import io.dapr.it.BaseIT;
|
import io.dapr.it.BaseIT;
|
||||||
import io.dapr.it.DaprRun;
|
import io.dapr.it.DaprRun;
|
||||||
import io.dapr.it.tracing.Validation;
|
import io.dapr.it.tracing.Validation;
|
||||||
|
@ -12,8 +12,8 @@ import io.opentelemetry.api.trace.Span;
|
||||||
import io.opentelemetry.api.trace.Tracer;
|
import io.opentelemetry.api.trace.Tracer;
|
||||||
import io.opentelemetry.context.Scope;
|
import io.opentelemetry.context.Scope;
|
||||||
import io.opentelemetry.sdk.OpenTelemetrySdk;
|
import io.opentelemetry.sdk.OpenTelemetrySdk;
|
||||||
import org.junit.jupiter.params.ParameterizedTest;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.params.provider.ValueSource;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@ -28,28 +28,20 @@ public class TracingIT extends BaseIT {
|
||||||
*/
|
*/
|
||||||
private DaprRun daprRun = null;
|
private DaprRun daprRun = null;
|
||||||
|
|
||||||
public void setup(boolean useGrpc) throws Exception {
|
@BeforeEach
|
||||||
|
public void setup() throws Exception {
|
||||||
daprRun = startDaprApp(
|
daprRun = startDaprApp(
|
||||||
TracingIT.class.getSimpleName() + "grpc",
|
TracingIT.class.getSimpleName() + "grpc",
|
||||||
Service.SUCCESS_MESSAGE,
|
Service.SUCCESS_MESSAGE,
|
||||||
Service.class,
|
Service.class,
|
||||||
DaprApiProtocol.GRPC, // appProtocol
|
AppRun.AppProtocol.GRPC, // appProtocol
|
||||||
60000);
|
60000);
|
||||||
|
|
||||||
if (useGrpc) {
|
|
||||||
daprRun.switchToGRPC();
|
|
||||||
} else {
|
|
||||||
daprRun.switchToHTTP();
|
|
||||||
}
|
|
||||||
|
|
||||||
daprRun.waitForAppHealth(10000);
|
daprRun.waitForAppHealth(10000);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ParameterizedTest
|
@Test
|
||||||
@ValueSource(booleans = {true, false})
|
public void testInvoke() throws Exception {
|
||||||
public void testInvoke(boolean useGrpc) throws Exception {
|
|
||||||
setup(useGrpc);
|
|
||||||
|
|
||||||
final OpenTelemetry openTelemetry = createOpenTelemetry("service over grpc");
|
final OpenTelemetry openTelemetry = createOpenTelemetry("service over grpc");
|
||||||
final Tracer tracer = openTelemetry.getTracer("grpc integration test tracer");
|
final Tracer tracer = openTelemetry.getTracer("grpc integration test tracer");
|
||||||
|
|
||||||
|
|
|
@ -16,14 +16,14 @@ package io.dapr.it.tracing.http;
|
||||||
import io.opentelemetry.api.OpenTelemetry;
|
import io.opentelemetry.api.OpenTelemetry;
|
||||||
import io.opentelemetry.context.Context;
|
import io.opentelemetry.context.Context;
|
||||||
import io.opentelemetry.context.propagation.TextMapPropagator;
|
import io.opentelemetry.context.propagation.TextMapPropagator;
|
||||||
|
import jakarta.servlet.DispatcherType;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import org.springframework.web.servlet.HandlerInterceptor;
|
import org.springframework.web.servlet.HandlerInterceptor;
|
||||||
import org.springframework.web.servlet.ModelAndView;
|
import org.springframework.web.servlet.ModelAndView;
|
||||||
|
|
||||||
import jakarta.servlet.DispatcherType;
|
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
|
|
|
@ -11,8 +11,8 @@ import io.opentelemetry.api.trace.Span;
|
||||||
import io.opentelemetry.api.trace.Tracer;
|
import io.opentelemetry.api.trace.Tracer;
|
||||||
import io.opentelemetry.context.Scope;
|
import io.opentelemetry.context.Scope;
|
||||||
import io.opentelemetry.sdk.OpenTelemetrySdk;
|
import io.opentelemetry.sdk.OpenTelemetrySdk;
|
||||||
import org.junit.jupiter.params.ParameterizedTest;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.params.provider.ValueSource;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@ -26,7 +26,8 @@ public class TracingIT extends BaseIT {
|
||||||
*/
|
*/
|
||||||
private DaprRun daprRun = null;
|
private DaprRun daprRun = null;
|
||||||
|
|
||||||
public void setup(boolean useGrpc) throws Exception {
|
@BeforeEach
|
||||||
|
public void setup() throws Exception {
|
||||||
daprRun = startDaprApp(
|
daprRun = startDaprApp(
|
||||||
TracingIT.class.getSimpleName() + "http",
|
TracingIT.class.getSimpleName() + "http",
|
||||||
Service.SUCCESS_MESSAGE,
|
Service.SUCCESS_MESSAGE,
|
||||||
|
@ -34,21 +35,12 @@ public class TracingIT extends BaseIT {
|
||||||
true,
|
true,
|
||||||
30000);
|
30000);
|
||||||
|
|
||||||
if (useGrpc) {
|
|
||||||
daprRun.switchToGRPC();
|
|
||||||
} else {
|
|
||||||
daprRun.switchToHTTP();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wait since service might be ready even after port is available.
|
// Wait since service might be ready even after port is available.
|
||||||
Thread.sleep(2000);
|
Thread.sleep(2000);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ParameterizedTest
|
@Test
|
||||||
@ValueSource(booleans = {true, false})
|
public void testInvoke() throws Exception {
|
||||||
public void testInvoke(boolean useGrpc) throws Exception {
|
|
||||||
setup(useGrpc);
|
|
||||||
|
|
||||||
final OpenTelemetry openTelemetry = createOpenTelemetry(OpenTelemetryConfig.SERVICE_NAME);
|
final OpenTelemetry openTelemetry = createOpenTelemetry(OpenTelemetryConfig.SERVICE_NAME);
|
||||||
final Tracer tracer = openTelemetry.getTracer(OpenTelemetryConfig.TRACER_NAME);
|
final Tracer tracer = openTelemetry.getTracer(OpenTelemetryConfig.TRACER_NAME);
|
||||||
|
|
||||||
|
|
|
@ -59,7 +59,7 @@ import java.util.stream.Collectors;
|
||||||
* Abstract class with convenient methods common between client implementations.
|
* Abstract class with convenient methods common between client implementations.
|
||||||
*
|
*
|
||||||
* @see io.dapr.client.DaprClient
|
* @see io.dapr.client.DaprClient
|
||||||
* @see io.dapr.client.DaprClientGrpc
|
* @see DaprClientImpl
|
||||||
* @see io.dapr.client.DaprClientHttp
|
* @see io.dapr.client.DaprClientHttp
|
||||||
*/
|
*/
|
||||||
abstract class AbstractDaprClient implements DaprClient, DaprPreviewClient {
|
abstract class AbstractDaprClient implements DaprClient, DaprPreviewClient {
|
||||||
|
|
|
@ -1,26 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2021 The Dapr 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.dapr.client;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Transport protocol for Dapr's API.
|
|
||||||
* @deprecated This class will be deleted at SDK version 1.10.
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public enum DaprApiProtocol {
|
|
||||||
|
|
||||||
GRPC,
|
|
||||||
HTTP
|
|
||||||
|
|
||||||
}
|
|
|
@ -34,11 +34,14 @@ import io.dapr.client.domain.TransactionalStateOperation;
|
||||||
import io.dapr.client.domain.UnsubscribeConfigurationRequest;
|
import io.dapr.client.domain.UnsubscribeConfigurationRequest;
|
||||||
import io.dapr.client.domain.UnsubscribeConfigurationResponse;
|
import io.dapr.client.domain.UnsubscribeConfigurationResponse;
|
||||||
import io.dapr.utils.TypeRef;
|
import io.dapr.utils.TypeRef;
|
||||||
|
import io.grpc.Channel;
|
||||||
|
import io.grpc.stub.AbstractStub;
|
||||||
import reactor.core.publisher.Flux;
|
import reactor.core.publisher.Flux;
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generic Client Adapter to be used regardless of the GRPC or the HTTP Client implementation required.
|
* Generic Client Adapter to be used regardless of the GRPC or the HTTP Client implementation required.
|
||||||
|
@ -659,6 +662,15 @@ public interface DaprClient extends AutoCloseable {
|
||||||
*/
|
*/
|
||||||
Mono<UnsubscribeConfigurationResponse> unsubscribeConfiguration(UnsubscribeConfigurationRequest request);
|
Mono<UnsubscribeConfigurationResponse> unsubscribeConfiguration(UnsubscribeConfigurationRequest request);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a newly created gRPC stub with proper interceptors and channel for gRPC proxy invocation.
|
||||||
|
* @param appId appId to be included in all gRPC calls for service invocation.
|
||||||
|
* @param stubBuilder user-provided callback method to construct a new stub given the channel.
|
||||||
|
* @return the gRPC stub with proper interceptors and channel.
|
||||||
|
* @param <T> the generic type of the service to be invoked.
|
||||||
|
*/
|
||||||
|
<T extends AbstractStub<T>> T newGrpcStub(String appId, Function<Channel, T> stubBuilder);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gracefully shutdown the dapr runtime.
|
* Gracefully shutdown the dapr runtime.
|
||||||
*
|
*
|
||||||
|
|
|
@ -14,14 +14,11 @@ limitations under the License.
|
||||||
package io.dapr.client;
|
package io.dapr.client;
|
||||||
|
|
||||||
import io.dapr.client.resiliency.ResiliencyOptions;
|
import io.dapr.client.resiliency.ResiliencyOptions;
|
||||||
import io.dapr.config.Properties;
|
|
||||||
import io.dapr.serializer.DaprObjectSerializer;
|
import io.dapr.serializer.DaprObjectSerializer;
|
||||||
import io.dapr.serializer.DefaultObjectSerializer;
|
import io.dapr.serializer.DefaultObjectSerializer;
|
||||||
import io.dapr.utils.NetworkUtils;
|
import io.dapr.utils.NetworkUtils;
|
||||||
import io.dapr.v1.DaprGrpc;
|
import io.dapr.v1.DaprGrpc;
|
||||||
import io.grpc.ManagedChannel;
|
import io.grpc.ManagedChannel;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A builder for the DaprClient,
|
* A builder for the DaprClient,
|
||||||
|
@ -29,18 +26,6 @@ import org.slf4j.LoggerFactory;
|
||||||
*/
|
*/
|
||||||
public class DaprClientBuilder {
|
public class DaprClientBuilder {
|
||||||
|
|
||||||
private static final Logger LOGGER = LoggerFactory.getLogger(DaprClientBuilder.class);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Determine if this builder will create GRPC clients instead of HTTP clients.
|
|
||||||
*/
|
|
||||||
private final DaprApiProtocol apiProtocol;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Determine if this builder will use HTTP client for service method invocation APIs.
|
|
||||||
*/
|
|
||||||
private final DaprApiProtocol methodInvocationApiProtocol;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builder for Dapr's HTTP Client.
|
* Builder for Dapr's HTTP Client.
|
||||||
*/
|
*/
|
||||||
|
@ -70,8 +55,6 @@ public class DaprClientBuilder {
|
||||||
public DaprClientBuilder() {
|
public DaprClientBuilder() {
|
||||||
this.objectSerializer = new DefaultObjectSerializer();
|
this.objectSerializer = new DefaultObjectSerializer();
|
||||||
this.stateSerializer = new DefaultObjectSerializer();
|
this.stateSerializer = new DefaultObjectSerializer();
|
||||||
this.apiProtocol = Properties.API_PROTOCOL.get();
|
|
||||||
this.methodInvocationApiProtocol = Properties.API_METHOD_INVOCATION_PROTOCOL.get();
|
|
||||||
this.daprHttpBuilder = new DaprHttpBuilder();
|
this.daprHttpBuilder = new DaprHttpBuilder();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,15 +112,7 @@ public class DaprClientBuilder {
|
||||||
* @throws java.lang.IllegalStateException if any required field is missing
|
* @throws java.lang.IllegalStateException if any required field is missing
|
||||||
*/
|
*/
|
||||||
public DaprClient build() {
|
public DaprClient build() {
|
||||||
if (this.apiProtocol == DaprApiProtocol.HTTP) {
|
return buildDaprClient();
|
||||||
LOGGER.warn("HTTP client protocol is deprecated and will be removed in Dapr's Java SDK version 1.10.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.apiProtocol != this.methodInvocationApiProtocol) {
|
|
||||||
return new DaprClientProxy(buildDaprClient(this.apiProtocol), buildDaprClient(this.methodInvocationApiProtocol));
|
|
||||||
}
|
|
||||||
|
|
||||||
return buildDaprClient(this.apiProtocol);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -147,26 +122,7 @@ public class DaprClientBuilder {
|
||||||
* @throws IllegalStateException if any required field is missing
|
* @throws IllegalStateException if any required field is missing
|
||||||
*/
|
*/
|
||||||
public DaprPreviewClient buildPreviewClient() {
|
public DaprPreviewClient buildPreviewClient() {
|
||||||
return (DaprPreviewClient) buildDaprClient(this.apiProtocol);
|
return buildDaprClient();
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates an instance of a Dapr Client based on the chosen protocol.
|
|
||||||
*
|
|
||||||
* @param protocol Dapr API's protocol.
|
|
||||||
* @return the GRPC Client.
|
|
||||||
* @throws java.lang.IllegalStateException if either host is missing or if port is missing or a negative number.
|
|
||||||
*/
|
|
||||||
private DaprClient buildDaprClient(DaprApiProtocol protocol) {
|
|
||||||
if (protocol == null) {
|
|
||||||
throw new IllegalStateException("Protocol is required.");
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (protocol) {
|
|
||||||
case GRPC: return buildDaprClientGrpc();
|
|
||||||
case HTTP: return buildDaprClientHttp();
|
|
||||||
default: throw new IllegalStateException("Unsupported protocol: " + protocol.name());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -175,25 +131,17 @@ public class DaprClientBuilder {
|
||||||
* @return the GRPC Client.
|
* @return the GRPC Client.
|
||||||
* @throws java.lang.IllegalStateException if either host is missing or if port is missing or a negative number.
|
* @throws java.lang.IllegalStateException if either host is missing or if port is missing or a negative number.
|
||||||
*/
|
*/
|
||||||
private DaprClient buildDaprClientGrpc() {
|
private DaprClientImpl buildDaprClient() {
|
||||||
final ManagedChannel channel = NetworkUtils.buildGrpcManagedChannel();
|
final ManagedChannel channel = NetworkUtils.buildGrpcManagedChannel();
|
||||||
final GrpcChannelFacade channelFacade = new GrpcChannelFacade(channel, this.daprHttpBuilder.build());
|
final DaprHttp daprHttp = this.daprHttpBuilder.build();
|
||||||
|
final GrpcChannelFacade channelFacade = new GrpcChannelFacade(channel);
|
||||||
DaprGrpc.DaprStub asyncStub = DaprGrpc.newStub(channel);
|
DaprGrpc.DaprStub asyncStub = DaprGrpc.newStub(channel);
|
||||||
return new DaprClientGrpc(
|
return new DaprClientImpl(
|
||||||
channelFacade,
|
channelFacade,
|
||||||
asyncStub,
|
asyncStub,
|
||||||
|
daprHttp,
|
||||||
this.objectSerializer,
|
this.objectSerializer,
|
||||||
this.stateSerializer,
|
this.stateSerializer,
|
||||||
this.resiliencyOptions);
|
this.resiliencyOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates and instance of DaprClient over HTTP.
|
|
||||||
*
|
|
||||||
* @return DaprClient over HTTP.
|
|
||||||
*/
|
|
||||||
private DaprClient buildDaprClientHttp() {
|
|
||||||
return new DaprClientHttp(this.daprHttpBuilder.build(), this.objectSerializer, this.stateSerializer);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -14,7 +14,6 @@ limitations under the License.
|
||||||
package io.dapr.client;
|
package io.dapr.client;
|
||||||
|
|
||||||
import com.google.common.base.Strings;
|
import com.google.common.base.Strings;
|
||||||
import com.google.protobuf.Any;
|
|
||||||
import com.google.protobuf.ByteString;
|
import com.google.protobuf.ByteString;
|
||||||
import com.google.protobuf.Empty;
|
import com.google.protobuf.Empty;
|
||||||
import io.dapr.client.domain.BulkPublishEntry;
|
import io.dapr.client.domain.BulkPublishEntry;
|
||||||
|
@ -48,9 +47,8 @@ import io.dapr.client.domain.UnlockResponseStatus;
|
||||||
import io.dapr.client.domain.UnsubscribeConfigurationRequest;
|
import io.dapr.client.domain.UnsubscribeConfigurationRequest;
|
||||||
import io.dapr.client.domain.UnsubscribeConfigurationResponse;
|
import io.dapr.client.domain.UnsubscribeConfigurationResponse;
|
||||||
import io.dapr.client.resiliency.ResiliencyOptions;
|
import io.dapr.client.resiliency.ResiliencyOptions;
|
||||||
import io.dapr.config.Properties;
|
|
||||||
import io.dapr.exceptions.DaprException;
|
import io.dapr.exceptions.DaprException;
|
||||||
import io.dapr.internal.opencensus.GrpcWrapper;
|
import io.dapr.internal.grpc.DaprClientGrpcInterceptors;
|
||||||
import io.dapr.internal.resiliency.RetryPolicy;
|
import io.dapr.internal.resiliency.RetryPolicy;
|
||||||
import io.dapr.internal.resiliency.TimeoutPolicy;
|
import io.dapr.internal.resiliency.TimeoutPolicy;
|
||||||
import io.dapr.serializer.DaprObjectSerializer;
|
import io.dapr.serializer.DaprObjectSerializer;
|
||||||
|
@ -60,22 +58,20 @@ import io.dapr.utils.TypeRef;
|
||||||
import io.dapr.v1.CommonProtos;
|
import io.dapr.v1.CommonProtos;
|
||||||
import io.dapr.v1.DaprGrpc;
|
import io.dapr.v1.DaprGrpc;
|
||||||
import io.dapr.v1.DaprProtos;
|
import io.dapr.v1.DaprProtos;
|
||||||
import io.grpc.CallOptions;
|
|
||||||
import io.grpc.Channel;
|
import io.grpc.Channel;
|
||||||
import io.grpc.ClientCall;
|
import io.grpc.stub.AbstractStub;
|
||||||
import io.grpc.ClientInterceptor;
|
|
||||||
import io.grpc.ForwardingClientCall;
|
|
||||||
import io.grpc.Metadata;
|
|
||||||
import io.grpc.MethodDescriptor;
|
|
||||||
import io.grpc.stub.StreamObserver;
|
import io.grpc.stub.StreamObserver;
|
||||||
import reactor.core.publisher.Flux;
|
import reactor.core.publisher.Flux;
|
||||||
import reactor.core.publisher.FluxSink;
|
import reactor.core.publisher.FluxSink;
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
import reactor.core.publisher.MonoSink;
|
import reactor.core.publisher.MonoSink;
|
||||||
import reactor.util.context.ContextView;
|
import reactor.util.context.ContextView;
|
||||||
|
import reactor.util.retry.Retry;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.time.Duration;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
@ -83,15 +79,16 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Function;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An adapter for the GRPC Client.
|
* Implementation of the Dapr client combining gRPC and HTTP (when applicable).
|
||||||
*
|
*
|
||||||
* @see io.dapr.v1.DaprGrpc
|
* @see io.dapr.v1.DaprGrpc
|
||||||
* @see io.dapr.client.DaprClient
|
* @see io.dapr.client.DaprClient
|
||||||
*/
|
*/
|
||||||
public class DaprClientGrpc extends AbstractDaprClient {
|
public class DaprClientImpl extends AbstractDaprClient {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The GRPC managed channel to be used.
|
* The GRPC managed channel to be used.
|
||||||
|
@ -114,21 +111,11 @@ public class DaprClientGrpc extends AbstractDaprClient {
|
||||||
private final DaprGrpc.DaprStub asyncStub;
|
private final DaprGrpc.DaprStub asyncStub;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default access level constructor, in order to create an instance of this class use io.dapr.client.DaprClientBuilder
|
* The HTTP client to be used for healthz and HTTP service invocation only.
|
||||||
*
|
*
|
||||||
* @param channel Facade for the managed GRPC channel
|
* @see io.dapr.client.DaprHttp
|
||||||
* @param asyncStub async gRPC stub
|
|
||||||
* @param objectSerializer Serializer for transient request/response objects.
|
|
||||||
* @param stateSerializer Serializer for state objects.
|
|
||||||
* @see DaprClientBuilder
|
|
||||||
*/
|
*/
|
||||||
DaprClientGrpc(
|
private final DaprHttp httpClient;
|
||||||
GrpcChannelFacade channel,
|
|
||||||
DaprGrpc.DaprStub asyncStub,
|
|
||||||
DaprObjectSerializer objectSerializer,
|
|
||||||
DaprObjectSerializer stateSerializer) {
|
|
||||||
this(channel, asyncStub, objectSerializer, stateSerializer, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default access level constructor, in order to create an instance of this class use io.dapr.client.DaprClientBuilder
|
* Default access level constructor, in order to create an instance of this class use io.dapr.client.DaprClientBuilder
|
||||||
|
@ -137,18 +124,39 @@ public class DaprClientGrpc extends AbstractDaprClient {
|
||||||
* @param asyncStub async gRPC stub
|
* @param asyncStub async gRPC stub
|
||||||
* @param objectSerializer Serializer for transient request/response objects.
|
* @param objectSerializer Serializer for transient request/response objects.
|
||||||
* @param stateSerializer Serializer for state objects.
|
* @param stateSerializer Serializer for state objects.
|
||||||
|
* @see DaprClientBuilder
|
||||||
|
*/
|
||||||
|
DaprClientImpl(
|
||||||
|
GrpcChannelFacade channel,
|
||||||
|
DaprGrpc.DaprStub asyncStub,
|
||||||
|
DaprHttp httpClient,
|
||||||
|
DaprObjectSerializer objectSerializer,
|
||||||
|
DaprObjectSerializer stateSerializer) {
|
||||||
|
this(channel, asyncStub, httpClient, objectSerializer, stateSerializer, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default access level constructor, in order to create an instance of this class use io.dapr.client.DaprClientBuilder
|
||||||
|
*
|
||||||
|
* @param channel Facade for the managed GRPC channel
|
||||||
|
* @param asyncStub async gRPC stub
|
||||||
|
* @param httpClient client for http service invocation
|
||||||
|
* @param objectSerializer Serializer for transient request/response objects.
|
||||||
|
* @param stateSerializer Serializer for state objects.
|
||||||
* @param resiliencyOptions Client-level override for resiliency options.
|
* @param resiliencyOptions Client-level override for resiliency options.
|
||||||
* @see DaprClientBuilder
|
* @see DaprClientBuilder
|
||||||
*/
|
*/
|
||||||
DaprClientGrpc(
|
DaprClientImpl(
|
||||||
GrpcChannelFacade channel,
|
GrpcChannelFacade channel,
|
||||||
DaprGrpc.DaprStub asyncStub,
|
DaprGrpc.DaprStub asyncStub,
|
||||||
|
DaprHttp httpClient,
|
||||||
DaprObjectSerializer objectSerializer,
|
DaprObjectSerializer objectSerializer,
|
||||||
DaprObjectSerializer stateSerializer,
|
DaprObjectSerializer stateSerializer,
|
||||||
ResiliencyOptions resiliencyOptions) {
|
ResiliencyOptions resiliencyOptions) {
|
||||||
super(objectSerializer, stateSerializer);
|
super(objectSerializer, stateSerializer);
|
||||||
this.channel = channel;
|
this.channel = channel;
|
||||||
this.asyncStub = intercept(asyncStub);
|
this.asyncStub = asyncStub;
|
||||||
|
this.httpClient = httpClient;
|
||||||
this.timeoutPolicy = new TimeoutPolicy(
|
this.timeoutPolicy = new TimeoutPolicy(
|
||||||
resiliencyOptions == null ? null : resiliencyOptions.getTimeout());
|
resiliencyOptions == null ? null : resiliencyOptions.getTimeout());
|
||||||
this.retryPolicy = new RetryPolicy(
|
this.retryPolicy = new RetryPolicy(
|
||||||
|
@ -177,12 +185,72 @@ public class DaprClientGrpc extends AbstractDaprClient {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public <T extends AbstractStub<T>> T newGrpcStub(String appId, Function<Channel, T> stubBuilder) {
|
||||||
|
// Adds Dapr interceptors to populate gRPC metadata automatically.
|
||||||
|
return DaprClientGrpcInterceptors.intercept(appId, stubBuilder.apply(this.channel.getGrpcChannel()), timeoutPolicy);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Mono<Void> waitForSidecar(int timeoutInMilliseconds) {
|
public Mono<Void> waitForSidecar(int timeoutInMilliseconds) {
|
||||||
return this.channel.waitForChannelReady(timeoutInMilliseconds);
|
String[] pathSegments = new String[] { DaprHttp.API_VERSION, "healthz", "outbound"};
|
||||||
|
int maxRetries = 5;
|
||||||
|
|
||||||
|
Retry retrySpec = Retry
|
||||||
|
.fixedDelay(maxRetries, Duration.ofMillis(500))
|
||||||
|
.doBeforeRetry(retrySignal -> {
|
||||||
|
System.out.println("Retrying component health check...");
|
||||||
|
});
|
||||||
|
|
||||||
|
/*
|
||||||
|
NOTE: (Cassie) Uncomment this once it actually gets implemented:
|
||||||
|
https://github.com/grpc/grpc-java/issues/4359
|
||||||
|
|
||||||
|
int maxChannelStateRetries = 5;
|
||||||
|
|
||||||
|
// Retry logic for checking the channel state
|
||||||
|
Retry channelStateRetrySpec = Retry
|
||||||
|
.fixedDelay(maxChannelStateRetries, Duration.ofMillis(500))
|
||||||
|
.doBeforeRetry(retrySignal -> {
|
||||||
|
System.out.println("Retrying channel state check...");
|
||||||
|
});
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Do the Dapr Http endpoint check to have parity with Dotnet
|
||||||
|
Mono<DaprHttp.Response> responseMono = this.httpClient.invokeApi(DaprHttp.HttpMethods.GET.name(), pathSegments,
|
||||||
|
null, "", null, null);
|
||||||
|
|
||||||
|
return responseMono
|
||||||
|
.retryWhen(retrySpec)
|
||||||
|
/*
|
||||||
|
NOTE: (Cassie) Uncomment this once it actually gets implemented:
|
||||||
|
https://github.com/grpc/grpc-java/issues/4359
|
||||||
|
.flatMap(response -> {
|
||||||
|
// Check the status code
|
||||||
|
int statusCode = response.getStatusCode();
|
||||||
|
|
||||||
|
// Check if the channel's state is READY
|
||||||
|
return Mono.defer(() -> {
|
||||||
|
if (this.channel.getState(true) == ConnectivityState.READY) {
|
||||||
|
// Return true if the status code is in the 2xx range
|
||||||
|
if (statusCode >= 200 && statusCode < 300) {
|
||||||
|
return Mono.empty(); // Continue with the flow
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Mono.error(new RuntimeException("Health check failed"));
|
||||||
|
}).retryWhen(channelStateRetrySpec);
|
||||||
|
})
|
||||||
|
*/
|
||||||
|
.timeout(Duration.ofMillis(timeoutInMilliseconds))
|
||||||
|
.onErrorResume(DaprException.class, e ->
|
||||||
|
Mono.error(new RuntimeException(e)))
|
||||||
|
.switchIfEmpty(DaprException.wrapMono(new RuntimeException("Health check timed out")))
|
||||||
|
.then();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -309,38 +377,63 @@ public class DaprClientGrpc extends AbstractDaprClient {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public <T> Mono<T> invokeMethod(InvokeMethodRequest invokeMethodRequest, TypeRef<T> type) {
|
public <T> Mono<T> invokeMethod(InvokeMethodRequest invokeMethodRequest, TypeRef<T> type) {
|
||||||
try {
|
try {
|
||||||
String appId = invokeMethodRequest.getAppId();
|
final String appId = invokeMethodRequest.getAppId();
|
||||||
String method = invokeMethodRequest.getMethod();
|
final String method = invokeMethodRequest.getMethod();
|
||||||
Object body = invokeMethodRequest.getBody();
|
final Object request = invokeMethodRequest.getBody();
|
||||||
HttpExtension httpExtension = invokeMethodRequest.getHttpExtension();
|
final HttpExtension httpExtension = invokeMethodRequest.getHttpExtension();
|
||||||
DaprProtos.InvokeServiceRequest envelope = buildInvokeServiceRequest(
|
final String contentType = invokeMethodRequest.getContentType();
|
||||||
httpExtension,
|
final Map<String, String> metadata = invokeMethodRequest.getMetadata();
|
||||||
appId,
|
|
||||||
method,
|
|
||||||
body);
|
|
||||||
// Regarding missing metadata in method invocation for gRPC:
|
|
||||||
// gRPC to gRPC does not handle metadata in Dapr runtime proto.
|
|
||||||
// gRPC to HTTP does not map correctly in Dapr runtime as per https://github.com/dapr/dapr/issues/2342
|
|
||||||
|
|
||||||
return Mono.deferContextual(
|
if (httpExtension == null) {
|
||||||
context -> this.<CommonProtos.InvokeResponse>createMono(
|
throw new IllegalArgumentException("HttpExtension cannot be null. Use HttpExtension.NONE instead.");
|
||||||
it -> intercept(context, asyncStub).invokeService(envelope, it)
|
}
|
||||||
)
|
// If the httpExtension is not null, then the method will not be null based on checks in constructor
|
||||||
).flatMap(
|
final String httpMethod = httpExtension.getMethod().toString();
|
||||||
it -> {
|
if (appId == null || appId.trim().isEmpty()) {
|
||||||
try {
|
throw new IllegalArgumentException("App Id cannot be null or empty.");
|
||||||
return Mono.justOrEmpty(objectSerializer.deserialize(it.getData().getValue().toByteArray(), type));
|
}
|
||||||
} catch (IOException e) {
|
if (method == null || method.trim().isEmpty()) {
|
||||||
throw DaprException.propagate(e);
|
throw new IllegalArgumentException("Method name cannot be null or empty.");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
String[] methodSegments = method.split("/");
|
||||||
|
|
||||||
|
List<String> pathSegments = new ArrayList<>(Arrays.asList(DaprHttp.API_VERSION, "invoke", appId, "method"));
|
||||||
|
pathSegments.addAll(Arrays.asList(methodSegments));
|
||||||
|
|
||||||
|
final Map<String, String> headers = new HashMap<>();
|
||||||
|
headers.putAll(httpExtension.getHeaders());
|
||||||
|
if (metadata != null) {
|
||||||
|
headers.putAll(metadata);
|
||||||
|
}
|
||||||
|
byte[] serializedRequestBody = objectSerializer.serialize(request);
|
||||||
|
if (contentType != null && !contentType.isEmpty()) {
|
||||||
|
headers.put(io.dapr.client.domain.Metadata.CONTENT_TYPE, contentType);
|
||||||
|
} else {
|
||||||
|
headers.put(io.dapr.client.domain.Metadata.CONTENT_TYPE, objectSerializer.getContentType());
|
||||||
|
}
|
||||||
|
Mono<DaprHttp.Response> response = Mono.deferContextual(
|
||||||
|
context -> this.httpClient.invokeApi(httpMethod, pathSegments.toArray(new String[0]),
|
||||||
|
httpExtension.getQueryParams(), serializedRequestBody, headers, context)
|
||||||
);
|
);
|
||||||
|
return response.flatMap(r -> getMonoForHttpResponse(type, r));
|
||||||
|
} catch (Exception ex) {
|
||||||
|
return DaprException.wrapMono(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private <T> Mono<T> getMonoForHttpResponse(TypeRef<T> type, DaprHttp.Response r) {
|
||||||
|
try {
|
||||||
|
T object = objectSerializer.deserialize(r.getBody(), type);
|
||||||
|
if (object == null) {
|
||||||
|
return Mono.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
return Mono.just(object);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
return DaprException.wrapMono(ex);
|
return DaprException.wrapMono(ex);
|
||||||
}
|
}
|
||||||
|
@ -673,48 +766,6 @@ public class DaprClientGrpc extends AbstractDaprClient {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Builds the object io.dapr.{@link DaprProtos.InvokeServiceRequest} to be send based on the parameters.
|
|
||||||
*
|
|
||||||
* @param httpExtension Object for HttpExtension
|
|
||||||
* @param appId The application id to be invoked
|
|
||||||
* @param method The application method to be invoked
|
|
||||||
* @param body The body of the request to be send as part of the invocation
|
|
||||||
* @param <K> The Type of the Body
|
|
||||||
* @return The object to be sent as part of the invocation.
|
|
||||||
* @throws IOException If there's an issue serializing the request.
|
|
||||||
*/
|
|
||||||
private <K> DaprProtos.InvokeServiceRequest buildInvokeServiceRequest(
|
|
||||||
HttpExtension httpExtension,
|
|
||||||
String appId,
|
|
||||||
String method,
|
|
||||||
K body) throws IOException {
|
|
||||||
if (httpExtension == null) {
|
|
||||||
throw new IllegalArgumentException("HttpExtension cannot be null. Use HttpExtension.NONE instead.");
|
|
||||||
}
|
|
||||||
CommonProtos.InvokeRequest.Builder requestBuilder = CommonProtos.InvokeRequest.newBuilder();
|
|
||||||
requestBuilder.setMethod(method);
|
|
||||||
if (body != null) {
|
|
||||||
byte[] byteRequest = objectSerializer.serialize(body);
|
|
||||||
Any data = Any.newBuilder().setValue(ByteString.copyFrom(byteRequest)).build();
|
|
||||||
requestBuilder.setData(data);
|
|
||||||
} else {
|
|
||||||
requestBuilder.setData(Any.newBuilder().build());
|
|
||||||
}
|
|
||||||
CommonProtos.HTTPExtension.Builder httpExtensionBuilder = CommonProtos.HTTPExtension.newBuilder();
|
|
||||||
|
|
||||||
httpExtensionBuilder.setVerb(CommonProtos.HTTPExtension.Verb.valueOf(httpExtension.getMethod().toString()))
|
|
||||||
.setQuerystring(httpExtension.encodeQueryString());
|
|
||||||
requestBuilder.setHttpExtension(httpExtensionBuilder.build());
|
|
||||||
|
|
||||||
requestBuilder.setContentType(objectSerializer.getContentType());
|
|
||||||
|
|
||||||
DaprProtos.InvokeServiceRequest.Builder envelopeBuilder = DaprProtos.InvokeServiceRequest.newBuilder()
|
|
||||||
.setId(appId)
|
|
||||||
.setMessage(requestBuilder.build());
|
|
||||||
return envelopeBuilder.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
|
@ -963,12 +1014,15 @@ public class DaprClientGrpc extends AbstractDaprClient {
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void close() throws Exception {
|
public void close() throws Exception {
|
||||||
if (channel != null) {
|
DaprException.wrap(() -> {
|
||||||
DaprException.wrap(() -> {
|
if (channel != null) {
|
||||||
channel.close();
|
channel.close();
|
||||||
return true;
|
}
|
||||||
}).call();
|
if (httpClient != null) {
|
||||||
}
|
httpClient.close();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}).call();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1054,7 +1108,7 @@ public class DaprClientGrpc extends AbstractDaprClient {
|
||||||
|
|
||||||
DaprProtos.SubscribeConfigurationRequest envelope = builder.build();
|
DaprProtos.SubscribeConfigurationRequest envelope = builder.build();
|
||||||
return this.<DaprProtos.SubscribeConfigurationResponse>createFlux(
|
return this.<DaprProtos.SubscribeConfigurationResponse>createFlux(
|
||||||
it -> intercept(asyncStub).subscribeConfiguration(envelope, it)
|
it -> intercept(null, asyncStub).subscribeConfiguration(envelope, it)
|
||||||
).map(
|
).map(
|
||||||
it -> {
|
it -> {
|
||||||
Map<String, ConfigurationItem> configMap = new HashMap<>();
|
Map<String, ConfigurationItem> configMap = new HashMap<>();
|
||||||
|
@ -1094,7 +1148,7 @@ public class DaprClientGrpc extends AbstractDaprClient {
|
||||||
DaprProtos.UnsubscribeConfigurationRequest envelope = builder.build();
|
DaprProtos.UnsubscribeConfigurationRequest envelope = builder.build();
|
||||||
|
|
||||||
return this.<DaprProtos.UnsubscribeConfigurationResponse>createMono(
|
return this.<DaprProtos.UnsubscribeConfigurationResponse>createMono(
|
||||||
it -> intercept(asyncStub).unsubscribeConfiguration(envelope, it)
|
it -> intercept(null, asyncStub).unsubscribeConfiguration(envelope, it)
|
||||||
).map(
|
).map(
|
||||||
it -> new UnsubscribeConfigurationResponse(it.getOk(), it.getMessage())
|
it -> new UnsubscribeConfigurationResponse(it.getOk(), it.getMessage())
|
||||||
);
|
);
|
||||||
|
@ -1119,35 +1173,6 @@ public class DaprClientGrpc extends AbstractDaprClient {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Populates GRPC client with interceptors.
|
|
||||||
*
|
|
||||||
* @param client GRPC client for Dapr.
|
|
||||||
* @return Client after adding interceptors.
|
|
||||||
*/
|
|
||||||
private DaprGrpc.DaprStub intercept(DaprGrpc.DaprStub client) {
|
|
||||||
ClientInterceptor interceptor = new ClientInterceptor() {
|
|
||||||
@Override
|
|
||||||
public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(
|
|
||||||
MethodDescriptor<ReqT, RespT> methodDescriptor,
|
|
||||||
CallOptions options,
|
|
||||||
Channel channel) {
|
|
||||||
ClientCall<ReqT, RespT> clientCall = channel.newCall(methodDescriptor, timeoutPolicy.apply(options));
|
|
||||||
return new ForwardingClientCall.SimpleForwardingClientCall<ReqT, RespT>(clientCall) {
|
|
||||||
@Override
|
|
||||||
public void start(final Listener<RespT> responseListener, final Metadata metadata) {
|
|
||||||
String daprApiToken = Properties.API_TOKEN.get();
|
|
||||||
if (daprApiToken != null) {
|
|
||||||
metadata.put(Metadata.Key.of(Headers.DAPR_API_TOKEN, Metadata.ASCII_STRING_MARSHALLER), daprApiToken);
|
|
||||||
}
|
|
||||||
super.start(responseListener, metadata);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return client.withInterceptors(interceptor);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Populates GRPC client with interceptors for telemetry.
|
* Populates GRPC client with interceptors for telemetry.
|
||||||
*
|
*
|
||||||
|
@ -1155,8 +1180,8 @@ public class DaprClientGrpc extends AbstractDaprClient {
|
||||||
* @param client GRPC client for Dapr.
|
* @param client GRPC client for Dapr.
|
||||||
* @return Client after adding interceptors.
|
* @return Client after adding interceptors.
|
||||||
*/
|
*/
|
||||||
private static DaprGrpc.DaprStub intercept(ContextView context, DaprGrpc.DaprStub client) {
|
private DaprGrpc.DaprStub intercept(ContextView context, DaprGrpc.DaprStub client) {
|
||||||
return GrpcWrapper.intercept(context, client);
|
return DaprClientGrpcInterceptors.intercept(client, this.timeoutPolicy, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
private <T> Mono<T> createMono(Consumer<StreamObserver<T>> consumer) {
|
private <T> Mono<T> createMono(Consumer<StreamObserver<T>> consumer) {
|
|
@ -1,608 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2021 The Dapr 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.dapr.client;
|
|
||||||
|
|
||||||
import io.dapr.client.domain.ConfigurationItem;
|
|
||||||
import io.dapr.client.domain.DeleteStateRequest;
|
|
||||||
import io.dapr.client.domain.ExecuteStateTransactionRequest;
|
|
||||||
import io.dapr.client.domain.GetBulkSecretRequest;
|
|
||||||
import io.dapr.client.domain.GetBulkStateRequest;
|
|
||||||
import io.dapr.client.domain.GetConfigurationRequest;
|
|
||||||
import io.dapr.client.domain.GetSecretRequest;
|
|
||||||
import io.dapr.client.domain.GetStateRequest;
|
|
||||||
import io.dapr.client.domain.HttpExtension;
|
|
||||||
import io.dapr.client.domain.InvokeBindingRequest;
|
|
||||||
import io.dapr.client.domain.InvokeMethodRequest;
|
|
||||||
import io.dapr.client.domain.PublishEventRequest;
|
|
||||||
import io.dapr.client.domain.SaveStateRequest;
|
|
||||||
import io.dapr.client.domain.State;
|
|
||||||
import io.dapr.client.domain.StateOptions;
|
|
||||||
import io.dapr.client.domain.SubscribeConfigurationRequest;
|
|
||||||
import io.dapr.client.domain.SubscribeConfigurationResponse;
|
|
||||||
import io.dapr.client.domain.TransactionalStateOperation;
|
|
||||||
import io.dapr.client.domain.UnsubscribeConfigurationRequest;
|
|
||||||
import io.dapr.client.domain.UnsubscribeConfigurationResponse;
|
|
||||||
import io.dapr.utils.TypeRef;
|
|
||||||
import reactor.core.publisher.Flux;
|
|
||||||
import reactor.core.publisher.Mono;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class that delegates to other implementations.
|
|
||||||
* @deprecated This class will be deleted at SDK release version 1.10.
|
|
||||||
* @see DaprClient
|
|
||||||
* @see DaprClientGrpc
|
|
||||||
* @see DaprClientHttp
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
class DaprClientProxy implements DaprClient {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Client for all API invocations.
|
|
||||||
*/
|
|
||||||
private final DaprClient client;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Client to override Dapr's service invocation APIs.
|
|
||||||
*/
|
|
||||||
private final DaprClient methodInvocationOverrideClient;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor with delegate client.
|
|
||||||
*
|
|
||||||
* @param client Client for all API invocations.
|
|
||||||
* @see DaprClientBuilder
|
|
||||||
*/
|
|
||||||
DaprClientProxy(DaprClient client) {
|
|
||||||
this(client, client);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor with delegate client and override client for Dapr's method invocation APIs.
|
|
||||||
*
|
|
||||||
* @param client Client for all API invocations, except override below.
|
|
||||||
* @param methodInvocationOverrideClient Client to override Dapr's service invocation APIs.
|
|
||||||
* @see DaprClientBuilder
|
|
||||||
*/
|
|
||||||
DaprClientProxy(
|
|
||||||
DaprClient client,
|
|
||||||
DaprClient methodInvocationOverrideClient) {
|
|
||||||
this.client = client;
|
|
||||||
this.methodInvocationOverrideClient = methodInvocationOverrideClient;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Mono<Void> waitForSidecar(int timeoutInMilliseconds) {
|
|
||||||
return client.waitForSidecar(timeoutInMilliseconds);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Mono<Void> publishEvent(String pubsubName, String topicName, Object data) {
|
|
||||||
return client.publishEvent(pubsubName, topicName, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Mono<Void> publishEvent(String pubsubName, String topicName, Object data, Map<String, String> metadata) {
|
|
||||||
return client.publishEvent(pubsubName, topicName, data, metadata);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Mono<Void> publishEvent(PublishEventRequest request) {
|
|
||||||
return client.publishEvent(request);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public <T> Mono<T> invokeMethod(String appId,
|
|
||||||
String methodName,
|
|
||||||
Object data,
|
|
||||||
HttpExtension httpExtension,
|
|
||||||
Map<String, String> metadata,
|
|
||||||
TypeRef<T> type) {
|
|
||||||
return methodInvocationOverrideClient.invokeMethod(appId, methodName, data, httpExtension, metadata, type);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public <T> Mono<T> invokeMethod(String appId,
|
|
||||||
String methodName,
|
|
||||||
Object request,
|
|
||||||
HttpExtension httpExtension,
|
|
||||||
Map<String, String> metadata,
|
|
||||||
Class<T> clazz) {
|
|
||||||
return methodInvocationOverrideClient.invokeMethod(appId, methodName, request, httpExtension, metadata, clazz);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public <T> Mono<T> invokeMethod(String appId,
|
|
||||||
String methodName,
|
|
||||||
Object request,
|
|
||||||
HttpExtension httpExtension,
|
|
||||||
TypeRef<T> type) {
|
|
||||||
return methodInvocationOverrideClient.invokeMethod(appId, methodName, request, httpExtension, type);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public <T> Mono<T> invokeMethod(String appId,
|
|
||||||
String methodName,
|
|
||||||
Object request,
|
|
||||||
HttpExtension httpExtension,
|
|
||||||
Class<T> clazz) {
|
|
||||||
return methodInvocationOverrideClient.invokeMethod(appId, methodName, request, httpExtension, clazz);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public <T> Mono<T> invokeMethod(String appId,
|
|
||||||
String methodName,
|
|
||||||
HttpExtension httpExtension,
|
|
||||||
Map<String, String> metadata,
|
|
||||||
TypeRef<T> type) {
|
|
||||||
return methodInvocationOverrideClient.invokeMethod(appId, methodName, httpExtension, metadata, type);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public <T> Mono<T> invokeMethod(String appId,
|
|
||||||
String methodName,
|
|
||||||
HttpExtension httpExtension,
|
|
||||||
Map<String, String> metadata,
|
|
||||||
Class<T> clazz) {
|
|
||||||
return methodInvocationOverrideClient.invokeMethod(appId, methodName, httpExtension, metadata, clazz);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Mono<Void> invokeMethod(String appId,
|
|
||||||
String methodName,
|
|
||||||
Object request,
|
|
||||||
HttpExtension httpExtension,
|
|
||||||
Map<String, String> metadata) {
|
|
||||||
return methodInvocationOverrideClient.invokeMethod(appId, methodName, request, httpExtension, metadata);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Mono<Void> invokeMethod(String appId, String methodName, Object request, HttpExtension httpExtension) {
|
|
||||||
return methodInvocationOverrideClient.invokeMethod(appId, methodName, request, httpExtension);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Mono<Void> invokeMethod(String appId,
|
|
||||||
String methodName,
|
|
||||||
HttpExtension httpExtension,
|
|
||||||
Map<String, String> metadata) {
|
|
||||||
return methodInvocationOverrideClient.invokeMethod(appId, methodName, httpExtension, metadata);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Mono<byte[]> invokeMethod(String appId,
|
|
||||||
String methodName,
|
|
||||||
byte[] request,
|
|
||||||
HttpExtension httpExtension,
|
|
||||||
Map<String, String> metadata) {
|
|
||||||
return methodInvocationOverrideClient.invokeMethod(appId, methodName, request, httpExtension, metadata);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public <T> Mono<T> invokeMethod(InvokeMethodRequest invokeMethodRequest, TypeRef<T> type) {
|
|
||||||
return methodInvocationOverrideClient.invokeMethod(invokeMethodRequest, type);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Mono<Void> invokeBinding(String bindingName, String operation, Object data) {
|
|
||||||
return client.invokeBinding(bindingName, operation, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Mono<byte[]> invokeBinding(String bindingName, String operation, byte[] data, Map<String, String> metadata) {
|
|
||||||
return client.invokeBinding(bindingName, operation, data, metadata);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public <T> Mono<T> invokeBinding(String bindingName, String operation, Object data, TypeRef<T> type) {
|
|
||||||
return client.invokeBinding(bindingName, operation, data, type);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public <T> Mono<T> invokeBinding(String bindingName, String operation, Object data, Class<T> clazz) {
|
|
||||||
return client.invokeBinding(bindingName, operation, data, clazz);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public <T> Mono<T> invokeBinding(String bindingName,
|
|
||||||
String operation,
|
|
||||||
Object data,
|
|
||||||
Map<String, String> metadata,
|
|
||||||
TypeRef<T> type) {
|
|
||||||
return client.invokeBinding(bindingName, operation, data, metadata, type);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public <T> Mono<T> invokeBinding(String bindingName,
|
|
||||||
String operation,
|
|
||||||
Object data,
|
|
||||||
Map<String, String> metadata,
|
|
||||||
Class<T> clazz) {
|
|
||||||
return client.invokeBinding(bindingName, operation, data, metadata, clazz);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public <T> Mono<T> invokeBinding(InvokeBindingRequest request, TypeRef<T> type) {
|
|
||||||
return client.invokeBinding(request, type);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public <T> Mono<State<T>> getState(String storeName, State<T> state, TypeRef<T> type) {
|
|
||||||
return client.getState(storeName, state, type);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public <T> Mono<State<T>> getState(String storeName, State<T> state, Class<T> clazz) {
|
|
||||||
return client.getState(storeName, state, clazz);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public <T> Mono<State<T>> getState(String storeName, String key, TypeRef<T> type) {
|
|
||||||
return client.getState(storeName, key, type);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public <T> Mono<State<T>> getState(String storeName, String key, Class<T> clazz) {
|
|
||||||
return client.getState(storeName, key, clazz);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public <T> Mono<State<T>> getState(String storeName, String key, StateOptions options, TypeRef<T> type) {
|
|
||||||
return client.getState(storeName, key, options, type);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public <T> Mono<State<T>> getState(String storeName, String key, StateOptions options, Class<T> clazz) {
|
|
||||||
return client.getState(storeName, key, options, clazz);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public <T> Mono<State<T>> getState(GetStateRequest request, TypeRef<T> type) {
|
|
||||||
return client.getState(request, type);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public <T> Mono<List<State<T>>> getBulkState(String storeName, List<String> keys, TypeRef<T> type) {
|
|
||||||
return client.getBulkState(storeName, keys, type);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public <T> Mono<List<State<T>>> getBulkState(String storeName, List<String> keys, Class<T> clazz) {
|
|
||||||
return client.getBulkState(storeName, keys, clazz);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public <T> Mono<List<State<T>>> getBulkState(GetBulkStateRequest request, TypeRef<T> type) {
|
|
||||||
return client.getBulkState(request, type);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Mono<Void> executeStateTransaction(String storeName, List<TransactionalStateOperation<?>> operations) {
|
|
||||||
return client.executeStateTransaction(storeName, operations);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Mono<Void> executeStateTransaction(ExecuteStateTransactionRequest request) {
|
|
||||||
return client.executeStateTransaction(request);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Mono<Void> saveBulkState(String storeName, List<State<?>> states) {
|
|
||||||
return client.saveBulkState(storeName, states);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Mono<Void> saveBulkState(SaveStateRequest request) {
|
|
||||||
return client.saveBulkState(request);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Mono<Void> saveState(String storeName, String key, Object value) {
|
|
||||||
return client.saveState(storeName, key, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Mono<Void> saveState(String storeName, String key, String etag, Object value, StateOptions options) {
|
|
||||||
return client.saveState(storeName, key, etag, value, options);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Mono<Void> deleteState(String storeName, String key) {
|
|
||||||
return client.deleteState(storeName, key);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Mono<Void> deleteState(String storeName, String key, String etag, StateOptions options) {
|
|
||||||
return client.deleteState(storeName, key, etag, options);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Mono<Void> deleteState(DeleteStateRequest request) {
|
|
||||||
return client.deleteState(request);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Mono<Map<String, String>> getSecret(String storeName, String secretName, Map<String, String> metadata) {
|
|
||||||
return client.getSecret(storeName, secretName, metadata);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Mono<Map<String, String>> getSecret(String storeName, String secretName) {
|
|
||||||
return client.getSecret(storeName, secretName);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Mono<Map<String, String>> getSecret(GetSecretRequest request) {
|
|
||||||
return client.getSecret(request);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Mono<Map<String, Map<String, String>>> getBulkSecret(String storeName) {
|
|
||||||
return client.getBulkSecret(storeName);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Mono<Map<String, Map<String, String>>> getBulkSecret(String storeName, Map<String, String> metadata) {
|
|
||||||
return client.getBulkSecret(storeName, metadata);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Mono<Map<String, Map<String, String>>> getBulkSecret(GetBulkSecretRequest request) {
|
|
||||||
return client.getBulkSecret(request);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Mono<ConfigurationItem> getConfiguration(String storeName, String key) {
|
|
||||||
return client.getConfiguration(storeName, key);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Mono<ConfigurationItem> getConfiguration(String storeName, String key, Map<String, String> metadata) {
|
|
||||||
return client.getConfiguration(storeName, key, metadata);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Mono<Map<String, ConfigurationItem>> getConfiguration(String storeName, String... keys) {
|
|
||||||
return client.getConfiguration(storeName, keys);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Mono<Map<String, ConfigurationItem>> getConfiguration(String storeName, List<String> keys,
|
|
||||||
Map<String, String> metadata) {
|
|
||||||
return client.getConfiguration(storeName, keys, metadata);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Mono<Map<String, ConfigurationItem>> getConfiguration(GetConfigurationRequest request) {
|
|
||||||
return client.getConfiguration(request);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Flux<SubscribeConfigurationResponse> subscribeConfiguration(String storeName, String... keys) {
|
|
||||||
return client.subscribeConfiguration(storeName, keys);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Flux<SubscribeConfigurationResponse> subscribeConfiguration(String storeName, List<String> keys,
|
|
||||||
Map<String, String> metadata) {
|
|
||||||
return client.subscribeConfiguration(storeName, keys, metadata);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Flux<SubscribeConfigurationResponse> subscribeConfiguration(SubscribeConfigurationRequest request) {
|
|
||||||
return client.subscribeConfiguration(request);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Mono<UnsubscribeConfigurationResponse> unsubscribeConfiguration(String id, String storeName) {
|
|
||||||
return client.unsubscribeConfiguration(id, storeName);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Mono<UnsubscribeConfigurationResponse> unsubscribeConfiguration(UnsubscribeConfigurationRequest request) {
|
|
||||||
return client.unsubscribeConfiguration(request);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void close() throws Exception {
|
|
||||||
client.close();
|
|
||||||
if (client != methodInvocationOverrideClient) {
|
|
||||||
methodInvocationOverrideClient.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Mono<Void> shutdown() {
|
|
||||||
return client.shutdown();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -23,9 +23,7 @@ import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A builder for the DaprHttp.
|
* A builder for the DaprHttp.
|
||||||
* @deprecated Use {@link DaprClientBuilder} instead, this will be removed in a future release.
|
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
|
||||||
public class DaprHttpBuilder {
|
public class DaprHttpBuilder {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2024 The Dapr 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.dapr.client;
|
||||||
|
|
||||||
|
import io.grpc.CallOptions;
|
||||||
|
import io.grpc.Channel;
|
||||||
|
import io.grpc.ClientCall;
|
||||||
|
import io.grpc.ClientInterceptor;
|
||||||
|
import io.grpc.MethodDescriptor;
|
||||||
|
import reactor.util.context.ContextView;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Injects tracing headers to gRPC metadata.
|
||||||
|
*/
|
||||||
|
public class DaprTracingInterceptor implements ClientInterceptor {
|
||||||
|
|
||||||
|
private final io.dapr.internal.grpc.interceptors.DaprTracingInterceptor delegate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an instance of the injector for gRPC context from Reactor's context.
|
||||||
|
* @param context Reactor's context
|
||||||
|
*/
|
||||||
|
public DaprTracingInterceptor(ContextView context) {
|
||||||
|
this.delegate = new io.dapr.internal.grpc.interceptors.DaprTracingInterceptor(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(
|
||||||
|
MethodDescriptor<ReqT, RespT> methodDescriptor,
|
||||||
|
CallOptions callOptions,
|
||||||
|
Channel channel) {
|
||||||
|
return this.delegate.interceptCall(methodDescriptor, callOptions, channel);
|
||||||
|
}
|
||||||
|
}
|
|
@ -13,18 +13,11 @@ limitations under the License.
|
||||||
|
|
||||||
package io.dapr.client;
|
package io.dapr.client;
|
||||||
|
|
||||||
import io.dapr.config.Properties;
|
|
||||||
import io.dapr.exceptions.DaprException;
|
|
||||||
import io.dapr.v1.DaprGrpc;
|
import io.dapr.v1.DaprGrpc;
|
||||||
import io.grpc.ConnectivityState;
|
|
||||||
import io.grpc.ManagedChannel;
|
import io.grpc.ManagedChannel;
|
||||||
import okhttp3.OkHttpClient;
|
|
||||||
import reactor.core.publisher.Mono;
|
|
||||||
import reactor.util.retry.Retry;
|
|
||||||
|
|
||||||
import java.io.Closeable;
|
import java.io.Closeable;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.time.Duration;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Facade for common operations on gRPC channel.
|
* Facade for common operations on gRPC channel.
|
||||||
|
@ -39,11 +32,6 @@ class GrpcChannelFacade implements Closeable {
|
||||||
*/
|
*/
|
||||||
private final ManagedChannel channel;
|
private final ManagedChannel channel;
|
||||||
|
|
||||||
/**
|
|
||||||
* The reference to the DaprHttp client.
|
|
||||||
*/
|
|
||||||
private final DaprHttp daprHttp;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default access level constructor, in order to create an instance of this class use io.dapr.client.DaprClientBuilder
|
* Default access level constructor, in order to create an instance of this class use io.dapr.client.DaprClientBuilder
|
||||||
|
@ -51,75 +39,23 @@ class GrpcChannelFacade implements Closeable {
|
||||||
* @param channel A Managed GRPC channel
|
* @param channel A Managed GRPC channel
|
||||||
* @see DaprClientBuilder
|
* @see DaprClientBuilder
|
||||||
*/
|
*/
|
||||||
GrpcChannelFacade(ManagedChannel channel, DaprHttp daprHttp) {
|
GrpcChannelFacade(ManagedChannel channel) {
|
||||||
this.channel = channel;
|
this.channel = channel;
|
||||||
this.daprHttp = daprHttp;
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the gRPC channel to the sidecar.
|
||||||
|
* @return Sidecar's gRPC channel.
|
||||||
|
*/
|
||||||
|
ManagedChannel getGrpcChannel() {
|
||||||
|
return this.channel;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() throws IOException {
|
public void close() throws IOException {
|
||||||
if (daprHttp != null) {
|
|
||||||
daprHttp.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (channel != null && !channel.isShutdown()) {
|
if (channel != null && !channel.isShutdown()) {
|
||||||
channel.shutdown();
|
channel.shutdown();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Mono<Void> waitForChannelReady(int timeoutInMilliseconds) {
|
|
||||||
String[] pathSegments = new String[] { DaprHttp.API_VERSION, "healthz", "outbound"};
|
|
||||||
int maxRetries = 5;
|
|
||||||
|
|
||||||
Retry retrySpec = Retry
|
|
||||||
.fixedDelay(maxRetries, Duration.ofMillis(500))
|
|
||||||
.doBeforeRetry(retrySignal -> {
|
|
||||||
System.out.println("Retrying component health check...");
|
|
||||||
});
|
|
||||||
|
|
||||||
/*
|
|
||||||
NOTE: (Cassie) Uncomment this once it actually gets implemented:
|
|
||||||
https://github.com/grpc/grpc-java/issues/4359
|
|
||||||
|
|
||||||
int maxChannelStateRetries = 5;
|
|
||||||
|
|
||||||
// Retry logic for checking the channel state
|
|
||||||
Retry channelStateRetrySpec = Retry
|
|
||||||
.fixedDelay(maxChannelStateRetries, Duration.ofMillis(500))
|
|
||||||
.doBeforeRetry(retrySignal -> {
|
|
||||||
System.out.println("Retrying channel state check...");
|
|
||||||
});
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Do the Dapr Http endpoint check to have parity with Dotnet
|
|
||||||
Mono<DaprHttp.Response> responseMono = this.daprHttp.invokeApi(DaprHttp.HttpMethods.GET.name(), pathSegments,
|
|
||||||
null, "", null, null);
|
|
||||||
|
|
||||||
return responseMono
|
|
||||||
.retryWhen(retrySpec)
|
|
||||||
/*
|
|
||||||
NOTE: (Cassie) Uncomment this once it actually gets implemented:
|
|
||||||
https://github.com/grpc/grpc-java/issues/4359
|
|
||||||
.flatMap(response -> {
|
|
||||||
// Check the status code
|
|
||||||
int statusCode = response.getStatusCode();
|
|
||||||
|
|
||||||
// Check if the channel's state is READY
|
|
||||||
return Mono.defer(() -> {
|
|
||||||
if (this.channel.getState(true) == ConnectivityState.READY) {
|
|
||||||
// Return true if the status code is in the 2xx range
|
|
||||||
if (statusCode >= 200 && statusCode < 300) {
|
|
||||||
return Mono.empty(); // Continue with the flow
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Mono.error(new RuntimeException("Health check failed"));
|
|
||||||
}).retryWhen(channelStateRetrySpec);
|
|
||||||
})
|
|
||||||
*/
|
|
||||||
.timeout(Duration.ofMillis(timeoutInMilliseconds))
|
|
||||||
.onErrorResume(DaprException.class, e ->
|
|
||||||
Mono.error(new RuntimeException(e)))
|
|
||||||
.switchIfEmpty(DaprException.wrapMono(new RuntimeException("Health check timed out")))
|
|
||||||
.then();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,6 @@ package io.dapr.client.domain;
|
||||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,6 @@ limitations under the License.
|
||||||
package io.dapr.client.domain;
|
package io.dapr.client.domain;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -13,7 +13,6 @@ limitations under the License.
|
||||||
|
|
||||||
package io.dapr.config;
|
package io.dapr.config;
|
||||||
|
|
||||||
import io.dapr.client.DaprApiProtocol;
|
|
||||||
import io.dapr.utils.NetworkUtils;
|
import io.dapr.utils.NetworkUtils;
|
||||||
|
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
|
@ -50,16 +49,6 @@ public class Properties {
|
||||||
*/
|
*/
|
||||||
private static final Duration DEFAULT_API_TIMEOUT = Duration.ofMillis(0L);
|
private static final Duration DEFAULT_API_TIMEOUT = Duration.ofMillis(0L);
|
||||||
|
|
||||||
/**
|
|
||||||
* Dapr's default use of gRPC or HTTP.
|
|
||||||
*/
|
|
||||||
private static final DaprApiProtocol DEFAULT_API_PROTOCOL = DaprApiProtocol.GRPC;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Dapr's default use of gRPC or HTTP for Dapr's method invocation APIs.
|
|
||||||
*/
|
|
||||||
private static final DaprApiProtocol DEFAULT_API_METHOD_INVOCATION_PROTOCOL = DaprApiProtocol.HTTP;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dapr's default String encoding: UTF-8.
|
* Dapr's default String encoding: UTF-8.
|
||||||
*/
|
*/
|
||||||
|
@ -143,28 +132,6 @@ public class Properties {
|
||||||
"DAPR_API_TIMEOUT_MILLISECONDS",
|
"DAPR_API_TIMEOUT_MILLISECONDS",
|
||||||
DEFAULT_API_TIMEOUT);
|
DEFAULT_API_TIMEOUT);
|
||||||
|
|
||||||
/**
|
|
||||||
* Determines if Dapr client will use gRPC or HTTP to talk to Dapr's side car.
|
|
||||||
* @deprecated This attribute will be deleted at SDK version 1.10.
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public static final Property<DaprApiProtocol> API_PROTOCOL = new GenericProperty<>(
|
|
||||||
"dapr.api.protocol",
|
|
||||||
"DAPR_API_PROTOCOL",
|
|
||||||
DEFAULT_API_PROTOCOL,
|
|
||||||
(s) -> DaprApiProtocol.valueOf(s.toUpperCase()));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Determines if Dapr client should use gRPC or HTTP for Dapr's service method invocation APIs.
|
|
||||||
* @deprecated This attribute will be deleted at SDK version 1.10.
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public static final Property<DaprApiProtocol> API_METHOD_INVOCATION_PROTOCOL = new GenericProperty<>(
|
|
||||||
"dapr.api.methodInvocation.protocol",
|
|
||||||
"DAPR_API_METHOD_INVOCATION_PROTOCOL",
|
|
||||||
DEFAULT_API_METHOD_INVOCATION_PROTOCOL,
|
|
||||||
(s) -> DaprApiProtocol.valueOf(s.toUpperCase()));
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* API token for authentication between App and Dapr's side car.
|
* API token for authentication between App and Dapr's side car.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -0,0 +1,139 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2024 The Dapr 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.dapr.internal.grpc;
|
||||||
|
|
||||||
|
import io.dapr.internal.grpc.interceptors.DaprApiTokenInterceptor;
|
||||||
|
import io.dapr.internal.grpc.interceptors.DaprAppIdInterceptor;
|
||||||
|
import io.dapr.internal.grpc.interceptors.DaprTimeoutInterceptor;
|
||||||
|
import io.dapr.internal.grpc.interceptors.DaprTracingInterceptor;
|
||||||
|
import io.dapr.internal.resiliency.TimeoutPolicy;
|
||||||
|
import io.grpc.stub.AbstractStub;
|
||||||
|
import reactor.util.context.ContextView;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class to be used as part of your service's client stub interceptor.
|
||||||
|
* Usage: myClientStub = DaprClientGrpcInterceptors.intercept(myClientStub);
|
||||||
|
*/
|
||||||
|
public class DaprClientGrpcInterceptors {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds all Dapr interceptors to a gRPC async stub.
|
||||||
|
* @param appId the appId to be invoked
|
||||||
|
* @param client gRPC client
|
||||||
|
* @param <T> async client type
|
||||||
|
* @return async client instance with interceptors
|
||||||
|
*/
|
||||||
|
public static <T extends AbstractStub<T>> T intercept(final String appId, final T client) {
|
||||||
|
return intercept(appId, client, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds all Dapr interceptors to a gRPC async stub.
|
||||||
|
* @param client gRPC client
|
||||||
|
* @param <T> async client type
|
||||||
|
* @return async client instance with interceptors
|
||||||
|
*/
|
||||||
|
public static <T extends AbstractStub<T>> T intercept(final T client) {
|
||||||
|
return intercept(null, client, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds all Dapr interceptors to a gRPC async stub.
|
||||||
|
* @param appId the appId to be invoked
|
||||||
|
* @param client gRPC client
|
||||||
|
* @param timeoutPolicy timeout policy for gRPC call
|
||||||
|
* @param <T> async client type
|
||||||
|
* @return async client instance with interceptors
|
||||||
|
*/
|
||||||
|
public static <T extends AbstractStub<T>> T intercept(
|
||||||
|
final String appId, final T client, final TimeoutPolicy timeoutPolicy) {
|
||||||
|
return intercept(appId, client, timeoutPolicy, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds all Dapr interceptors to a gRPC async stub.
|
||||||
|
* @param client gRPC client
|
||||||
|
* @param timeoutPolicy timeout policy for gRPC call
|
||||||
|
* @param <T> async client type
|
||||||
|
* @return async client instance with interceptors
|
||||||
|
*/
|
||||||
|
public static <T extends AbstractStub<T>> T intercept(final T client, final TimeoutPolicy timeoutPolicy) {
|
||||||
|
return intercept(null, client, timeoutPolicy, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds all Dapr interceptors to a gRPC async stub.
|
||||||
|
* @param appId the appId to be invoked
|
||||||
|
* @param client gRPC client
|
||||||
|
* @param context Reactor context for tracing
|
||||||
|
* @param <T> async client type
|
||||||
|
* @return async client instance with interceptors
|
||||||
|
*/
|
||||||
|
public static <T extends AbstractStub<T>> T intercept(
|
||||||
|
final String appId, final T client, final ContextView context) {
|
||||||
|
return intercept(appId, client, null, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds all Dapr interceptors to a gRPC async stub.
|
||||||
|
* @param client gRPC client
|
||||||
|
* @param context Reactor context for tracing
|
||||||
|
* @param <T> async client type
|
||||||
|
* @return async client instance with interceptors
|
||||||
|
*/
|
||||||
|
public static <T extends AbstractStub<T>> T intercept(final T client, final ContextView context) {
|
||||||
|
return intercept(null, client, null, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds all Dapr interceptors to a gRPC async stub.
|
||||||
|
* @param client gRPC client
|
||||||
|
* @param timeoutPolicy timeout policy for gRPC call
|
||||||
|
* @param context Reactor context for tracing
|
||||||
|
* @param <T> async client type
|
||||||
|
* @return async client instance with interceptors
|
||||||
|
*/
|
||||||
|
public static <T extends AbstractStub<T>> T intercept(
|
||||||
|
final T client,
|
||||||
|
final TimeoutPolicy timeoutPolicy,
|
||||||
|
final ContextView context) {
|
||||||
|
return intercept(null, client, timeoutPolicy, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds all Dapr interceptors to a gRPC async stub.
|
||||||
|
* @param appId the appId to be invoked
|
||||||
|
* @param client gRPC client
|
||||||
|
* @param timeoutPolicy timeout policy for gRPC call
|
||||||
|
* @param context Reactor context for tracing
|
||||||
|
* @param <T> async client type
|
||||||
|
* @return async client instance with interceptors
|
||||||
|
*/
|
||||||
|
public static <T extends AbstractStub<T>> T intercept(
|
||||||
|
final String appId,
|
||||||
|
final T client,
|
||||||
|
final TimeoutPolicy timeoutPolicy,
|
||||||
|
final ContextView context) {
|
||||||
|
if (client == null) {
|
||||||
|
throw new IllegalArgumentException("client cannot be null");
|
||||||
|
}
|
||||||
|
|
||||||
|
return client.withInterceptors(
|
||||||
|
new DaprAppIdInterceptor(appId),
|
||||||
|
new DaprApiTokenInterceptor(),
|
||||||
|
new DaprTimeoutInterceptor(timeoutPolicy),
|
||||||
|
new DaprTracingInterceptor(context));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2024 The Dapr 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.dapr.internal.grpc.interceptors;
|
||||||
|
|
||||||
|
import io.dapr.client.Headers;
|
||||||
|
import io.dapr.config.Properties;
|
||||||
|
import io.grpc.CallOptions;
|
||||||
|
import io.grpc.Channel;
|
||||||
|
import io.grpc.ClientCall;
|
||||||
|
import io.grpc.ClientInterceptor;
|
||||||
|
import io.grpc.ForwardingClientCall;
|
||||||
|
import io.grpc.Metadata;
|
||||||
|
import io.grpc.MethodDescriptor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class to be used as part of your service's client stub interceptor to include Dapr tokens.
|
||||||
|
*/
|
||||||
|
public class DaprApiTokenInterceptor implements ClientInterceptor {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(
|
||||||
|
MethodDescriptor<ReqT, RespT> methodDescriptor,
|
||||||
|
CallOptions options,
|
||||||
|
Channel channel) {
|
||||||
|
ClientCall<ReqT, RespT> clientCall = channel.newCall(methodDescriptor, options);
|
||||||
|
return new ForwardingClientCall.SimpleForwardingClientCall<>(clientCall) {
|
||||||
|
@Override
|
||||||
|
public void start(final Listener<RespT> responseListener, final Metadata metadata) {
|
||||||
|
String daprApiToken = Properties.API_TOKEN.get();
|
||||||
|
if (daprApiToken != null) {
|
||||||
|
metadata.put(Metadata.Key.of(Headers.DAPR_API_TOKEN, Metadata.ASCII_STRING_MARSHALLER), daprApiToken);
|
||||||
|
}
|
||||||
|
super.start(responseListener, metadata);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,63 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2024 The Dapr 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.dapr.internal.grpc.interceptors;
|
||||||
|
|
||||||
|
import io.grpc.CallOptions;
|
||||||
|
import io.grpc.Channel;
|
||||||
|
import io.grpc.ClientCall;
|
||||||
|
import io.grpc.ClientInterceptor;
|
||||||
|
import io.grpc.ForwardingClientCall;
|
||||||
|
import io.grpc.Metadata;
|
||||||
|
import io.grpc.MethodDescriptor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class to be used as part of your service's client stub interceptor to include Dapr App Id metadata.
|
||||||
|
*/
|
||||||
|
public class DaprAppIdInterceptor implements ClientInterceptor {
|
||||||
|
|
||||||
|
private final Metadata extraHeaders;
|
||||||
|
|
||||||
|
public DaprAppIdInterceptor(String appId) {
|
||||||
|
this.extraHeaders = buildMetadata(appId);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final Metadata buildMetadata(String appId) {
|
||||||
|
if (appId == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Metadata headers = new Metadata();
|
||||||
|
headers.put(Metadata.Key.of("dapr-app-id", Metadata.ASCII_STRING_MARSHALLER), appId);
|
||||||
|
return headers;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(
|
||||||
|
MethodDescriptor<ReqT, RespT> methodDescriptor,
|
||||||
|
CallOptions options,
|
||||||
|
Channel channel) {
|
||||||
|
ClientCall<ReqT, RespT> clientCall = channel.newCall(methodDescriptor, options);
|
||||||
|
final Metadata extraHeaders = this.extraHeaders;
|
||||||
|
return new ForwardingClientCall.SimpleForwardingClientCall<>(clientCall) {
|
||||||
|
@Override
|
||||||
|
public void start(ClientCall.Listener<RespT> responseListener, Metadata headers) {
|
||||||
|
if (extraHeaders != null) {
|
||||||
|
headers.merge(extraHeaders);
|
||||||
|
}
|
||||||
|
super.start(responseListener, headers);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2024 The Dapr 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.dapr.internal.grpc.interceptors;
|
||||||
|
|
||||||
|
import io.dapr.internal.resiliency.TimeoutPolicy;
|
||||||
|
import io.grpc.CallOptions;
|
||||||
|
import io.grpc.Channel;
|
||||||
|
import io.grpc.ClientCall;
|
||||||
|
import io.grpc.ClientInterceptor;
|
||||||
|
import io.grpc.MethodDescriptor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class to be used as part of your service's client stub interceptor to include timeout.
|
||||||
|
*/
|
||||||
|
public class DaprTimeoutInterceptor implements ClientInterceptor {
|
||||||
|
|
||||||
|
private final TimeoutPolicy timeoutPolicy;
|
||||||
|
|
||||||
|
public DaprTimeoutInterceptor(TimeoutPolicy timeoutPolicy) {
|
||||||
|
this.timeoutPolicy = timeoutPolicy;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(
|
||||||
|
MethodDescriptor<ReqT, RespT> methodDescriptor,
|
||||||
|
CallOptions options,
|
||||||
|
Channel channel) {
|
||||||
|
if (timeoutPolicy == null) {
|
||||||
|
return channel.newCall(methodDescriptor, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
return channel.newCall(methodDescriptor, timeoutPolicy.apply(options));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2024 The Dapr 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.dapr.internal.grpc.interceptors;
|
||||||
|
|
||||||
|
import io.dapr.internal.opencensus.GrpcHelper;
|
||||||
|
import io.grpc.CallOptions;
|
||||||
|
import io.grpc.Channel;
|
||||||
|
import io.grpc.ClientCall;
|
||||||
|
import io.grpc.ClientInterceptor;
|
||||||
|
import io.grpc.ForwardingClientCall;
|
||||||
|
import io.grpc.Metadata;
|
||||||
|
import io.grpc.MethodDescriptor;
|
||||||
|
import reactor.util.context.ContextView;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Injects tracing headers to gRPC metadata.
|
||||||
|
*/
|
||||||
|
public class DaprTracingInterceptor implements ClientInterceptor {
|
||||||
|
|
||||||
|
private final ContextView context;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an instance of the injector for gRPC context from Reactor's context.
|
||||||
|
* @param context Reactor's context
|
||||||
|
*/
|
||||||
|
public DaprTracingInterceptor(ContextView context) {
|
||||||
|
this.context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(
|
||||||
|
MethodDescriptor<ReqT, RespT> methodDescriptor,
|
||||||
|
CallOptions callOptions,
|
||||||
|
Channel channel) {
|
||||||
|
ClientCall<ReqT, RespT> clientCall = channel.newCall(methodDescriptor, callOptions);
|
||||||
|
return new ForwardingClientCall.SimpleForwardingClientCall<>(clientCall) {
|
||||||
|
@Override
|
||||||
|
public void start(final Listener<RespT> responseListener, final Metadata metadata) {
|
||||||
|
if (context != null) {
|
||||||
|
GrpcHelper.populateMetadata(context, metadata);
|
||||||
|
}
|
||||||
|
super.start(responseListener, metadata);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,96 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2021 The Dapr 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.dapr.internal.opencensus;
|
||||||
|
|
||||||
|
import io.grpc.Metadata;
|
||||||
|
import reactor.util.context.Context;
|
||||||
|
import reactor.util.context.ContextView;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper to extract tracing information for gRPC calls.
|
||||||
|
*/
|
||||||
|
public final class GrpcHelper {
|
||||||
|
|
||||||
|
private static final Logger LOGGER = Logger.getLogger(GrpcHelper.class.getName());
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Binary formatter to generate grpc-trace-bin.
|
||||||
|
*/
|
||||||
|
private static final BinaryFormatImpl OPENCENSUS_BINARY_FORMAT = new BinaryFormatImpl();
|
||||||
|
|
||||||
|
private static final Metadata.Key<byte[]> GRPC_TRACE_BIN_KEY =
|
||||||
|
Metadata.Key.of("grpc-trace-bin", Metadata.BINARY_BYTE_MARSHALLER);
|
||||||
|
|
||||||
|
private static final Metadata.Key<String> TRACEPARENT_KEY =
|
||||||
|
Metadata.Key.of("traceparent", Metadata.ASCII_STRING_MARSHALLER);
|
||||||
|
|
||||||
|
private static final Metadata.Key<String> TRACESTATE_KEY =
|
||||||
|
Metadata.Key.of("tracestate", Metadata.ASCII_STRING_MARSHALLER);
|
||||||
|
|
||||||
|
private GrpcHelper() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Populates GRPC client's metadata with tracing headers.
|
||||||
|
*
|
||||||
|
* @param context Reactor's context.
|
||||||
|
* @param metadata GRPC client metadata to be populated.
|
||||||
|
*/
|
||||||
|
public static void populateMetadata(final ContextView context, final Metadata metadata) {
|
||||||
|
Map<String, Object> map = (context == null ? Context.empty() : context)
|
||||||
|
.stream()
|
||||||
|
.filter(e -> (e.getKey() != null) && (e.getValue() != null))
|
||||||
|
.collect(Collectors.toMap(e -> e.getKey().toString(), e -> e.getValue()));
|
||||||
|
if (map.containsKey(GRPC_TRACE_BIN_KEY.name())) {
|
||||||
|
byte[] value = (byte[]) map.get(GRPC_TRACE_BIN_KEY.name());
|
||||||
|
metadata.put(GRPC_TRACE_BIN_KEY, value);
|
||||||
|
}
|
||||||
|
if (map.containsKey(TRACEPARENT_KEY.name())) {
|
||||||
|
String value = map.get(TRACEPARENT_KEY.name()).toString();
|
||||||
|
metadata.put(TRACEPARENT_KEY, value);
|
||||||
|
}
|
||||||
|
if (map.containsKey(TRACESTATE_KEY.name())) {
|
||||||
|
String value = map.get(TRACESTATE_KEY.name()).toString();
|
||||||
|
metadata.put(TRACESTATE_KEY, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dapr only supports "grpc-trace-bin" for GRPC and OpenTelemetry SDK does not support that yet:
|
||||||
|
// https://github.com/open-telemetry/opentelemetry-specification/issues/639
|
||||||
|
// This should be the only use of OpenCensus SDK: populate "grpc-trace-bin".
|
||||||
|
SpanContext opencensusSpanContext = extractOpenCensusSpanContext(metadata);
|
||||||
|
if (opencensusSpanContext != null) {
|
||||||
|
byte[] grpcTraceBin = OPENCENSUS_BINARY_FORMAT.toByteArray(opencensusSpanContext);
|
||||||
|
metadata.put(GRPC_TRACE_BIN_KEY, grpcTraceBin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static SpanContext extractOpenCensusSpanContext(Metadata metadata) {
|
||||||
|
if (!metadata.keys().contains(TRACEPARENT_KEY.name())) {
|
||||||
|
// Trying to extract context without this key will throw an "expected" exception, so we avoid it here.
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return TraceContextFormat.extract(metadata);
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
LOGGER.log(Level.FINE, "Could not extract span context.", e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,122 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2021 The Dapr 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.dapr.internal.opencensus;
|
|
||||||
|
|
||||||
import io.dapr.config.Property;
|
|
||||||
import io.dapr.v1.DaprGrpc;
|
|
||||||
import io.grpc.CallOptions;
|
|
||||||
import io.grpc.Channel;
|
|
||||||
import io.grpc.ClientCall;
|
|
||||||
import io.grpc.ClientInterceptor;
|
|
||||||
import io.grpc.ForwardingClientCall;
|
|
||||||
import io.grpc.Metadata;
|
|
||||||
import io.grpc.MethodDescriptor;
|
|
||||||
import reactor.util.context.Context;
|
|
||||||
import reactor.util.context.ContextView;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.logging.Level;
|
|
||||||
import java.util.logging.Logger;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wraps a Dapr gRPC stub with telemetry interceptor.
|
|
||||||
*/
|
|
||||||
public final class GrpcWrapper {
|
|
||||||
|
|
||||||
private static final Logger LOGGER = Logger.getLogger(Property.class.getName());
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Binary formatter to generate grpc-trace-bin.
|
|
||||||
*/
|
|
||||||
private static final BinaryFormatImpl OPENCENSUS_BINARY_FORMAT = new BinaryFormatImpl();
|
|
||||||
|
|
||||||
private static final Metadata.Key<byte[]> GRPC_TRACE_BIN_KEY =
|
|
||||||
Metadata.Key.of("grpc-trace-bin", Metadata.BINARY_BYTE_MARSHALLER);
|
|
||||||
|
|
||||||
private static final Metadata.Key<String> TRACEPARENT_KEY =
|
|
||||||
Metadata.Key.of("traceparent", Metadata.ASCII_STRING_MARSHALLER);
|
|
||||||
|
|
||||||
private static final Metadata.Key<String> TRACESTATE_KEY =
|
|
||||||
Metadata.Key.of("tracestate", Metadata.ASCII_STRING_MARSHALLER);
|
|
||||||
|
|
||||||
private GrpcWrapper() {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Populates GRPC client with interceptors.
|
|
||||||
*
|
|
||||||
* @param context Reactor's context.
|
|
||||||
* @param client GRPC client for Dapr.
|
|
||||||
* @return Client after adding interceptors.
|
|
||||||
*/
|
|
||||||
public static DaprGrpc.DaprStub intercept(final ContextView context, DaprGrpc.DaprStub client) {
|
|
||||||
ClientInterceptor interceptor = new ClientInterceptor() {
|
|
||||||
@Override
|
|
||||||
public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(
|
|
||||||
MethodDescriptor<ReqT, RespT> methodDescriptor,
|
|
||||||
CallOptions callOptions,
|
|
||||||
Channel channel) {
|
|
||||||
ClientCall<ReqT, RespT> clientCall = channel.newCall(methodDescriptor, callOptions);
|
|
||||||
return new ForwardingClientCall.SimpleForwardingClientCall<ReqT, RespT>(clientCall) {
|
|
||||||
@Override
|
|
||||||
public void start(final Listener<RespT> responseListener, final Metadata metadata) {
|
|
||||||
Map<String, Object> map = (context == null ? Context.empty() : context)
|
|
||||||
.stream()
|
|
||||||
.filter(e -> (e.getKey() != null) && (e.getValue() != null))
|
|
||||||
.collect(Collectors.toMap(e -> e.getKey().toString(), e -> e.getValue()));
|
|
||||||
if (map.containsKey(GRPC_TRACE_BIN_KEY.name())) {
|
|
||||||
byte[] value = (byte[]) map.get(GRPC_TRACE_BIN_KEY.name());
|
|
||||||
metadata.put(GRPC_TRACE_BIN_KEY, value);
|
|
||||||
}
|
|
||||||
if (map.containsKey(TRACEPARENT_KEY.name())) {
|
|
||||||
String value = map.get(TRACEPARENT_KEY.name()).toString();
|
|
||||||
metadata.put(TRACEPARENT_KEY, value);
|
|
||||||
}
|
|
||||||
if (map.containsKey(TRACESTATE_KEY.name())) {
|
|
||||||
String value = map.get(TRACESTATE_KEY.name()).toString();
|
|
||||||
metadata.put(TRACESTATE_KEY, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Dapr only supports "grpc-trace-bin" for GRPC and OpenTelemetry SDK does not support that yet:
|
|
||||||
// https://github.com/open-telemetry/opentelemetry-specification/issues/639
|
|
||||||
// This should be the only use of OpenCensus SDK: populate "grpc-trace-bin".
|
|
||||||
SpanContext opencensusSpanContext = extractOpenCensusSpanContext(metadata);
|
|
||||||
if (opencensusSpanContext != null) {
|
|
||||||
byte[] grpcTraceBin = OPENCENSUS_BINARY_FORMAT.toByteArray(opencensusSpanContext);
|
|
||||||
metadata.put(GRPC_TRACE_BIN_KEY, grpcTraceBin);
|
|
||||||
}
|
|
||||||
|
|
||||||
super.start(responseListener, metadata);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return client.withInterceptors(interceptor);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static SpanContext extractOpenCensusSpanContext(Metadata metadata) {
|
|
||||||
if (!metadata.keys().contains(TRACEPARENT_KEY.name())) {
|
|
||||||
// Trying to extract context without this key will throw an "expected" exception, so we avoid it here.
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
return TraceContextFormat.extract(metadata);
|
|
||||||
} catch (RuntimeException e) {
|
|
||||||
LOGGER.log(Level.FINE, "Could not extract span context.", e);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -13,8 +13,6 @@ limitations under the License.
|
||||||
|
|
||||||
package io.dapr.utils;
|
package io.dapr.utils;
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.JavaType;
|
|
||||||
|
|
||||||
import java.lang.reflect.ParameterizedType;
|
import java.lang.reflect.ParameterizedType;
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
|
|
||||||
|
|
|
@ -15,11 +15,8 @@ package io.dapr.client;
|
||||||
|
|
||||||
import io.dapr.client.domain.CloudEvent;
|
import io.dapr.client.domain.CloudEvent;
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
|
|
||||||
public class CloudEventCustom<T> extends CloudEvent<T> {
|
public class CloudEventCustom<T> extends CloudEvent<T> {
|
||||||
|
|
||||||
|
|
|
@ -13,16 +13,15 @@ limitations under the License.
|
||||||
|
|
||||||
package io.dapr.client;
|
package io.dapr.client;
|
||||||
|
|
||||||
|
import io.dapr.serializer.DaprObjectSerializer;
|
||||||
|
import io.dapr.serializer.DefaultObjectSerializer;
|
||||||
|
import io.dapr.utils.TypeRef;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
|
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||||
|
|
||||||
import io.dapr.serializer.DaprObjectSerializer;
|
|
||||||
import io.dapr.serializer.DefaultObjectSerializer;
|
|
||||||
import io.dapr.utils.TypeRef;
|
|
||||||
|
|
||||||
public class CloudEventCustomTest {
|
public class CloudEventCustomTest {
|
||||||
|
|
||||||
private DaprObjectSerializer serializer = new DefaultObjectSerializer();
|
private DaprObjectSerializer serializer = new DefaultObjectSerializer();
|
||||||
|
|
|
@ -16,7 +16,6 @@ package io.dapr.client;
|
||||||
import io.dapr.serializer.DaprObjectSerializer;
|
import io.dapr.serializer.DaprObjectSerializer;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertNotEquals;
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
|
|
|
@ -15,10 +15,10 @@ package io.dapr.client;
|
||||||
|
|
||||||
import io.dapr.client.domain.HttpExtension;
|
import io.dapr.client.domain.HttpExtension;
|
||||||
import io.dapr.client.domain.InvokeMethodRequest;
|
import io.dapr.client.domain.InvokeMethodRequest;
|
||||||
import io.dapr.serializer.DefaultObjectSerializer;
|
import io.dapr.internal.grpc.DaprClientGrpcInterceptors;
|
||||||
import io.dapr.utils.TypeRef;
|
|
||||||
import io.dapr.v1.CommonProtos;
|
import io.dapr.v1.CommonProtos;
|
||||||
import io.dapr.v1.DaprGrpc;
|
import io.dapr.v1.DaprGrpc;
|
||||||
|
import io.dapr.v1.DaprProtos;
|
||||||
import io.grpc.ManagedChannel;
|
import io.grpc.ManagedChannel;
|
||||||
import io.grpc.Metadata;
|
import io.grpc.Metadata;
|
||||||
import io.grpc.ServerCall;
|
import io.grpc.ServerCall;
|
||||||
|
@ -28,6 +28,7 @@ import io.grpc.ServerInterceptors;
|
||||||
import io.grpc.ServerServiceDefinition;
|
import io.grpc.ServerServiceDefinition;
|
||||||
import io.grpc.inprocess.InProcessChannelBuilder;
|
import io.grpc.inprocess.InProcessChannelBuilder;
|
||||||
import io.grpc.inprocess.InProcessServerBuilder;
|
import io.grpc.inprocess.InProcessServerBuilder;
|
||||||
|
import io.grpc.stub.StreamObserver;
|
||||||
import io.grpc.testing.GrpcCleanupRule;
|
import io.grpc.testing.GrpcCleanupRule;
|
||||||
import org.junit.Rule;
|
import org.junit.Rule;
|
||||||
import org.junit.jupiter.api.AfterEach;
|
import org.junit.jupiter.api.AfterEach;
|
||||||
|
@ -36,15 +37,16 @@ import org.junit.jupiter.migrationsupport.rules.EnableRuleMigrationSupport;
|
||||||
import org.junit.jupiter.params.ParameterizedTest;
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
import org.junit.jupiter.params.provider.Arguments;
|
import org.junit.jupiter.params.provider.Arguments;
|
||||||
import org.junit.jupiter.params.provider.MethodSource;
|
import org.junit.jupiter.params.provider.MethodSource;
|
||||||
import org.mockito.Mockito;
|
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
|
import reactor.core.publisher.MonoSink;
|
||||||
import reactor.util.context.Context;
|
import reactor.util.context.Context;
|
||||||
|
import reactor.util.context.ContextView;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.function.Consumer;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import reactor.util.context.ContextView;
|
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||||
|
|
||||||
|
@ -67,6 +69,8 @@ public class DaprClientGrpcTelemetryTest {
|
||||||
@Rule
|
@Rule
|
||||||
public final GrpcCleanupRule grpcCleanup = new GrpcCleanupRule();
|
public final GrpcCleanupRule grpcCleanup = new GrpcCleanupRule();
|
||||||
|
|
||||||
|
private DaprGrpc.DaprStub daprStub;
|
||||||
|
|
||||||
private DaprClient client;
|
private DaprClient client;
|
||||||
|
|
||||||
@AfterEach
|
@AfterEach
|
||||||
|
@ -144,10 +148,7 @@ null,
|
||||||
|
|
||||||
// Create a client channel and register for automatic graceful shutdown.
|
// Create a client channel and register for automatic graceful shutdown.
|
||||||
ManagedChannel channel = InProcessChannelBuilder.forName(serverName).directExecutor().build();
|
ManagedChannel channel = InProcessChannelBuilder.forName(serverName).directExecutor().build();
|
||||||
DaprGrpc.DaprStub asyncStub = DaprGrpc.newStub(channel);
|
daprStub = DaprGrpc.newStub(channel);
|
||||||
DaprHttp daprHTTP = Mockito.mock(DaprHttp.class);
|
|
||||||
client = new DaprClientGrpc(
|
|
||||||
new GrpcChannelFacade(channel, daprHTTP), asyncStub, new DefaultObjectSerializer(), new DefaultObjectSerializer());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setup() throws IOException {
|
public void setup() throws IOException {
|
||||||
|
@ -184,11 +185,7 @@ null,
|
||||||
|
|
||||||
// Create a client channel and register for automatic graceful shutdown.
|
// Create a client channel and register for automatic graceful shutdown.
|
||||||
ManagedChannel channel = InProcessChannelBuilder.forName(serverName).directExecutor().build();
|
ManagedChannel channel = InProcessChannelBuilder.forName(serverName).directExecutor().build();
|
||||||
DaprGrpc.DaprStub asyncStub = DaprGrpc.newStub(channel);
|
this.daprStub = DaprGrpc.newStub(channel);
|
||||||
|
|
||||||
DaprHttp daprHTTP = Mockito.mock(DaprHttp.class);
|
|
||||||
client = new DaprClientGrpc(
|
|
||||||
new GrpcChannelFacade(channel, daprHTTP), asyncStub, new DefaultObjectSerializer(), new DefaultObjectSerializer());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -214,10 +211,7 @@ null,
|
||||||
}
|
}
|
||||||
|
|
||||||
final Context contextCopy = context;
|
final Context contextCopy = context;
|
||||||
InvokeMethodRequest req = new InvokeMethodRequest("appId", "method")
|
Mono<Void> result = this.invoke()
|
||||||
.setBody("request")
|
|
||||||
.setHttpExtension(HttpExtension.NONE);
|
|
||||||
Mono<Void> result = this.client.invokeMethod(req, TypeRef.get(Void.class))
|
|
||||||
.contextWrite(it -> it.putAll(contextCopy));
|
.contextWrite(it -> it.putAll(contextCopy));
|
||||||
result.block();
|
result.block();
|
||||||
}
|
}
|
||||||
|
@ -233,8 +227,42 @@ null,
|
||||||
InvokeMethodRequest req = new InvokeMethodRequest("appId", "method")
|
InvokeMethodRequest req = new InvokeMethodRequest("appId", "method")
|
||||||
.setBody("request")
|
.setBody("request")
|
||||||
.setHttpExtension(HttpExtension.NONE);
|
.setHttpExtension(HttpExtension.NONE);
|
||||||
Mono<Void> result = this.client.invokeMethod(req, TypeRef.get(Void.class))
|
Mono<Void> result = this.invoke()
|
||||||
.contextWrite(it -> it.putAll(contextCopy == null ? (ContextView) Context.empty() : contextCopy));
|
.contextWrite(it -> it.putAll(contextCopy == null ? (ContextView) Context.empty() : contextCopy));
|
||||||
result.block();
|
result.block();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Mono<Void> invoke() {
|
||||||
|
DaprProtos.InvokeServiceRequest req =
|
||||||
|
DaprProtos.InvokeServiceRequest.newBuilder()
|
||||||
|
.build();
|
||||||
|
return Mono.deferContextual(
|
||||||
|
context -> this.<CommonProtos.InvokeResponse>createMono(
|
||||||
|
it -> DaprClientGrpcInterceptors.intercept(daprStub, context).invokeService(req, it)
|
||||||
|
)
|
||||||
|
).then();
|
||||||
|
}
|
||||||
|
|
||||||
|
private <T> Mono<T> createMono(Consumer<StreamObserver<T>> consumer) {
|
||||||
|
return Mono.create(sink -> consumer.accept(createStreamObserver(sink)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private <T> StreamObserver<T> createStreamObserver(MonoSink<T> sink) {
|
||||||
|
return new StreamObserver<T>() {
|
||||||
|
@Override
|
||||||
|
public void onNext(T value) {
|
||||||
|
sink.success(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError(Throwable t) {
|
||||||
|
sink.error(new ExecutionException(t));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCompleted() {
|
||||||
|
sink.success();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,6 @@ import io.dapr.client.domain.DeleteStateRequest;
|
||||||
import io.dapr.client.domain.ExecuteStateTransactionRequest;
|
import io.dapr.client.domain.ExecuteStateTransactionRequest;
|
||||||
import io.dapr.client.domain.GetBulkStateRequest;
|
import io.dapr.client.domain.GetBulkStateRequest;
|
||||||
import io.dapr.client.domain.GetStateRequest;
|
import io.dapr.client.domain.GetStateRequest;
|
||||||
import io.dapr.client.domain.HttpExtension;
|
|
||||||
import io.dapr.client.domain.PublishEventRequest;
|
import io.dapr.client.domain.PublishEventRequest;
|
||||||
import io.dapr.client.domain.State;
|
import io.dapr.client.domain.State;
|
||||||
import io.dapr.client.domain.StateOptions;
|
import io.dapr.client.domain.StateOptions;
|
||||||
|
@ -45,7 +44,6 @@ import org.junit.jupiter.api.Test;
|
||||||
import org.mockito.ArgumentCaptor;
|
import org.mockito.ArgumentCaptor;
|
||||||
import org.mockito.ArgumentMatcher;
|
import org.mockito.ArgumentMatcher;
|
||||||
import org.mockito.ArgumentMatchers;
|
import org.mockito.ArgumentMatchers;
|
||||||
import org.mockito.Mockito;
|
|
||||||
import org.mockito.stubbing.Answer;
|
import org.mockito.stubbing.Answer;
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
|
@ -63,7 +61,6 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static io.dapr.utils.TestUtils.assertThrowsDaprException;
|
import static io.dapr.utils.TestUtils.assertThrowsDaprException;
|
||||||
import static io.dapr.utils.TestUtils.findFreePort;
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
|
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||||
|
@ -72,7 +69,12 @@ import static org.junit.jupiter.api.Assertions.assertNull;
|
||||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
import static org.mockito.Mockito.*;
|
import static org.mockito.Mockito.argThat;
|
||||||
|
import static org.mockito.Mockito.doAnswer;
|
||||||
|
import static org.mockito.Mockito.doNothing;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
public class DaprClientGrpcTest {
|
public class DaprClientGrpcTest {
|
||||||
|
|
||||||
|
@ -84,6 +86,7 @@ public class DaprClientGrpcTest {
|
||||||
|
|
||||||
private GrpcChannelFacade channel;
|
private GrpcChannelFacade channel;
|
||||||
private DaprGrpc.DaprStub daprStub;
|
private DaprGrpc.DaprStub daprStub;
|
||||||
|
private DaprHttp daprHttp;
|
||||||
private DaprClient client;
|
private DaprClient client;
|
||||||
private ObjectSerializer serializer;
|
private ObjectSerializer serializer;
|
||||||
|
|
||||||
|
@ -91,10 +94,10 @@ public class DaprClientGrpcTest {
|
||||||
public void setup() throws IOException {
|
public void setup() throws IOException {
|
||||||
channel = mock(GrpcChannelFacade.class);
|
channel = mock(GrpcChannelFacade.class);
|
||||||
daprStub = mock(DaprGrpc.DaprStub.class);
|
daprStub = mock(DaprGrpc.DaprStub.class);
|
||||||
|
daprHttp = mock(DaprHttp.class);
|
||||||
when(daprStub.withInterceptors(any())).thenReturn(daprStub);
|
when(daprStub.withInterceptors(any())).thenReturn(daprStub);
|
||||||
DaprClient grpcClient = new DaprClientGrpc(
|
client = new DaprClientImpl(
|
||||||
channel, daprStub, new DefaultObjectSerializer(), new DefaultObjectSerializer());
|
channel, daprStub, daprHttp, new DefaultObjectSerializer(), new DefaultObjectSerializer());
|
||||||
client = new DaprClientProxy(grpcClient);
|
|
||||||
serializer = new ObjectSerializer();
|
serializer = new ObjectSerializer();
|
||||||
doNothing().when(channel).close();
|
doNothing().when(channel).close();
|
||||||
}
|
}
|
||||||
|
@ -105,18 +108,6 @@ public class DaprClientGrpcTest {
|
||||||
verify(channel).close();
|
verify(channel).close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void waitForSidecarTimeout() {
|
|
||||||
Mockito.doReturn(Mono.error(new RuntimeException())).when(channel).waitForChannelReady(1);
|
|
||||||
assertThrows(RuntimeException.class, () -> client.waitForSidecar(1).block());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void waitForSidecarOK() {
|
|
||||||
Mockito.doReturn(Mono.empty()).when(channel).waitForChannelReady(10000);
|
|
||||||
client.waitForSidecar(10000).block();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void publishEventExceptionThrownTest() {
|
public void publishEventExceptionThrownTest() {
|
||||||
doAnswer((Answer<Void>) invocation -> {
|
doAnswer((Answer<Void>) invocation -> {
|
||||||
|
@ -150,7 +141,7 @@ public class DaprClientGrpcTest {
|
||||||
@Test
|
@Test
|
||||||
public void publishEventSerializeException() throws IOException {
|
public void publishEventSerializeException() throws IOException {
|
||||||
DaprObjectSerializer mockSerializer = mock(DaprObjectSerializer.class);
|
DaprObjectSerializer mockSerializer = mock(DaprObjectSerializer.class);
|
||||||
client = new DaprClientGrpc(channel, daprStub, mockSerializer, new DefaultObjectSerializer());
|
client = new DaprClientImpl(channel, daprStub, daprHttp, mockSerializer, new DefaultObjectSerializer());
|
||||||
doAnswer((Answer<Void>) invocation -> {
|
doAnswer((Answer<Void>) invocation -> {
|
||||||
StreamObserver<Empty> observer = (StreamObserver<Empty>) invocation.getArguments()[1];
|
StreamObserver<Empty> observer = (StreamObserver<Empty>) invocation.getArguments()[1];
|
||||||
observer.onNext(Empty.getDefaultInstance());
|
observer.onNext(Empty.getDefaultInstance());
|
||||||
|
@ -268,7 +259,7 @@ public class DaprClientGrpcTest {
|
||||||
@Test
|
@Test
|
||||||
public void invokeBindingSerializeException() throws IOException {
|
public void invokeBindingSerializeException() throws IOException {
|
||||||
DaprObjectSerializer mockSerializer = mock(DaprObjectSerializer.class);
|
DaprObjectSerializer mockSerializer = mock(DaprObjectSerializer.class);
|
||||||
client = new DaprClientGrpc(channel, daprStub, mockSerializer, new DefaultObjectSerializer());
|
client = new DaprClientImpl(channel, daprStub, daprHttp, mockSerializer, new DefaultObjectSerializer());
|
||||||
doAnswer((Answer<Void>) invocation -> {
|
doAnswer((Answer<Void>) invocation -> {
|
||||||
StreamObserver<Empty> observer = (StreamObserver<Empty>) invocation.getArguments()[1];
|
StreamObserver<Empty> observer = (StreamObserver<Empty>) invocation.getArguments()[1];
|
||||||
observer.onNext(Empty.getDefaultInstance());
|
observer.onNext(Empty.getDefaultInstance());
|
||||||
|
@ -419,440 +410,6 @@ public class DaprClientGrpcTest {
|
||||||
assertFalse(called.get());
|
assertFalse(called.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void invokeServiceVoidExceptionThrownTest() {
|
|
||||||
doAnswer((Answer<Void>) invocation -> {
|
|
||||||
throw new RuntimeException();
|
|
||||||
}).when(daprStub).invokeService(any(DaprProtos.InvokeServiceRequest.class), any());
|
|
||||||
|
|
||||||
Mono<Void> result = client.invokeMethod("appId", "method", "request", HttpExtension.NONE);
|
|
||||||
|
|
||||||
assertThrowsDaprException(
|
|
||||||
RuntimeException.class,
|
|
||||||
"UNKNOWN",
|
|
||||||
"UNKNOWN: ",
|
|
||||||
() -> result.block());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void invokeServiceIllegalArgumentExceptionThrownTest() {
|
|
||||||
doAnswer((Answer<Void>) invocation -> {
|
|
||||||
StreamObserver<CommonProtos.InvokeResponse> observer = (StreamObserver<CommonProtos.InvokeResponse>) invocation.getArguments()[1];
|
|
||||||
observer.onNext(CommonProtos.InvokeResponse.newBuilder().setData(getAny("Value")).build());
|
|
||||||
observer.onCompleted();
|
|
||||||
return null;
|
|
||||||
}).when(daprStub).invokeService(any(DaprProtos.InvokeServiceRequest.class), any());
|
|
||||||
|
|
||||||
// HttpExtension cannot be null
|
|
||||||
Mono<Void> result = client.invokeMethod("appId", "method", "request", null);
|
|
||||||
|
|
||||||
assertThrows(IllegalArgumentException.class, () -> result.block());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void invokeServiceEmptyRequestVoidExceptionThrownTest() {
|
|
||||||
doAnswer((Answer<Void>) invocation -> {
|
|
||||||
throw new RuntimeException();
|
|
||||||
}).when(daprStub).invokeService(any(DaprProtos.InvokeServiceRequest.class), any());
|
|
||||||
|
|
||||||
Mono<Void> result = client.invokeMethod("appId", "method", HttpExtension.NONE, (Map<String, String>)null);
|
|
||||||
|
|
||||||
assertThrowsDaprException(
|
|
||||||
RuntimeException.class,
|
|
||||||
"UNKNOWN",
|
|
||||||
"UNKNOWN: ",
|
|
||||||
() -> result.block());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void invokeServiceVoidCallbackExceptionThrownTest() {
|
|
||||||
RuntimeException ex = new RuntimeException("An Exception");
|
|
||||||
doAnswer((Answer<Void>) invocation -> {
|
|
||||||
StreamObserver<CommonProtos.InvokeResponse> observer = (StreamObserver<CommonProtos.InvokeResponse>) invocation.getArguments()[1];
|
|
||||||
observer.onError(ex);
|
|
||||||
return null;
|
|
||||||
}).when(daprStub).invokeService(any(DaprProtos.InvokeServiceRequest.class), any());
|
|
||||||
|
|
||||||
Mono<Void> result = client.invokeMethod("appId", "method", "request", HttpExtension.NONE);
|
|
||||||
|
|
||||||
assertThrowsDaprException(
|
|
||||||
ExecutionException.class,
|
|
||||||
"UNKNOWN",
|
|
||||||
"UNKNOWN: java.lang.RuntimeException: An Exception",
|
|
||||||
() -> result.block());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void invokeServiceVoidTest() {
|
|
||||||
doAnswer((Answer<Void>) invocation -> {
|
|
||||||
StreamObserver<CommonProtos.InvokeResponse> observer = (StreamObserver<CommonProtos.InvokeResponse>) invocation.getArguments()[1];
|
|
||||||
observer.onNext(CommonProtos.InvokeResponse.newBuilder().setData(getAny("Value")).build());
|
|
||||||
observer.onCompleted();
|
|
||||||
return null;
|
|
||||||
}).when(daprStub).invokeService(any(DaprProtos.InvokeServiceRequest.class), any());
|
|
||||||
|
|
||||||
Mono<Void> result = client.invokeMethod("appId", "method", "request", HttpExtension.NONE);
|
|
||||||
result.block();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void invokeServiceVoidObjectTest() {
|
|
||||||
doAnswer((Answer<Void>) invocation -> {
|
|
||||||
StreamObserver<CommonProtos.InvokeResponse> observer = (StreamObserver<CommonProtos.InvokeResponse>) invocation.getArguments()[1];
|
|
||||||
observer.onNext(CommonProtos.InvokeResponse.newBuilder().setData(getAny("Value")).build());
|
|
||||||
observer.onCompleted();
|
|
||||||
return null;
|
|
||||||
}).when(daprStub).invokeService(any(DaprProtos.InvokeServiceRequest.class), any());
|
|
||||||
|
|
||||||
MyObject request = new MyObject(1, "Event");
|
|
||||||
Mono<Void> result = client.invokeMethod("appId", "method", request, HttpExtension.NONE);
|
|
||||||
result.block();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void invokeServiceExceptionThrownTest() {
|
|
||||||
doAnswer((Answer<Void>) invocation -> {
|
|
||||||
throw new RuntimeException();
|
|
||||||
}).when(daprStub).invokeService(any(DaprProtos.InvokeServiceRequest.class), any());
|
|
||||||
|
|
||||||
Mono<String> result = client.invokeMethod("appId", "method", "request", HttpExtension.NONE, null, String.class);
|
|
||||||
|
|
||||||
assertThrowsDaprException(
|
|
||||||
RuntimeException.class,
|
|
||||||
"UNKNOWN",
|
|
||||||
"UNKNOWN: ",
|
|
||||||
() -> result.block());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void invokeServiceNoRequestClassExceptionThrownTest() {
|
|
||||||
doAnswer((Answer<Void>) invocation -> {
|
|
||||||
throw new RuntimeException();
|
|
||||||
}).when(daprStub).invokeService(any(DaprProtos.InvokeServiceRequest.class), any());
|
|
||||||
|
|
||||||
Mono<String> result = client.invokeMethod("appId", "method", HttpExtension.NONE, (Map<String, String>)null, String.class);
|
|
||||||
|
|
||||||
assertThrowsDaprException(
|
|
||||||
RuntimeException.class,
|
|
||||||
"UNKNOWN",
|
|
||||||
"UNKNOWN: ",
|
|
||||||
() -> result.block());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void invokeServiceNoRequestTypeRefExceptionThrownTest() {
|
|
||||||
doAnswer((Answer<Void>) invocation -> {
|
|
||||||
throw new RuntimeException();
|
|
||||||
}).when(daprStub).invokeService(any(DaprProtos.InvokeServiceRequest.class), any());
|
|
||||||
|
|
||||||
Mono<String> result = client.invokeMethod("appId", "method", HttpExtension.NONE, (Map<String, String>)null, TypeRef.STRING);
|
|
||||||
|
|
||||||
assertThrowsDaprException(
|
|
||||||
RuntimeException.class,
|
|
||||||
"UNKNOWN",
|
|
||||||
"UNKNOWN: ",
|
|
||||||
() -> result.block());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void invokeServiceCallbackExceptionThrownTest() {
|
|
||||||
RuntimeException ex = new RuntimeException("An Exception");
|
|
||||||
doAnswer((Answer<Void>) invocation -> {
|
|
||||||
StreamObserver<CommonProtos.InvokeResponse> observer = (StreamObserver<CommonProtos.InvokeResponse>) invocation.getArguments()[1];
|
|
||||||
observer.onError(ex);
|
|
||||||
return null;
|
|
||||||
}).when(daprStub).invokeService(any(DaprProtos.InvokeServiceRequest.class), any());
|
|
||||||
|
|
||||||
Mono<String> result = client.invokeMethod("appId", "method", "request", HttpExtension.NONE, null, String.class);
|
|
||||||
|
|
||||||
assertThrowsDaprException(
|
|
||||||
ExecutionException.class,
|
|
||||||
"UNKNOWN",
|
|
||||||
"UNKNOWN: java.lang.RuntimeException: An Exception",
|
|
||||||
() -> result.block());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void invokeServiceWithHttpExtensionTest() throws IOException {
|
|
||||||
HttpExtension httpExtension = new HttpExtension(
|
|
||||||
DaprHttp.HttpMethods.GET, Collections.singletonMap("test", Arrays.asList("1", "ab/c")), null);
|
|
||||||
CommonProtos.InvokeRequest message = CommonProtos.InvokeRequest.newBuilder()
|
|
||||||
.setMethod("method")
|
|
||||||
.setData(getAny("request"))
|
|
||||||
.setContentType("application/json")
|
|
||||||
.setHttpExtension(CommonProtos.HTTPExtension.newBuilder()
|
|
||||||
.setVerb(CommonProtos.HTTPExtension.Verb.GET)
|
|
||||||
.setQuerystring("test=1&test=ab%2Fc").build())
|
|
||||||
.build();
|
|
||||||
DaprProtos.InvokeServiceRequest request = DaprProtos.InvokeServiceRequest.newBuilder()
|
|
||||||
.setId("appId")
|
|
||||||
.setMessage(message)
|
|
||||||
.build();
|
|
||||||
String expected = "Value";
|
|
||||||
|
|
||||||
doAnswer(invocation -> {
|
|
||||||
StreamObserver<CommonProtos.InvokeResponse> observer = (StreamObserver<CommonProtos.InvokeResponse>) invocation.getArguments()[1];
|
|
||||||
observer.onNext(CommonProtos.InvokeResponse.newBuilder().setData(getAny(expected)).build());
|
|
||||||
observer.onCompleted();
|
|
||||||
return null;
|
|
||||||
}).when(daprStub).invokeService(eq(request), any());
|
|
||||||
|
|
||||||
Mono<String> result = client.invokeMethod("appId", "method", "request", httpExtension, null, String.class);
|
|
||||||
String strOutput = result.block();
|
|
||||||
assertEquals(expected, strOutput);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void invokeServiceTest() {
|
|
||||||
String expected = "Value";
|
|
||||||
doAnswer((Answer<Void>) invocation -> {
|
|
||||||
StreamObserver<CommonProtos.InvokeResponse> observer = (StreamObserver<CommonProtos.InvokeResponse>) invocation.getArguments()[1];
|
|
||||||
observer.onNext(CommonProtos.InvokeResponse.newBuilder().setData(getAny(expected)).build());
|
|
||||||
observer.onCompleted();
|
|
||||||
return null;
|
|
||||||
}).when(daprStub).invokeService(any(DaprProtos.InvokeServiceRequest.class), any());
|
|
||||||
|
|
||||||
Mono<String> result = client.invokeMethod("appId", "method", "request", HttpExtension.NONE, null, String.class);
|
|
||||||
String strOutput = result.block();
|
|
||||||
|
|
||||||
assertEquals(expected, strOutput);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void invokeServiceObjectTest() throws Exception {
|
|
||||||
MyObject object = new MyObject(1, "Value");
|
|
||||||
doAnswer((Answer<Void>) invocation -> {
|
|
||||||
StreamObserver<CommonProtos.InvokeResponse> observer = (StreamObserver<CommonProtos.InvokeResponse>) invocation.getArguments()[1];
|
|
||||||
observer.onNext(CommonProtos.InvokeResponse.newBuilder().setData(getAny(object)).build());
|
|
||||||
observer.onCompleted();
|
|
||||||
return null;
|
|
||||||
}).when(daprStub).invokeService(any(DaprProtos.InvokeServiceRequest.class), any());
|
|
||||||
|
|
||||||
Mono<MyObject> result = client.invokeMethod("appId", "method", "request", HttpExtension.NONE, null, MyObject.class);
|
|
||||||
MyObject resultObject = result.block();
|
|
||||||
|
|
||||||
assertEquals(object.id, resultObject.id);
|
|
||||||
assertEquals(object.value, resultObject.value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void invokeServiceNoRequestBodyExceptionThrownTest() {
|
|
||||||
doAnswer((Answer<Void>) invocation -> {
|
|
||||||
throw new RuntimeException();
|
|
||||||
}).when(daprStub).invokeService(any(DaprProtos.InvokeServiceRequest.class), any());
|
|
||||||
|
|
||||||
Mono<String> result = client.invokeMethod("appId", "method", (Object)null, HttpExtension.NONE, String.class);
|
|
||||||
|
|
||||||
assertThrowsDaprException(
|
|
||||||
RuntimeException.class,
|
|
||||||
"UNKNOWN",
|
|
||||||
"UNKNOWN: ",
|
|
||||||
() -> result.block());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void invokeServiceNoRequestCallbackExceptionThrownTest() {
|
|
||||||
RuntimeException ex = new RuntimeException("An Exception");
|
|
||||||
doAnswer((Answer<Void>) invocation -> {
|
|
||||||
StreamObserver<CommonProtos.InvokeResponse> observer = (StreamObserver<CommonProtos.InvokeResponse>) invocation.getArguments()[1];
|
|
||||||
observer.onError(ex);
|
|
||||||
return null;
|
|
||||||
}).when(daprStub).invokeService(any(DaprProtos.InvokeServiceRequest.class), any());
|
|
||||||
|
|
||||||
Mono<String> result = client.invokeMethod("appId", "method", (Object)null, HttpExtension.NONE, String.class);
|
|
||||||
|
|
||||||
assertThrowsDaprException(
|
|
||||||
ExecutionException.class,
|
|
||||||
"UNKNOWN",
|
|
||||||
"UNKNOWN: java.lang.RuntimeException: An Exception",
|
|
||||||
() -> result.block());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void invokeServiceNoRequestBodyTest() throws Exception {
|
|
||||||
String expected = "Value";
|
|
||||||
doAnswer((Answer<Void>) invocation -> {
|
|
||||||
StreamObserver<CommonProtos.InvokeResponse> observer = (StreamObserver<CommonProtos.InvokeResponse>) invocation.getArguments()[1];
|
|
||||||
observer.onNext(CommonProtos.InvokeResponse.newBuilder().setData(getAny(expected)).build());
|
|
||||||
observer.onCompleted();
|
|
||||||
return null;
|
|
||||||
}).when(daprStub).invokeService(any(DaprProtos.InvokeServiceRequest.class), any());
|
|
||||||
|
|
||||||
Mono<String> result = client.invokeMethod("appId", "method", (Object)null, HttpExtension.NONE, String.class);
|
|
||||||
String strOutput = result.block();
|
|
||||||
|
|
||||||
assertEquals(expected, strOutput);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void invokeServiceNoRequestBodyObjectTest() throws Exception {
|
|
||||||
MyObject object = new MyObject(1, "Value");
|
|
||||||
doAnswer((Answer<Void>) invocation -> {
|
|
||||||
StreamObserver<CommonProtos.InvokeResponse> observer = (StreamObserver<CommonProtos.InvokeResponse>) invocation.getArguments()[1];
|
|
||||||
observer.onNext(CommonProtos.InvokeResponse.newBuilder().setData(getAny(object)).build());
|
|
||||||
observer.onCompleted();
|
|
||||||
return null;
|
|
||||||
}).when(daprStub).invokeService(any(DaprProtos.InvokeServiceRequest.class), any());
|
|
||||||
|
|
||||||
Mono<MyObject> result = client.invokeMethod("appId", "method", (Object)null, HttpExtension.NONE, MyObject.class);
|
|
||||||
MyObject resultObject = result.block();
|
|
||||||
|
|
||||||
assertEquals(object.id, resultObject.id);
|
|
||||||
assertEquals(object.value, resultObject.value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void invokeServiceByteRequestExceptionThrownTest() throws IOException {
|
|
||||||
doAnswer((Answer<Void>) invocation -> {
|
|
||||||
throw new RuntimeException();
|
|
||||||
}).when(daprStub).invokeService(any(DaprProtos.InvokeServiceRequest.class), any());
|
|
||||||
String request = "Request";
|
|
||||||
byte[] byteRequest = serializer.serialize(request);
|
|
||||||
|
|
||||||
Mono<byte[]> result = client.invokeMethod("appId", "method", byteRequest, HttpExtension.NONE, byte[].class);
|
|
||||||
|
|
||||||
assertThrowsDaprException(
|
|
||||||
RuntimeException.class,
|
|
||||||
"UNKNOWN",
|
|
||||||
"UNKNOWN: ",
|
|
||||||
() -> result.block());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void invokeServiceByteRequestCallbackExceptionThrownTest() throws IOException {
|
|
||||||
RuntimeException ex = new RuntimeException("An Exception");
|
|
||||||
doAnswer((Answer<Void>) invocation -> {
|
|
||||||
StreamObserver<CommonProtos.InvokeResponse> observer = (StreamObserver<CommonProtos.InvokeResponse>) invocation.getArguments()[1];
|
|
||||||
observer.onError(ex);
|
|
||||||
return null;
|
|
||||||
}).when(daprStub).invokeService(any(DaprProtos.InvokeServiceRequest.class), any());
|
|
||||||
String request = "Request";
|
|
||||||
byte[] byteRequest = serializer.serialize(request);
|
|
||||||
|
|
||||||
Mono<byte[]> result =
|
|
||||||
client.invokeMethod("appId", "method", byteRequest, HttpExtension.NONE,(HashMap<String, String>) null);
|
|
||||||
|
|
||||||
assertThrowsDaprException(
|
|
||||||
ExecutionException.class,
|
|
||||||
"UNKNOWN",
|
|
||||||
"UNKNOWN: java.lang.RuntimeException: An Exception",
|
|
||||||
() -> result.block());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void invokeByteRequestServiceTest() throws Exception {
|
|
||||||
String expected = "Value";
|
|
||||||
doAnswer((Answer<Void>) invocation -> {
|
|
||||||
StreamObserver<CommonProtos.InvokeResponse> observer = (StreamObserver<CommonProtos.InvokeResponse>) invocation.getArguments()[1];
|
|
||||||
observer.onNext(CommonProtos.InvokeResponse.newBuilder().setData(getAny(expected)).build());
|
|
||||||
observer.onCompleted();
|
|
||||||
return null;
|
|
||||||
}).when(daprStub).invokeService(any(DaprProtos.InvokeServiceRequest.class), any());
|
|
||||||
String request = "Request";
|
|
||||||
byte[] byteRequest = serializer.serialize(request);
|
|
||||||
|
|
||||||
Mono<byte[]> result = client.invokeMethod(
|
|
||||||
"appId", "method", byteRequest, HttpExtension.NONE, (HashMap<String, String>) null);
|
|
||||||
byte[] byteOutput = result.block();
|
|
||||||
|
|
||||||
String strOutput = serializer.deserialize(byteOutput, String.class);
|
|
||||||
assertEquals(expected, strOutput);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void invokeServiceByteRequestObjectTest() throws Exception {
|
|
||||||
MyObject resultObj = new MyObject(1, "Value");
|
|
||||||
doAnswer((Answer<Void>) invocation -> {
|
|
||||||
StreamObserver<CommonProtos.InvokeResponse> observer = (StreamObserver<CommonProtos.InvokeResponse>) invocation.getArguments()[1];
|
|
||||||
observer.onNext(CommonProtos.InvokeResponse.newBuilder().setData(getAny(resultObj)).build());
|
|
||||||
observer.onCompleted();
|
|
||||||
return null;
|
|
||||||
}).when(daprStub).invokeService(any(DaprProtos.InvokeServiceRequest.class), any());
|
|
||||||
|
|
||||||
String request = "Request";
|
|
||||||
byte[] byteRequest = serializer.serialize(request);
|
|
||||||
Mono<byte[]> result = client.invokeMethod("appId", "method", byteRequest, HttpExtension.NONE, byte[].class);
|
|
||||||
byte[] byteOutput = result.block();
|
|
||||||
|
|
||||||
assertEquals(resultObj, serializer.deserialize(byteOutput, MyObject.class));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void invokeServiceNoRequestNoClassBodyExceptionThrownTest() {
|
|
||||||
doAnswer((Answer<Void>) invocation -> {
|
|
||||||
throw new RuntimeException();
|
|
||||||
}).when(daprStub).invokeService(any(DaprProtos.InvokeServiceRequest.class), any());
|
|
||||||
Mono<Void> result = client.invokeMethod("appId", "method", (Object)null, HttpExtension.NONE);
|
|
||||||
|
|
||||||
assertThrowsDaprException(
|
|
||||||
RuntimeException.class,
|
|
||||||
"UNKNOWN",
|
|
||||||
"UNKNOWN: ",
|
|
||||||
() -> result.block());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void invokeServiceNoRequestNoClassCallbackExceptionThrownTest() {
|
|
||||||
RuntimeException ex = new RuntimeException("An Exception");
|
|
||||||
doAnswer((Answer<Void>) invocation -> {
|
|
||||||
StreamObserver<CommonProtos.InvokeResponse> observer = (StreamObserver<CommonProtos.InvokeResponse>) invocation.getArguments()[1];
|
|
||||||
observer.onError(ex);
|
|
||||||
return null;
|
|
||||||
}).when(daprStub).invokeService(any(DaprProtos.InvokeServiceRequest.class), any());
|
|
||||||
|
|
||||||
Mono<Void> result = client.invokeMethod("appId", "method", (Object)null, HttpExtension.NONE);
|
|
||||||
|
|
||||||
assertThrowsDaprException(
|
|
||||||
ExecutionException.class,
|
|
||||||
"UNKNOWN",
|
|
||||||
"UNKNOWN: java.lang.RuntimeException: An Exception",
|
|
||||||
() -> result.block());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void invokeServiceNoRequestNoClassBodyTest() {
|
|
||||||
String expected = "Value";
|
|
||||||
doAnswer((Answer<Void>) invocation -> {
|
|
||||||
StreamObserver<CommonProtos.InvokeResponse> observer = (StreamObserver<CommonProtos.InvokeResponse>) invocation.getArguments()[1];
|
|
||||||
observer.onNext(CommonProtos.InvokeResponse.newBuilder().setData(getAny(expected)).build());
|
|
||||||
observer.onCompleted();
|
|
||||||
return null;
|
|
||||||
}).when(daprStub).invokeService(any(DaprProtos.InvokeServiceRequest.class), any());
|
|
||||||
|
|
||||||
Mono<Void> result = client.invokeMethod("appId", "method", (Object)null, HttpExtension.NONE);
|
|
||||||
result.block();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void invokeServiceNoRequestNoHotMono() {
|
|
||||||
AtomicBoolean called = new AtomicBoolean(false);
|
|
||||||
String expected = "Value";
|
|
||||||
doAnswer((Answer<Void>) invocation -> {
|
|
||||||
called.set(true);
|
|
||||||
StreamObserver<CommonProtos.InvokeResponse> observer = (StreamObserver<CommonProtos.InvokeResponse>) invocation.getArguments()[1];
|
|
||||||
observer.onNext(CommonProtos.InvokeResponse.newBuilder().setData(getAny(expected)).build());
|
|
||||||
observer.onCompleted();
|
|
||||||
return null;
|
|
||||||
}).when(daprStub).invokeService(any(DaprProtos.InvokeServiceRequest.class), any());
|
|
||||||
client.invokeMethod("appId", "method", (Object)null, HttpExtension.NONE);
|
|
||||||
// Do not call block() on mono above, so nothing should happen.
|
|
||||||
assertFalse(called.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void invokeServiceNoRequestNoClassBodyObjectTest() throws Exception {
|
|
||||||
MyObject resultObj = new MyObject(1, "Value");
|
|
||||||
doAnswer((Answer<Void>) invocation -> {
|
|
||||||
StreamObserver<CommonProtos.InvokeResponse> observer = (StreamObserver<CommonProtos.InvokeResponse>) invocation.getArguments()[1];
|
|
||||||
observer.onNext(CommonProtos.InvokeResponse.newBuilder().setData(getAny(resultObj)).build());
|
|
||||||
observer.onCompleted();
|
|
||||||
return null;
|
|
||||||
}).when(daprStub).invokeService(any(DaprProtos.InvokeServiceRequest.class), any());
|
|
||||||
|
|
||||||
Mono<Void> result = client.invokeMethod("appId", "method", (Object)null, HttpExtension.NONE);
|
|
||||||
result.block();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getStateIllegalArgumentExceptionTest() {
|
public void getStateIllegalArgumentExceptionTest() {
|
||||||
State<String> key = buildStateKey(null, "Key1", "ETag1", null);
|
State<String> key = buildStateKey(null, "Key1", "ETag1", null);
|
||||||
|
@ -1429,7 +986,7 @@ public class DaprClientGrpcTest {
|
||||||
@Test
|
@Test
|
||||||
public void executeTransactionSerializerExceptionTest() throws IOException {
|
public void executeTransactionSerializerExceptionTest() throws IOException {
|
||||||
DaprObjectSerializer mockSerializer = mock(DaprObjectSerializer.class);
|
DaprObjectSerializer mockSerializer = mock(DaprObjectSerializer.class);
|
||||||
client = new DaprClientGrpc(channel, daprStub, mockSerializer, mockSerializer);
|
client = new DaprClientImpl(channel, daprStub, daprHttp, mockSerializer, mockSerializer);
|
||||||
String etag = "ETag1";
|
String etag = "ETag1";
|
||||||
String key = "key1";
|
String key = "key1";
|
||||||
String data = "my data";
|
String data = "my data";
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,80 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2021 The Dapr 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.dapr.client;
|
|
||||||
|
|
||||||
import io.dapr.client.domain.HttpExtension;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import org.mockito.Mockito;
|
|
||||||
import reactor.core.publisher.Mono;
|
|
||||||
|
|
||||||
import static org.mockito.Mockito.times;
|
|
||||||
|
|
||||||
public class DaprClientProxyTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void stateAPI() {
|
|
||||||
DaprClient client1 = Mockito.mock(DaprClient.class);
|
|
||||||
DaprClient client2 = Mockito.mock(DaprClient.class);
|
|
||||||
|
|
||||||
Mockito.when(client1.saveState("state", "key", "value")).thenReturn(Mono.empty());
|
|
||||||
Mockito.when(client2.saveState("state", "key", "value")).thenReturn(Mono.empty());
|
|
||||||
|
|
||||||
DaprClient proxy = new DaprClientProxy(client1, client2);
|
|
||||||
proxy.saveState("state", "key", "value").block();
|
|
||||||
|
|
||||||
Mockito.verify(client1, times(1)).saveState("state", "key", "value");
|
|
||||||
Mockito.verify(client2, times(0)).saveState("state", "key", "value");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void methodInvocationAPI() {
|
|
||||||
DaprClient client1 = Mockito.mock(DaprClient.class);
|
|
||||||
DaprClient client2 = Mockito.mock(DaprClient.class);
|
|
||||||
|
|
||||||
Mockito.when(client1.invokeMethod("appId", "methodName", "body", HttpExtension.POST))
|
|
||||||
.thenReturn(Mono.empty());
|
|
||||||
Mockito.when(client2.invokeMethod("appId", "methodName", "body", HttpExtension.POST))
|
|
||||||
.thenReturn(Mono.empty());
|
|
||||||
|
|
||||||
DaprClient proxy = new DaprClientProxy(client1, client2);
|
|
||||||
proxy.invokeMethod("appId", "methodName", "body", HttpExtension.POST).block();
|
|
||||||
|
|
||||||
Mockito.verify(client1, times(0))
|
|
||||||
.invokeMethod("appId", "methodName", "body", HttpExtension.POST);
|
|
||||||
Mockito.verify(client2, times(1))
|
|
||||||
.invokeMethod("appId", "methodName", "body", HttpExtension.POST);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void closeAllClients() throws Exception {
|
|
||||||
DaprClient client1 = Mockito.mock(DaprClient.class);
|
|
||||||
DaprClient client2 = Mockito.mock(DaprClient.class);
|
|
||||||
|
|
||||||
DaprClient proxy = new DaprClientProxy(client1, client2);
|
|
||||||
proxy.close();
|
|
||||||
|
|
||||||
Mockito.verify(client1, times(1)).close();
|
|
||||||
Mockito.verify(client2, times(1)).close();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void closeSingleClient() throws Exception {
|
|
||||||
DaprClient client1 = Mockito.mock(DaprClient.class);
|
|
||||||
|
|
||||||
DaprClient proxy = new DaprClientProxy(client1);
|
|
||||||
proxy.close();
|
|
||||||
|
|
||||||
Mockito.verify(client1, times(1)).close();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -13,17 +13,19 @@ limitations under the License.
|
||||||
|
|
||||||
package io.dapr.client;
|
package io.dapr.client;
|
||||||
|
|
||||||
|
import io.dapr.serializer.DefaultObjectSerializer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builder for DaprClient used in tests only.
|
* Builder for DaprClient used in tests only.
|
||||||
*/
|
*/
|
||||||
public class DaprClientTestBuilder {
|
public class DaprClientTestBuilder {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds a DaprClient.
|
* Builds a DaprClient only for HTTP calls.
|
||||||
* @param client DaprHttp used for http calls (can be mocked or stubbed)
|
* @param client DaprHttp used for http calls (can be mocked or stubbed)
|
||||||
* @return New instance of DaprClient.
|
* @return New instance of DaprClient.
|
||||||
*/
|
*/
|
||||||
public static DaprClient buildHttpClient(DaprHttp client) {
|
public static DaprClient buildClientForHttpOnly(DaprHttp client) {
|
||||||
return new DaprClientHttp(client);
|
return new DaprClientImpl(null, null, client, new DefaultObjectSerializer(), new DefaultObjectSerializer());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,16 +40,17 @@ import static org.mockito.Mockito.when;
|
||||||
public class DaprExceptionTest {
|
public class DaprExceptionTest {
|
||||||
private GrpcChannelFacade channel;
|
private GrpcChannelFacade channel;
|
||||||
private DaprGrpc.DaprStub daprStub;
|
private DaprGrpc.DaprStub daprStub;
|
||||||
|
private DaprHttp daprHttp;
|
||||||
private DaprClient client;
|
private DaprClient client;
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
public void setup() throws IOException {
|
public void setup() throws IOException {
|
||||||
channel = mock(GrpcChannelFacade.class);
|
channel = mock(GrpcChannelFacade.class);
|
||||||
daprStub = mock(DaprGrpc.DaprStub.class);
|
daprStub = mock(DaprGrpc.DaprStub.class);
|
||||||
|
daprHttp = mock(DaprHttp.class);
|
||||||
when(daprStub.withInterceptors(any())).thenReturn(daprStub);
|
when(daprStub.withInterceptors(any())).thenReturn(daprStub);
|
||||||
DaprClient grpcClient = new DaprClientGrpc(
|
client = new DaprClientImpl(
|
||||||
channel, daprStub, new DefaultObjectSerializer(), new DefaultObjectSerializer());
|
channel, daprStub, daprHttp, new DefaultObjectSerializer(), new DefaultObjectSerializer());
|
||||||
client = new DaprClientProxy(grpcClient);
|
|
||||||
doNothing().when(channel).close();
|
doNothing().when(channel).close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,17 +16,17 @@ import io.dapr.config.Properties;
|
||||||
import io.dapr.exceptions.DaprErrorDetails;
|
import io.dapr.exceptions.DaprErrorDetails;
|
||||||
import io.dapr.exceptions.DaprException;
|
import io.dapr.exceptions.DaprException;
|
||||||
import io.dapr.utils.TypeRef;
|
import io.dapr.utils.TypeRef;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
|
||||||
import reactor.test.StepVerifier;
|
|
||||||
import reactor.util.context.Context;
|
|
||||||
import okhttp3.MediaType;
|
import okhttp3.MediaType;
|
||||||
import okhttp3.OkHttpClient;
|
import okhttp3.OkHttpClient;
|
||||||
import okhttp3.ResponseBody;
|
import okhttp3.ResponseBody;
|
||||||
import okhttp3.mock.Behavior;
|
import okhttp3.mock.Behavior;
|
||||||
import okhttp3.mock.MockInterceptor;
|
import okhttp3.mock.MockInterceptor;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
|
import reactor.test.StepVerifier;
|
||||||
|
import reactor.util.context.Context;
|
||||||
import uk.org.webcompere.systemstubs.environment.EnvironmentVariables;
|
import uk.org.webcompere.systemstubs.environment.EnvironmentVariables;
|
||||||
import uk.org.webcompere.systemstubs.jupiter.SystemStub;
|
import uk.org.webcompere.systemstubs.jupiter.SystemStub;
|
||||||
import uk.org.webcompere.systemstubs.jupiter.SystemStubsExtension;
|
import uk.org.webcompere.systemstubs.jupiter.SystemStubsExtension;
|
||||||
|
|
|
@ -17,8 +17,8 @@ package io.dapr.client;
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.google.protobuf.ByteString;
|
import com.google.protobuf.ByteString;
|
||||||
import io.dapr.client.domain.BulkPublishRequest;
|
|
||||||
import io.dapr.client.domain.BulkPublishEntry;
|
import io.dapr.client.domain.BulkPublishEntry;
|
||||||
|
import io.dapr.client.domain.BulkPublishRequest;
|
||||||
import io.dapr.client.domain.BulkPublishResponse;
|
import io.dapr.client.domain.BulkPublishResponse;
|
||||||
import io.dapr.client.domain.QueryStateItem;
|
import io.dapr.client.domain.QueryStateItem;
|
||||||
import io.dapr.client.domain.QueryStateRequest;
|
import io.dapr.client.domain.QueryStateRequest;
|
||||||
|
@ -74,15 +74,17 @@ public class DaprPreviewClientGrpcTest {
|
||||||
|
|
||||||
private GrpcChannelFacade channel;
|
private GrpcChannelFacade channel;
|
||||||
private DaprGrpc.DaprStub daprStub;
|
private DaprGrpc.DaprStub daprStub;
|
||||||
|
private DaprHttp daprHttp;
|
||||||
private DaprPreviewClient previewClient;
|
private DaprPreviewClient previewClient;
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
public void setup() throws IOException {
|
public void setup() throws IOException {
|
||||||
channel = mock(GrpcChannelFacade.class);
|
channel = mock(GrpcChannelFacade.class);
|
||||||
daprStub = mock(DaprGrpc.DaprStub.class);
|
daprStub = mock(DaprGrpc.DaprStub.class);
|
||||||
|
daprHttp = mock(DaprHttp.class);
|
||||||
when(daprStub.withInterceptors(any())).thenReturn(daprStub);
|
when(daprStub.withInterceptors(any())).thenReturn(daprStub);
|
||||||
previewClient = new DaprClientGrpc(
|
previewClient = new DaprClientImpl(
|
||||||
channel, daprStub, new DefaultObjectSerializer(), new DefaultObjectSerializer());
|
channel, daprStub, daprHttp, new DefaultObjectSerializer(), new DefaultObjectSerializer());
|
||||||
doNothing().when(channel).close();
|
doNothing().when(channel).close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,7 +149,7 @@ public class DaprPreviewClientGrpcTest {
|
||||||
@Test
|
@Test
|
||||||
public void publishEventsSerializeException() throws IOException {
|
public void publishEventsSerializeException() throws IOException {
|
||||||
DaprObjectSerializer mockSerializer = mock(DaprObjectSerializer.class);
|
DaprObjectSerializer mockSerializer = mock(DaprObjectSerializer.class);
|
||||||
previewClient = new DaprClientGrpc(channel, daprStub, mockSerializer, new DefaultObjectSerializer());
|
previewClient = new DaprClientImpl(channel, daprStub, daprHttp, mockSerializer, new DefaultObjectSerializer());
|
||||||
doAnswer((Answer<Void>) invocation -> {
|
doAnswer((Answer<Void>) invocation -> {
|
||||||
StreamObserver<DaprProtos.BulkPublishResponse> observer =
|
StreamObserver<DaprProtos.BulkPublishResponse> observer =
|
||||||
(StreamObserver<DaprProtos.BulkPublishResponse>) invocation.getArguments()[1];
|
(StreamObserver<DaprProtos.BulkPublishResponse>) invocation.getArguments()[1];
|
||||||
|
|
|
@ -1,131 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2021 The Dapr 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.dapr.client;
|
|
||||||
|
|
||||||
import io.dapr.client.domain.LockRequest;
|
|
||||||
import io.dapr.client.domain.QueryStateRequest;
|
|
||||||
import io.dapr.client.domain.QueryStateResponse;
|
|
||||||
import io.dapr.client.domain.UnlockRequest;
|
|
||||||
import io.dapr.client.domain.UnlockResponseStatus;
|
|
||||||
import io.dapr.client.domain.query.Query;
|
|
||||||
import io.dapr.config.Properties;
|
|
||||||
import io.dapr.utils.TypeRef;
|
|
||||||
import okhttp3.OkHttpClient;
|
|
||||||
import okhttp3.mock.Behavior;
|
|
||||||
import okhttp3.mock.MockInterceptor;
|
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import reactor.core.publisher.Mono;
|
|
||||||
|
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
|
||||||
|
|
||||||
public class DaprPreviewClientHttpTest {
|
|
||||||
|
|
||||||
private static final String LOCK_STORE_NAME = "MyLockStore";
|
|
||||||
|
|
||||||
private DaprPreviewClient daprPreviewClientHttp;
|
|
||||||
|
|
||||||
private DaprHttp daprHttp;
|
|
||||||
|
|
||||||
private OkHttpClient okHttpClient;
|
|
||||||
|
|
||||||
private MockInterceptor mockInterceptor;
|
|
||||||
|
|
||||||
@BeforeEach
|
|
||||||
public void setUp() {
|
|
||||||
mockInterceptor = new MockInterceptor(Behavior.UNORDERED);
|
|
||||||
okHttpClient = new OkHttpClient.Builder().addInterceptor(mockInterceptor).build();
|
|
||||||
daprHttp = new DaprHttp(Properties.SIDECAR_IP.get(), 3000, okHttpClient);
|
|
||||||
daprPreviewClientHttp = new DaprClientHttp(daprHttp);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void queryStateExceptionsTest() {
|
|
||||||
assertThrows(IllegalArgumentException.class, () -> {
|
|
||||||
daprPreviewClientHttp.queryState("", "query", TypeRef.BOOLEAN).block();
|
|
||||||
});
|
|
||||||
assertThrows(IllegalArgumentException.class, () -> {
|
|
||||||
daprPreviewClientHttp.queryState("", "query", String.class).block();
|
|
||||||
});
|
|
||||||
assertThrows(IllegalArgumentException.class, () -> {
|
|
||||||
daprPreviewClientHttp.queryState("storeName", "", TypeRef.BOOLEAN).block();
|
|
||||||
});
|
|
||||||
assertThrows(IllegalArgumentException.class, () -> {
|
|
||||||
daprPreviewClientHttp.queryState("storeName", "", String.class).block();
|
|
||||||
});
|
|
||||||
assertThrows(IllegalArgumentException.class, () -> {
|
|
||||||
daprPreviewClientHttp.queryState("storeName", (Query) null, TypeRef.BOOLEAN).block();
|
|
||||||
});
|
|
||||||
assertThrows(IllegalArgumentException.class, () -> {
|
|
||||||
daprPreviewClientHttp.queryState("storeName", (Query) null, String.class).block();
|
|
||||||
});
|
|
||||||
assertThrows(IllegalArgumentException.class, () -> {
|
|
||||||
daprPreviewClientHttp.queryState("storeName", (String) null, TypeRef.BOOLEAN).block();
|
|
||||||
});
|
|
||||||
assertThrows(IllegalArgumentException.class, () -> {
|
|
||||||
daprPreviewClientHttp.queryState("storeName", (String) null, String.class).block();
|
|
||||||
});
|
|
||||||
assertThrows(IllegalArgumentException.class, () -> {
|
|
||||||
daprPreviewClientHttp.queryState(null, TypeRef.BOOLEAN).block();
|
|
||||||
});
|
|
||||||
assertThrows(IllegalArgumentException.class, () -> {
|
|
||||||
daprPreviewClientHttp.queryState(new QueryStateRequest("storeName"), TypeRef.BOOLEAN).block();
|
|
||||||
});
|
|
||||||
assertThrows(IllegalArgumentException.class, () -> {
|
|
||||||
daprPreviewClientHttp.queryState(null, String.class).block();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void queryStateTest() {
|
|
||||||
mockInterceptor.addRule()
|
|
||||||
.post()
|
|
||||||
.path("/v1.0-alpha1/state/testStore/query")
|
|
||||||
.respond("{\"results\": [{\"key\": \"1\",\"data\": \"testData\","
|
|
||||||
+ "\"etag\": \"6f54ad94-dfb9-46f0-a371-e42d550adb7d\"}]}");
|
|
||||||
QueryStateResponse<String> response = daprPreviewClientHttp.queryState("testStore", "query", String.class).block();
|
|
||||||
assertNotNull(response);
|
|
||||||
assertEquals(1, response.getResults().size(), "result size must be 1");
|
|
||||||
assertEquals( "1", response.getResults().get(0).getKey(), "result must be same");
|
|
||||||
assertEquals("testData", response.getResults().get(0).getValue(), "result must be same");
|
|
||||||
assertEquals( "6f54ad94-dfb9-46f0-a371-e42d550adb7d", response.getResults().get(0).getEtag(), "result must be same");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void tryLock() {
|
|
||||||
mockInterceptor.addRule()
|
|
||||||
.post("http://127.0.0.1:3000/v1.0-alpha1/lock/MyLockStore")
|
|
||||||
.respond("{ \"success\": true}");
|
|
||||||
|
|
||||||
LockRequest lockRequest = new LockRequest(LOCK_STORE_NAME,"1","owner",10);
|
|
||||||
|
|
||||||
Mono<Boolean> mono = daprPreviewClientHttp.tryLock(lockRequest);
|
|
||||||
assertEquals(Boolean.TRUE, mono.block());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void unLock() {
|
|
||||||
mockInterceptor.addRule()
|
|
||||||
.post("http://127.0.0.1:3000/v1.0-alpha1/unlock/MyLockStore")
|
|
||||||
.respond("{ \"status\": 0}");
|
|
||||||
|
|
||||||
UnlockRequest unLockRequest = new UnlockRequest(LOCK_STORE_NAME,"1","owner");
|
|
||||||
|
|
||||||
Mono<UnlockResponseStatus> mono = daprPreviewClientHttp.unlock(unLockRequest);
|
|
||||||
assertEquals(UnlockResponseStatus.SUCCESS, mono.block());
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,136 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2023 The Dapr 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.dapr.client;
|
|
||||||
|
|
||||||
import io.dapr.config.Properties;
|
|
||||||
import io.dapr.utils.NetworkUtils;
|
|
||||||
import io.dapr.v1.DaprGrpc;
|
|
||||||
import io.grpc.ManagedChannel;
|
|
||||||
import io.grpc.ManagedChannelBuilder;
|
|
||||||
import io.grpc.Server;
|
|
||||||
import io.grpc.ServerBuilder;
|
|
||||||
import io.grpc.inprocess.InProcessChannelBuilder;
|
|
||||||
import io.grpc.inprocess.InProcessServerBuilder;
|
|
||||||
import io.grpc.testing.GrpcCleanupRule;
|
|
||||||
import okhttp3.MediaType;
|
|
||||||
import okhttp3.OkHttpClient;
|
|
||||||
import okhttp3.ResponseBody;
|
|
||||||
import okhttp3.mock.Behavior;
|
|
||||||
import okhttp3.mock.MockInterceptor;
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.Rule;
|
|
||||||
import org.junit.jupiter.api.AfterAll;
|
|
||||||
import org.junit.jupiter.api.BeforeAll;
|
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import reactor.test.StepVerifier;
|
|
||||||
import reactor.test.scheduler.VirtualTimeScheduler;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.time.Duration;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import java.util.concurrent.TimeoutException;
|
|
||||||
|
|
||||||
import static io.dapr.utils.TestUtils.findFreePort;
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
|
||||||
|
|
||||||
public class GrpcChannelFacadeTest {
|
|
||||||
|
|
||||||
private static int port;
|
|
||||||
|
|
||||||
public static Server server;
|
|
||||||
|
|
||||||
private MockInterceptor mockInterceptor;
|
|
||||||
|
|
||||||
private OkHttpClient okHttpClient;
|
|
||||||
|
|
||||||
private static DaprHttp daprHttp;
|
|
||||||
|
|
||||||
@Rule
|
|
||||||
public static final GrpcCleanupRule grpcCleanup = new GrpcCleanupRule();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Enable the waitForSidecar to allow the gRPC to check the http endpoint for the health check
|
|
||||||
*/
|
|
||||||
@BeforeEach
|
|
||||||
public void setUp() {
|
|
||||||
mockInterceptor = new MockInterceptor(Behavior.UNORDERED);
|
|
||||||
okHttpClient = new OkHttpClient.Builder().addInterceptor(mockInterceptor).build();
|
|
||||||
}
|
|
||||||
|
|
||||||
@BeforeAll
|
|
||||||
public static void setup() throws IOException {
|
|
||||||
port = findFreePort();
|
|
||||||
|
|
||||||
// Create a server, add service, start, and register for automatic graceful shutdown.
|
|
||||||
grpcCleanup.register(ServerBuilder.forPort(port)
|
|
||||||
.addService(new DaprGrpc.DaprImplBase() {
|
|
||||||
})
|
|
||||||
.build().start());
|
|
||||||
}
|
|
||||||
|
|
||||||
@AfterAll
|
|
||||||
public static void teardown() throws InterruptedException {
|
|
||||||
if (daprHttp != null) {
|
|
||||||
daprHttp.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void waitForSidecarTimeoutHealthCheck() throws Exception {
|
|
||||||
OkHttpClient okHttpClient = new OkHttpClient.Builder().addInterceptor(mockInterceptor).build();
|
|
||||||
DaprHttp daprHttp = new DaprHttp(Properties.SIDECAR_IP.get(), 3500, okHttpClient);
|
|
||||||
|
|
||||||
ManagedChannel channel = InProcessChannelBuilder.forName("waitForSidecarTimeoutHealthCheck").build();
|
|
||||||
grpcCleanup.register(channel);
|
|
||||||
final GrpcChannelFacade channelFacade = new GrpcChannelFacade(channel, daprHttp);
|
|
||||||
|
|
||||||
mockInterceptor.addRule()
|
|
||||||
.get()
|
|
||||||
.path("/v1.0/healthz/outbound")
|
|
||||||
.times(6)
|
|
||||||
.respond(404, ResponseBody.create("Not Found", MediaType.get("application/json")));
|
|
||||||
|
|
||||||
StepVerifier.create(channelFacade.waitForChannelReady(1000))
|
|
||||||
.expectSubscription()
|
|
||||||
.expectError(TimeoutException.class)
|
|
||||||
.verify(Duration.ofSeconds(20));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void waitForSidecarOK() {
|
|
||||||
OkHttpClient okHttpClient = new OkHttpClient.Builder().addInterceptor(mockInterceptor).build();
|
|
||||||
|
|
||||||
DaprHttp daprHttp = new DaprHttp(Properties.SIDECAR_IP.get(), 3500, okHttpClient);
|
|
||||||
|
|
||||||
ManagedChannel channel = ManagedChannelBuilder.forAddress("127.0.0.1", port)
|
|
||||||
.usePlaintext().build();
|
|
||||||
|
|
||||||
grpcCleanup.register(channel);
|
|
||||||
|
|
||||||
final GrpcChannelFacade channelFacade = new GrpcChannelFacade(channel, daprHttp);
|
|
||||||
|
|
||||||
// added since this is doing a check against the http health check endpoint
|
|
||||||
// for parity with dotnet
|
|
||||||
mockInterceptor.addRule()
|
|
||||||
.get()
|
|
||||||
.path("/v1.0/healthz/outbound")
|
|
||||||
.respond(204);
|
|
||||||
|
|
||||||
StepVerifier.create(channelFacade.waitForChannelReady(10000))
|
|
||||||
.expectSubscription()
|
|
||||||
.expectComplete()
|
|
||||||
.verify();
|
|
||||||
}
|
|
||||||
}
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue