implemented graphql remote execution

This commit is contained in:
Andrey Terentev 2024-05-24 13:55:02 +07:00 committed by Andrey Terentev
parent 3f8b758de2
commit 0ce5427d40
3 changed files with 95 additions and 0 deletions

View File

@ -0,0 +1,18 @@
package ru.dragonestia.picker.api.impl.exception;
import java.util.Collections;
import java.util.Map;
public class GraphqlException extends RuntimeException {
private final Map<String, String> details;
public GraphqlException(Map<String, String> details) {
super(details.get("message"));
this.details = details;
}
public Map<String, String> getDetails() {
return Collections.unmodifiableMap(details);
}
}

View File

@ -0,0 +1,21 @@
package ru.dragonestia.picker.api.impl.util;
import java.util.Map;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
public record GraphqlQuery<T>(String query, Class<T> responseClass, ParamProvider paramProvider) {
public interface ParamConsumer extends BiConsumer<String, String> {
default void put(String key, String value) {
accept(key, value);
}
}
public interface ParamProvider extends Consumer<ParamConsumer> {}
public record Request(String query, Map<String, String> variables) {}
public record Response<T>(T data) {}
}

View File

@ -3,10 +3,13 @@ package ru.dragonestia.picker.api.impl.util;
import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.JsonNodeCreator;
import okhttp3.*; import okhttp3.*;
import org.jetbrains.annotations.ApiStatus.Internal; import org.jetbrains.annotations.ApiStatus.Internal;
import ru.dragonestia.picker.api.impl.exception.ExceptionService; import ru.dragonestia.picker.api.impl.exception.ExceptionService;
import ru.dragonestia.picker.api.impl.exception.GraphqlException;
import ru.dragonestia.picker.api.impl.exception.NotEnoughPermissions; import ru.dragonestia.picker.api.impl.exception.NotEnoughPermissions;
import ru.dragonestia.picker.api.impl.exception.AuthException; import ru.dragonestia.picker.api.impl.exception.AuthException;
import ru.dragonestia.picker.api.impl.RoomPickerClient; import ru.dragonestia.picker.api.impl.RoomPickerClient;
@ -18,6 +21,7 @@ import java.net.URLEncoder;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.*; import java.util.*;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.stream.Stream;
@Internal @Internal
public class RestTemplate { public class RestTemplate {
@ -85,6 +89,46 @@ public class RestTemplate {
.build()); .build());
} }
public <T> T executeGraphQL(GraphqlQuery<T> query) {
var map = new HashMap<String, String>();
query.paramProvider().accept(map::put);
String queryBody;
try {
queryBody = json.writeValueAsString(new GraphqlQuery.Request(query.query(), map));
} catch (Exception ex) {
throw new RuntimeException(ex);
}
var request = client.prepareRequestBuilder("/graphql")
.post(RequestBody.create(queryBody, MediaType.get("application/json")))
.build();
var response = executeGraphql(request);
JsonNode node;
try {
node = json.readTree(response);
} catch (Exception ex) {
throw new RuntimeException(ex);
}
if (node.has("errors")) {
var details = new HashMap<String, String>();
for (Iterator<Map.Entry<String, JsonNode>> it = node.fields(); it.hasNext(); ) {
var entry = it.next();
details.put(entry.getKey(), entry.getValue().textValue());
}
throw new GraphqlException(details);
}
try {
return json.readValue(response, new TypeReference<GraphqlQuery.Response<T>>(){}).data();
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
private String queryEncode(ParamsConsumer paramsConsumer) { private String queryEncode(ParamsConsumer paramsConsumer) {
var params = new HashMap<String, String>(); var params = new HashMap<String, String>();
paramsConsumer.accept(params); paramsConsumer.accept(params);
@ -120,6 +164,18 @@ public class RestTemplate {
} }
} }
private String executeGraphql(Request request) {
try (var response = httpClient.newCall(request).execute()) {
checkResponseForErrors(response);
return new String(Objects.requireNonNull(response.body()).bytes(), StandardCharsets.UTF_8);
} catch (JsonProcessingException ex) {
throw new RuntimeException("Json processing error", ex);
} catch (IOException ex) {
throw new RuntimeException(ex);
}
}
private void checkResponseForErrors(Response response) throws IOException { private void checkResponseForErrors(Response response) throws IOException {
var code = response.code(); var code = response.code();
var statusCode = code / 100; var statusCode = code / 100;