[Java] improve Java API module (#2783)

API module (`ray/java/api` dir) includes all public APIs provided by Ray, it should be the only module that normal Ray users need to face.

The purpose of this PR to first improve the code quality of the API module. Subsequent PRs will improve other modules later. The changes of this PR include the following aspects: 
1) Only keep interfaces in api module, to hide implementation details from users and fix circular dependencies among modules.
2) Document everything in the api module. 
3) Improve naming.
4) Add more tests for API. 
5) Also fix/improve related code in other modules.
6) Remove some unused code.

(Apologize for posting such a large PR. Java worker code has been lack of maintenance for a while. There're a lot of code quality issues that need to be fixed. We plan to use a couple of large PRs to address them. After that, future changes will come in small PRs.)
This commit is contained in:
Hao Chen
2018-09-03 02:51:16 +08:00
committed by Robert Nishihara
parent 2691b3a11a
commit 3b0a2c4197
98 changed files with 2232 additions and 2158 deletions
+41 -39
View File
@@ -1,46 +1,48 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<groupId>org.ray.parent</groupId>
<artifactId>ray-superpom</artifactId>
<version>1.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<groupId>org.ray.parent</groupId>
<artifactId>ray-superpom</artifactId>
<version>1.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.ray</groupId>
<artifactId>ray-common</artifactId>
<name>java common and util for ray</name>
<description>java common and util for ray</description>
<url></url>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</dependency>
<dependency>
<groupId>quartz</groupId>
<artifactId>quartz</artifactId>
</dependency>
<dependency>
<groupId>org.ini4j</groupId>
<artifactId>ini4j</artifactId>
</dependency>
<dependency>
<groupId>org.ow2.asm</groupId>
<artifactId>asm</artifactId>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
</dependencies>
<groupId>org.ray</groupId>
<artifactId>ray-common</artifactId>
<name>java common and util for ray</name>
<description>java common and util for ray</description>
<url></url>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.ray</groupId>
<artifactId>ray-api</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</dependency>
<dependency>
<groupId>quartz</groupId>
<artifactId>quartz</artifactId>
</dependency>
<dependency>
<groupId>org.ini4j</groupId>
<artifactId>ini4j</artifactId>
</dependency>
<dependency>
<groupId>org.ow2.asm</groupId>
<artifactId>asm</artifactId>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
</dependencies>
</project>
@@ -1,10 +0,0 @@
package org.ray.util;
import java.io.Serializable;
import java.util.function.BiFunction;
@FunctionalInterface
public interface RemoteBiFunction<T1, T2, O> extends BiFunction<T1, T2, O>, Serializable {
}
@@ -1,9 +0,0 @@
package org.ray.util;
import java.io.Serializable;
import java.util.function.Function;
@FunctionalInterface
public interface RemoteFunction<I, O> extends Function<I, O>, Serializable {
}
@@ -1,7 +0,0 @@
package org.ray.util;
public @interface ResourceItem {
public String name() default "";
public double value() default 0;
}
@@ -2,6 +2,7 @@ package org.ray.util;
import java.util.HashMap;
import java.util.Map;
import org.ray.api.annotation.ResourceItem;
public class ResourceUtil {
public static final String CPU_LITERAL = "CPU";
@@ -12,6 +12,7 @@ import java.util.Vector;
import org.ini4j.Config;
import org.ini4j.Ini;
import org.ini4j.Profile;
import org.ray.api.id.UniqueId;
import org.ray.util.ObjectUtil;
import org.ray.util.StringUtil;
@@ -319,7 +320,7 @@ public class ConfigReader {
Object v = Enum.valueOf((Class<Enum>) fld.getType(), sv);
fld.set(obj, v);
// TODO: this is a hack and needs to be resolved later
} else if (fld.getType().getName().equals("org.ray.api.UniqueID")) {
} else if (fld.getType().equals(UniqueId.class)) {
String sv = getStringValue(section, fld.getName(), defaultFldValue.toString(), comment);
Object v;
try {
@@ -0,0 +1,113 @@
package org.ray.util.generator;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.ray.util.FileUtil;
/**
* A util class that generates `RayCall.java`
*/
public class RayCallGenerator extends BaseGenerator {
/**
* @return Whole file content of `RayCall.java`.
*/
private String build() {
sb = new StringBuilder();
newLine("// generated automatically, do not modify.");
newLine("");
newLine("package org.ray.api;");
newLine("");
newLine("import org.ray.api.function.*;");
newLine("");
newLine("/**");
newLine(" * This class provides type-safe interfaces for Ray.call.");
newLine(" **/");
newLine("@SuppressWarnings({\"rawtypes\", \"unchecked\"})");
newLine("class RayCall {");
for (int i = 0; i <= 6; i++) {
if (i > 0) {
buildCalls(i, true);
}
buildCalls(i, false);
}
newLine("}");
return sb.toString();
}
/**
* Build the `Ray.call` methods for given number of parameters.
* @param numParameters the number of parameters, including the actor parameter.
* @param forActor build actor api when true, otherwise build task api.
*/
private void buildCalls(int numParameters, boolean forActor) {
String genericTypes = "";
String argList = "";
for (int i = 0; i < numParameters; i++) {
genericTypes += "T" + i + ", ";
if (!forActor || i > 0) {
argList += "t" + i + ", ";
}
}
if (argList.endsWith(", ")) {
argList = argList.substring(0, argList.length() - 2);
}
String funcParam = String.format("RayFunc%d<%sR> f%s",
numParameters,
genericTypes,
numParameters > 0 ? ", " : "");
String actorParam = "";
if (forActor) {
actorParam = "RayActor<T0> actor";
if (numParameters > 1) {
actorParam += ", ";
}
}
for (String param : generateParameters(forActor ? 1 : 0, numParameters)) {
// method signature
indents(1);
newLine(String.format(
"public static <%sR> RayObject<R> call(%s%s%s) {",
genericTypes, funcParam, actorParam, param
));
// method body
indents(2);
newLine(String.format("Object[] args = new Object[]{%s};", argList));
indents(2);
newLine(String.format("return Ray.internal().call(f%s, args);", forActor ? ", actor" : ""));
indents(1);
newLine("}");
}
}
private List<String> generateParameters(int from, int to) {
List<String> res = new ArrayList<>();
dfs(from, from, to, "", res);
return res;
}
private void dfs(int pos, int from, int to, String cur, List<String> res) {
if (pos >= to) {
res.add(cur);
return;
}
if (pos > from) {
cur += ", ";
}
String nextParameter = String.format("T%d t%d", pos, pos);
dfs(pos + 1, from, to, cur + nextParameter, res);
nextParameter = String.format("RayObject<T%d> t%d", pos, pos);
dfs(pos + 1, from, to, cur + nextParameter, res);
}
public static void main(String[] args) throws IOException {
String path = System.getProperty("user.dir")
+ "/api/src/main/java/org/ray/api/RayCall.java";
FileUtil.overrideFile(path, new RayCallGenerator().build());
}
}
@@ -4,9 +4,9 @@ import java.io.IOException;
import org.ray.util.FileUtil;
/**
* A util class that generates all the classes under org.ray.api.funcs package.
* A util class that generates all the RayFuncX classes under org.ray.api.function package.
*/
public class FuncsGenerator extends BaseGenerator {
public class RayFuncGenerator extends BaseGenerator {
private String generate(int numParameters) {
sb = new StringBuilder();
@@ -23,8 +23,14 @@ public class FuncsGenerator extends BaseGenerator {
newLine("// generated automatically, do not modify.");
newLine("");
newLine("package org.ray.api.funcs;");
newLine("package org.ray.api.function;");
newLine("");
newLine("/**");
String comment = String.format(
" * Functional interface for a remote function that has %d parameter%s.",
numParameters, numParameters > 1 ? "s" : "");
newLine(comment);
newLine(" */");
newLine("@FunctionalInterface");
newLine(String.format("public interface RayFunc%d<%sR> extends RayFunc {",
numParameters, genericTypes));
@@ -37,8 +43,8 @@ public class FuncsGenerator extends BaseGenerator {
public static void main(String[] args) throws IOException {
String root = System.getProperty("user.dir")
+ "/api/src/main/java/org/ray/api/funcs/";
FuncsGenerator generator = new FuncsGenerator();
+ "/api/src/main/java/org/ray/api/function/";
RayFuncGenerator generator = new RayFuncGenerator();
for (int i = 0; i <= MAX_PARAMETERS; i++) {
String content = generator.generate(i);
FileUtil.overrideFile(root + "RayFunc" + i + ".java", content);
@@ -1,77 +0,0 @@
package org.ray.util.generator;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.ray.util.FileUtil;
/**
* A util class that generates Rpc.java
*/
public class RpcGenerator extends BaseGenerator {
private String build() {
sb = new StringBuilder();
newLine("// generated automatically, do not modify.");
newLine("");
newLine("package org.ray.api;");
newLine("");
newLine("import org.ray.api.funcs.*;");
newLine("");
newLine("@SuppressWarnings({\"rawtypes\", \"unchecked\"})");
newLine("class Rpc {");
for (int i = 0; i <= 6; i++) {
buildCalls(i);
}
newLine("}");
return sb.toString();
}
private void buildCalls(int numParameters) {
String funcClass = "RayFunc" + numParameters;
String genericTypes = "";
String callList = "";
for (int i = 1; i <= numParameters; i++) {
genericTypes += "T" + i + ", ";
callList += ", t" + i;
}
String body = String.format("return Ray.internal().call(f%s);", callList);
for (String param : generateParameters(numParameters)) {
indents(1);
newLine(String.format(
"public static <%sR> RayObject<R> call(%s<%sR> f%s) {",
genericTypes, funcClass, genericTypes, param
));
indents(2);
newLine(body);
indents(1);
newLine("}");
}
}
private List<String> generateParameters(int numParameters) {
List<String> res = new ArrayList<>();
dfs(1, numParameters, "", res);
return res;
}
private void dfs(int pos, int max, String cur, List<String> res) {
if (pos > max) {
res.add(cur);
return;
}
cur += ", ";
String nextParameter = String.format("T%d t%d", pos, pos);
dfs(pos + 1, max, cur + nextParameter, res);
nextParameter = String.format("RayObject<T%d> t%d", pos, pos);
dfs(pos + 1, max, cur + nextParameter, res);
}
public static void main(String[] args) throws IOException {
String path = System.getProperty("user.dir") + "/api/src/main/java";
path += "/org/ray/api/Rpc.java";
FileUtil.overrideFile(path, new RpcGenerator().build());
}
}