Last active
June 19, 2019 17:02
-
-
Save DarkSeraphim/7bb6fd698701e3ba0be8877073863807 to your computer and use it in GitHub Desktop.
GraphQL4J design v2
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public interface FieldResolver extends BiFunction<SelectionSet, Map<String, Object>, CompletableFuture<?>> { | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public interface Resolvable { | |
default Map<String, FieldResolver> nodes(); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.util.Map; | |
import java.util.UUID; | |
import java.util.concurrent.CompletableFuture; | |
import java.util.concurrent.TimeUnit; | |
import java.util.function.Function; | |
import java.util.function.Supplier; | |
import java.util.stream.Stream; | |
class UData { | |
public String name; | |
public long playing; | |
} | |
class GraphExecutor { | |
public CompletableFuture<Map<String, ?>> execute(SelectionSet selectionSet, Map<String, Object> args) { | |
UserQuery userQuery = getUserQuery(); | |
return resolve(selectionSet, args, userQuery); | |
} | |
public CompletableFuture<Map<String, ?>> resolve(SelectionSet selectionSet, Map<String, Object> args, Resolvable resolvable) { | |
Map<String, FieldResolver> resolvers = resolvable.nodes(); | |
Map<String, ?> result = new ConcurrentHashMap<>(); | |
return CompletableFuture.allOf(selectionSet.map(field -> { | |
FieldResolver resolver = resolvers.get(field); | |
return resolver.apply(selectionSet, args).thenApply(object -> { | |
if (object instanceof Resolvable) { | |
return resolve(selectionSet.getChild(field), args, (Resolvable) object); | |
} | |
return object; | |
}).thenAccept(value -> result.put(field, value)); | |
})).thenApply($ -> result); | |
} | |
private UserQuery getUserQuery() { | |
return new UserQuery() { | |
CompletableFuture<User> userById(SelectionSet selectionSet, UUID id) { | |
return getUser(selectionSet, id); | |
} | |
} | |
} | |
private User getUser(SelectionSet selectionSet, UUID id) { | |
Supplier<CompletableFuture<UData>> query = loadUser(selectionSet.asSet(), id); | |
return new User() { | |
public CompletableFuture<String> name() { | |
return query.get().thenApply(data -> data.name); | |
} | |
public CompletableFuture<Long> playingFor(TimeUnit unit) { | |
return query.get().thenApply(data -> unit.toMillis(data.playing)); | |
} | |
}; | |
} | |
// Out of scope: | |
private static Supplier<CompletableFuture<UData>> loadUser(Set<String> fields, UUID id) { | |
return () -> CompletableFuture.completedFuture(new UData() { | |
{ | |
super.name = "Foo"; | |
super.playing = 5; | |
} | |
}); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class SelectionSet { | |
private Map<String, SelectionSet> fields; | |
public <T> Stream<T> map(Function<String, T> mapper) { | |
return fields.keySet().stream().map(mapper); | |
} | |
public SelectionSet getChild(String field) { | |
return fields.get(field); | |
} | |
public Set<String> asSet() { | |
return Collections.unmodifiableSet(field.keySet()); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.util.HashMap; | |
import java.util.Map; | |
import java.util.concurrent.CompletableFuture; | |
import java.util.concurrent.TimeUnit; | |
import java.util.function.BiFunction; | |
public interface User extends Resolvable { | |
// Scalars don't need their selection set | |
CompletableFuture<String> name(); | |
CompletableFuture<Long> playingFor(TimeUnit units); | |
default Map<String, FieldResolver> nodes() { | |
return NODES(this); | |
} | |
static Map<String, FieldResolver> NODES(User instance) { | |
return new HashMap<String, FieldResolver>() {{ | |
put("name", (selectionSet, args) -> instance.name()); | |
put("playingFor", (selectionSet, args) -> instance.playingFor((TimeUnit) args.get("unit"))); | |
}}; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.util.HashMap; | |
import java.util.Map; | |
import java.util.UUID; | |
import java.util.concurrent.CompletableFuture; | |
import java.util.function.BiFunction; | |
public interface UserQuery extends Resolvable { | |
CompletableFuture<User> userById(SelectionSet selectionSet, UUID id); | |
default Map<String, FieldResolver> nodes() { | |
return NODES(this); | |
} | |
static Map<String, FieldResolver> NODES(UserQuery instance) { | |
return new HashMap<String, BiFunction<SelectionSet, Map<String, Object>, ?>>(){ | |
{ | |
put("userById", (selectionSet, args) -> instance.userById(selectionSet, (UUID) args.get("uuid"))); | |
}}; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment