Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

graphql poc #1277

Merged
merged 22 commits into from
Nov 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/backend_build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,14 @@ jobs:

steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
submodules: true

- name: Set up JDK
uses: actions/setup-java@v3
with:
java-version: 17
java-version: 21
distribution: temurin
cache: 'maven'

Expand Down
16 changes: 8 additions & 8 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ jobs:

steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
submodules: true

Expand All @@ -40,14 +40,14 @@ jobs:
- name: Set up JDK
uses: actions/setup-java@v3
with:
java-version: 17
java-version: 21
distribution: temurin
cache: 'maven'

- name: Set up Node
uses: actions/setup-node@v3
with:
node-version: '18'
node-version: '20'

- name: Set up pnpm
uses: pnpm/action-setup@v2
Expand Down Expand Up @@ -110,23 +110,23 @@ jobs:
run: (cd frontend && pnpm build)

- name: Login to registry
uses: docker/login-action@v2
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Extract metadata (tags, labels) for Docker (frontend)
id: frontend-meta
uses: docker/metadata-action@v4
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ github.repository }}/frontend
tags: |
type=sha,enable=true,format=short,prefix=${{ env.BRANCH_NAME }}-,suffix=-${{ steps.timestamp.outputs.timestamp }}
type=raw,value=latest,enable={{is_default_branch}}

- name: Build and push frontend Dockerfile
uses: docker/build-push-action@v4
uses: docker/build-push-action@v5
with:
context: .
file: chart/dockerfiles/frontend/Dockerfile
Expand All @@ -138,15 +138,15 @@ jobs:

- name: Extract metadata (tags, labels) for Docker (backend)
id: backend-meta
uses: docker/metadata-action@v4
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ github.repository }}/backend
tags: |
type=sha,enable=true,format=short,prefix=${{ env.BRANCH_NAME }}-,suffix=-${{ steps.timestamp.outputs.timestamp }}
type=raw,value=latest,enable={{is_default_branch}}

- name: Build and push backend Dockerfile
uses: docker/build-push-action@v4
uses: docker/build-push-action@v5
with:
context: .
file: chart/dockerfiles/backend/Dockerfile
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/frontend_build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,14 @@ jobs:

steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
submodules: true

- name: Set up Node
uses: actions/setup-node@v3
with:
node-version: '18'
node-version: '20'

- name: Set up pnpm
uses: pnpm/action-setup@v2
Expand Down
28 changes: 19 additions & 9 deletions backend/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.1.3</version>
<version>3.1.5</version>
<relativePath/>
</parent>

Expand All @@ -18,25 +18,25 @@

<properties>
<!-- compiling -->
<java.version>17</java.version>
<java.version>21</java.version>

<!-- encoding -->
<encoding>UTF-8</encoding>
<project.build.sourceEncoding>${encoding}</project.build.sourceEncoding>
<project.reporting.outputEncoding>${encoding}</project.reporting.outputEncoding>

<!-- dependency management -->
<jdbi3-bom.version>3.41.1</jdbi3-bom.version>
<jdbi3-bom.version>3.41.3</jdbi3-bom.version>
<configurate.version>4.1.2</configurate.version>
<spring-cloud-aws.version>3.0.2</spring-cloud-aws.version>

<!-- dependencies -->
<sentry.version>6.29.0</sentry.version>
<sentry.version>6.32.0</sentry.version>
<springdoc.version>2.2.0</springdoc.version>
<jsitemapgenerator.version>4.5</jsitemapgenerator.version>
<org-json.version>20230618</org-json.version>
<bucket4j.version>7.6.0</bucket4j.version>
<datafaker.version>2.0.1</datafaker.version>
<datafaker.version>2.0.2</datafaker.version>
<apache-commons-lang.version>3.13.0</apache-commons-lang.version>
<jwt.version>4.4.0</jwt.version>
<jetbrains-annotations.version>24.0.1</jetbrains-annotations.version>
Expand All @@ -52,7 +52,7 @@
<mockito-inline.version>5.2.0</mockito-inline.version>

<!-- test -->
<pg.version>1.19.0</pg.version>
<pg.version>1.19.1</pg.version>

<!-- plugins -->
<maven-compiler-plugin.version>3.11.0</maven-compiler-plugin.version>
Expand Down Expand Up @@ -146,6 +146,10 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-graphql</artifactId>
</dependency>

<dependency>
<groupId>org.apache.commons</groupId>
Expand Down Expand Up @@ -424,9 +428,15 @@
<testSource>${java.version}</testSource>
<testTarget>${java.version}</testTarget>
<encoding>${encoding}</encoding>
<compilerArgs>
<arg>-parameters</arg>
</compilerArgs>
<compilerArgs>--enable-preview</compilerArgs>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.1.2</version>
<configuration>
<argLine>--enable-preview</argLine>
</configuration>
</plugin>
<plugin>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ public void setupDefault() {
throw new RuntimeException("Error saving default avatar", e);
}
}
this.defaultAvatarUrl = this.fileService.getAvatarUrl("default", "default", 0);
this.defaultAvatarUrl = this.fileService.getAvatarUrl("default", "default", "0");
logger.info("Default avatar url is {}", this.defaultAvatarUrl);
}

Expand Down Expand Up @@ -122,7 +122,7 @@ private String getAvatarUrl(final String type, final String subject, final Suppl
return this.defaultAvatarUrl;
}
} else {
return this.fileService.getAvatarUrl(type, subject, table.getVersion());
return this.fileService.getAvatarUrl(type, subject, String.valueOf(table.getVersion()));
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package io.papermc.hangar.components.query;

import graphql.execution.ExecutionStepInfo;
import graphql.schema.GraphQLList;

public final class PrefixUtil {

private PrefixUtil() {
}

public static String getParentAlias(final ExecutionStepInfo info, final QueryBuilder queryBuilder) {
return getParentTable(info, queryBuilder, true);
}

public static String getParentTable(final ExecutionStepInfo info, final QueryBuilder queryBuilder) {
return getParentTable(info, queryBuilder, false);
}

private static String getParentTable(final ExecutionStepInfo info, final QueryBuilder queryBuilder, final boolean alias) {
final ExecutionStepInfo parent = info.getParent();
if (parent == null || parent.getObjectType() == null || parent.getObjectType().getName().equals("Query")) {
return queryBuilder.rootTable + (alias ? "_" : ".");
} else if (parent.getType() instanceof GraphQLList) {
// skip lists, else we would match them twice
return getParentTable(parent, queryBuilder, true);
} else {
return getParentTable(parent, queryBuilder, true) + parent.getField().getName() + (alias ? "_" : ".");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package io.papermc.hangar.components.query;

import graphql.GraphQLContext;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import org.jdbi.v3.core.Handle;
import org.jdbi.v3.core.statement.Query;

public class QueryBuilder {

public static final String QUERY_BUILDER = "queryBuilder";

String rootTable = "";
String from = "";
String condition = "";
Set<String> fields = new HashSet<>();
Set<String> joins = new LinkedHashSet<>();
Map<String, Function<Map<String, String>, String>> resolver = new HashMap<>();
Map<String, Object> variables = new HashMap<>();

public static List<QueryBuilder> getAllQueryBuilders(final GraphQLContext context) {
return context.getOrDefault(QUERY_BUILDER, List.of());
}

public static QueryBuilder getActiveQueryBuilder(final GraphQLContext context) {
return context.<List<QueryBuilder>>get(QUERY_BUILDER).getLast();
}

public static QueryBuilder newQueryBuilder(final GraphQLContext context) {
if (!context.hasKey(QUERY_BUILDER)) {
context.put(QUERY_BUILDER, new LinkedList<>());
}
final QueryBuilder newBuilder = new QueryBuilder();
context.<List<QueryBuilder>>get(QUERY_BUILDER).add(newBuilder);
return newBuilder;
}

public String buildSql() {
return STR."""
SELECT

\{this.fields.stream().sorted(Comparator.comparing(String::length)).reduce((a, b) -> a + ",\n" + b).orElse("")}

\{this.from}

\{this.joins.stream().reduce((a, b) -> a + "\n" + b).orElse("")}

\{this.condition};
""";
}

public List<Map<String, String>> execute(final Handle handle, final String sql) {
Query select = handle.select(sql);
// bind the arguments
for (final var entry : this.variables.entrySet()) {
select = select.bind(entry.getKey(), entry.getValue());
}

// execute the query
return select.mapToMap(String.class).collectIntoList();
}

public void handleResolvers(final List<Map<String, String>> result) {
Set<String> keysToRemove = null;
for (final Map<String, String> inputMap : result) {
// run the resolvers
for (final var entry : this.resolver.entrySet()) {
inputMap.put(entry.getKey(), entry.getValue().apply(inputMap));
}
// first time: find the ext keys
if (keysToRemove == null) {
keysToRemove = new HashSet<>();
for (final String key : inputMap.keySet()) {
if (key.startsWith("ext_")) {
keysToRemove.add(key);
}
}
}
// remove th ext keys
for (final String key : keysToRemove) {
inputMap.remove(key);
}
}
}
}
Loading
Loading