mirror of
https://github.com/wassname/ray.git
synced 2026-06-28 02:46:49 +08:00
[Java] New Java actor API (#7414)
This commit is contained in:
@@ -98,7 +98,7 @@ public abstract class AbstractRayRuntime implements RayRuntime {
|
||||
}
|
||||
|
||||
@Override
|
||||
public RayObject call(RayFunc func, RayActor<?> actor, Object[] args) {
|
||||
public RayObject callActor(RayFunc func, RayActor<?> actor, Object[] args) {
|
||||
FunctionDescriptor functionDescriptor =
|
||||
functionManager.getFunction(workerContext.getCurrentJobId(), func)
|
||||
.functionDescriptor;
|
||||
|
||||
@@ -149,8 +149,8 @@ public class RayMultiWorkerNativeRuntime implements RayRuntime {
|
||||
}
|
||||
|
||||
@Override
|
||||
public RayObject call(RayFunc func, RayActor<?> actor, Object[] args) {
|
||||
return getCurrentRuntime().call(func, actor, args);
|
||||
public RayObject callActor(RayFunc func, RayActor<?> actor, Object[] args) {
|
||||
return getCurrentRuntime().callActor(func, actor, args);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -3,7 +3,6 @@ package org.ray.runtime.functionmanager;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Executable;
|
||||
import java.lang.reflect.Method;
|
||||
import org.ray.api.annotation.RayRemote;
|
||||
|
||||
/**
|
||||
* Represents a Ray function (either a Method or a Constructor in Java) and its metadata.
|
||||
@@ -57,21 +56,6 @@ public class RayFunction {
|
||||
return functionDescriptor;
|
||||
}
|
||||
|
||||
public RayRemote getRayRemoteAnnotation() {
|
||||
RayRemote rayRemote;
|
||||
|
||||
// If this method is a constructor, the task of it should be a actorCreationTask.
|
||||
// And the annotation of actorCreationTask should inherit from class.
|
||||
// Otherwise, it's a normal method, and it shouldn't inherit annotation from class.
|
||||
if (isConstructor()) {
|
||||
rayRemote = executable.getDeclaringClass().getAnnotation(RayRemote.class);
|
||||
} else {
|
||||
rayRemote = executable.getAnnotation(RayRemote.class);
|
||||
}
|
||||
|
||||
return rayRemote;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Whether this function has a return value.
|
||||
*/
|
||||
|
||||
@@ -8,18 +8,18 @@ import java.util.List;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
|
||||
/**
|
||||
* A util class that generates `RayCall.java`, which provides type-safe interfaces for `Ray.call`
|
||||
* and `Ray.createActor`.
|
||||
* A util class that generates `RayCall.java` and `ActorCall.java`, which provide type-safe
|
||||
* interfaces for `Ray.call`, `Ray.createActor` and `actor.call`.
|
||||
*/
|
||||
public class RayCallGenerator extends BaseGenerator {
|
||||
|
||||
/**
|
||||
* @return Whole file content of `RayCall.java`.
|
||||
*/
|
||||
private String build() {
|
||||
private String generateRayCallDotJava() {
|
||||
sb = new StringBuilder();
|
||||
|
||||
newLine("// generated automatically, do not modify.");
|
||||
newLine("// Generated by `RayCallGenerator.java`. DO NOT EDIT.");
|
||||
newLine("");
|
||||
newLine("package org.ray.api;");
|
||||
newLine("");
|
||||
@@ -48,13 +48,6 @@ public class RayCallGenerator extends BaseGenerator {
|
||||
buildCalls(i, false, false, false, true);
|
||||
}
|
||||
|
||||
newLine(1, "// ===========================================");
|
||||
newLine(1, "// Methods for remote actor method invocation.");
|
||||
newLine(1, "// ===========================================");
|
||||
for (int i = 0; i <= MAX_PARAMETERS - 1; i++) {
|
||||
buildCalls(i, true, false, true, false);
|
||||
buildCalls(i, true, false, false, false);
|
||||
}
|
||||
newLine(1, "// ===========================");
|
||||
newLine(1, "// Methods for actor creation.");
|
||||
newLine(1, "// ===========================");
|
||||
@@ -70,6 +63,7 @@ public class RayCallGenerator extends BaseGenerator {
|
||||
buildPyCalls(i, false, false, false);
|
||||
buildPyCalls(i, false, false, true);
|
||||
}
|
||||
// TODO(hchen): move Python actor call API to `RayPyActor` class.
|
||||
for (int i = 0; i <= MAX_PARAMETERS - 1; i++) {
|
||||
buildPyCalls(i, true, false, false);
|
||||
}
|
||||
@@ -82,30 +76,61 @@ public class RayCallGenerator extends BaseGenerator {
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the `Ray.call` or `Ray.createActor` methods with the given number of parameters.
|
||||
* @return Whole file content of `ActorCall.java`.
|
||||
*/
|
||||
private String generateActorCallDotJava() {
|
||||
sb = new StringBuilder();
|
||||
|
||||
newLine("// Generated by `RayCallGenerator.java`. DO NOT EDIT.");
|
||||
newLine("");
|
||||
newLine("package org.ray.api;");
|
||||
newLine("");
|
||||
for (int i = 1; i <= MAX_PARAMETERS; i++) {
|
||||
newLine("import org.ray.api.function.RayFunc" + i + ";");
|
||||
}
|
||||
for (int i = 1; i <= MAX_PARAMETERS; i++) {
|
||||
newLine("import org.ray.api.function.RayFuncVoid" + i + ";");
|
||||
}
|
||||
newLine("");
|
||||
newLine("/**");
|
||||
newLine(" * This class provides type-safe interfaces for remote actor calls.");
|
||||
newLine(" **/");
|
||||
newLine("@SuppressWarnings({\"rawtypes\", \"unchecked\"})");
|
||||
newLine("interface ActorCall<A> {");
|
||||
newLine("");
|
||||
for (int i = 0; i <= MAX_PARAMETERS - 1; i++) {
|
||||
buildCalls(i, true, false, true, false);
|
||||
buildCalls(i, true, false, false, false);
|
||||
}
|
||||
|
||||
newLine("}");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Build `Ray.call`, `Ray.createActor` and `actor.call` methods with
|
||||
* the given number of parameters.
|
||||
*
|
||||
* @param numParameters the number of parameters
|
||||
* @param forActor build actor api when true, otherwise build task api.
|
||||
* @param hasReturn if true, build api for functions with return.
|
||||
* @param forActorCreation build `Ray.createActor` when true, otherwise build `Ray.call`.
|
||||
* @param forActor Build `actor.call` when true, otherwise build `Ray.call`.
|
||||
* @param hasReturn if true, Build api for functions with return.
|
||||
* @param forActorCreation Build `Ray.createActor` when true, otherwise build `Ray.call`.
|
||||
*/
|
||||
private void buildCalls(int numParameters, boolean forActor,
|
||||
boolean forActorCreation, boolean hasReturn, boolean hasOptionsParam) {
|
||||
// Template of the generated function:
|
||||
// public static [genericTypes] [returnType] [callFunc]([argsDeclaration]) {
|
||||
// [modifiers] [genericTypes] [returnType] [callFunc]([argsDeclaration]) {
|
||||
// Objects[] args = new Object[]{[args]};
|
||||
// return Ray.internal().[callFunc](f[, actor], args[, options]);
|
||||
// return Ray.internal().[callFunc](f[, getThis()], args[, options]);
|
||||
// }
|
||||
|
||||
String modifiers = forActor ? "default" : "public static";
|
||||
|
||||
// 1) Construct the `genericTypes` part, e.g. `<T0, T1, T2, R>`.
|
||||
String genericTypes = "";
|
||||
for (int i = 0; i < numParameters; i++) {
|
||||
genericTypes += "T" + i + ", ";
|
||||
}
|
||||
if (forActor) {
|
||||
// Actor generic type.
|
||||
genericTypes = "A, " + genericTypes;
|
||||
}
|
||||
// Return generic type.
|
||||
if (forActorCreation) {
|
||||
genericTypes += "A, ";
|
||||
@@ -129,15 +154,21 @@ public class RayCallGenerator extends BaseGenerator {
|
||||
}
|
||||
|
||||
// 3) Construct the `argsDeclaration` part.
|
||||
String rayFuncGenericTypes = genericTypes;
|
||||
if (forActor) {
|
||||
if (rayFuncGenericTypes.isEmpty()) {
|
||||
rayFuncGenericTypes = "<A>";
|
||||
} else {
|
||||
rayFuncGenericTypes = rayFuncGenericTypes.replace("<", "<A, ");
|
||||
}
|
||||
}
|
||||
String argsDeclarationPrefix = String.format("RayFunc%s%d%s f, ",
|
||||
hasReturn ? "" : "Void",
|
||||
!forActor ? numParameters : numParameters + 1,
|
||||
genericTypes);
|
||||
if (forActor) {
|
||||
argsDeclarationPrefix += "RayActor<A> actor, ";
|
||||
}
|
||||
rayFuncGenericTypes);
|
||||
|
||||
String callFunc = forActorCreation ? "createActor" : "call";
|
||||
String internalCallFunc = forActorCreation ? "createActor" : forActor ? "callActor" : "call";
|
||||
|
||||
// Enumerate all combinations of the parameters.
|
||||
for (String param : generateParameters(numParameters)) {
|
||||
@@ -150,7 +181,7 @@ public class RayCallGenerator extends BaseGenerator {
|
||||
argsDeclaration = argsDeclaration.substring(0, argsDeclaration.length() - 2);
|
||||
// Print the first line (method signature).
|
||||
newLine(1, String.format(
|
||||
"public static%s %s %s(%s) {",
|
||||
"%s%s %s %s(%s) {", modifiers,
|
||||
genericTypes.isEmpty() ? "" : " " + genericTypes, returnType, callFunc, argsDeclaration
|
||||
));
|
||||
|
||||
@@ -169,22 +200,23 @@ public class RayCallGenerator extends BaseGenerator {
|
||||
// 5) Construct the third line.
|
||||
String callFuncArgs = "f, ";
|
||||
if (forActor) {
|
||||
callFuncArgs += "actor, ";
|
||||
callFuncArgs += "(RayActor) this, ";
|
||||
}
|
||||
callFuncArgs += "args, ";
|
||||
callFuncArgs += forActor ? "" : hasOptionsParam ? "options, " : "null, ";
|
||||
callFuncArgs = callFuncArgs.substring(0, callFuncArgs.length() - 2);
|
||||
newLine(2, String.format("%sRay.internal().%s(%s);",
|
||||
hasReturn ? "return " : "", callFunc, callFuncArgs));
|
||||
hasReturn ? "return " : "", internalCallFunc, callFuncArgs));
|
||||
newLine(1, "}");
|
||||
newLine("");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the `Ray.callPy` or `Ray.createPyActor` methods.
|
||||
*
|
||||
* @param forActor build actor api when true, otherwise build task api.
|
||||
* @param forActorCreation build `Ray.createPyActor` when true, otherwise build `Ray.callPy`.
|
||||
* @param forActor Build actor api when true, otherwise build task api.
|
||||
* @param forActorCreation Build `Ray.createPyActor` when true, otherwise build `Ray.callPy`.
|
||||
*/
|
||||
private void buildPyCalls(int numParameters, boolean forActor,
|
||||
boolean forActorCreation, boolean hasOptionsParam) {
|
||||
@@ -269,7 +301,12 @@ public class RayCallGenerator extends BaseGenerator {
|
||||
public static void main(String[] args) throws IOException {
|
||||
String path = System.getProperty("user.dir")
|
||||
+ "/api/src/main/java/org/ray/api/RayCall.java";
|
||||
FileUtils.write(new File(path), new RayCallGenerator().build(), Charset.defaultCharset());
|
||||
FileUtils.write(new File(path), new RayCallGenerator().generateRayCallDotJava(),
|
||||
Charset.defaultCharset());
|
||||
path = System.getProperty("user.dir")
|
||||
+ "/api/src/main/java/org/ray/api/ActorCall.java";
|
||||
FileUtils.write(new File(path), new RayCallGenerator().generateActorCallDotJava(),
|
||||
Charset.defaultCharset());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,6 @@ import javax.tools.ToolProvider;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.lang3.tuple.ImmutablePair;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.ray.api.annotation.RayRemote;
|
||||
import org.ray.api.function.RayFunc0;
|
||||
import org.ray.api.function.RayFunc1;
|
||||
import org.ray.api.id.JobId;
|
||||
@@ -23,12 +22,10 @@ import org.testng.annotations.Test;
|
||||
*/
|
||||
public class FunctionManagerTest {
|
||||
|
||||
@RayRemote
|
||||
public static Object foo() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@RayRemote
|
||||
public static class Bar {
|
||||
|
||||
public Bar() {
|
||||
@@ -81,19 +78,16 @@ public class FunctionManagerTest {
|
||||
RayFunction func = functionManager.getFunction(JobId.NIL, fooFunc);
|
||||
Assert.assertFalse(func.isConstructor());
|
||||
Assert.assertEquals(func.getFunctionDescriptor(), fooDescriptor);
|
||||
Assert.assertNotNull(func.getRayRemoteAnnotation());
|
||||
|
||||
// Test actor method
|
||||
func = functionManager.getFunction(JobId.NIL, barFunc);
|
||||
Assert.assertFalse(func.isConstructor());
|
||||
Assert.assertEquals(func.getFunctionDescriptor(), barDescriptor);
|
||||
Assert.assertNull(func.getRayRemoteAnnotation());
|
||||
|
||||
// Test actor constructor
|
||||
func = functionManager.getFunction(JobId.NIL, barConstructor);
|
||||
Assert.assertTrue(func.isConstructor());
|
||||
Assert.assertEquals(func.getFunctionDescriptor(), barConstructorDescriptor);
|
||||
Assert.assertNotNull(func.getRayRemoteAnnotation());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -103,19 +97,16 @@ public class FunctionManagerTest {
|
||||
RayFunction func = functionManager.getFunction(JobId.NIL, fooDescriptor);
|
||||
Assert.assertFalse(func.isConstructor());
|
||||
Assert.assertEquals(func.getFunctionDescriptor(), fooDescriptor);
|
||||
Assert.assertNotNull(func.getRayRemoteAnnotation());
|
||||
|
||||
// Test actor method
|
||||
func = functionManager.getFunction(JobId.NIL, barDescriptor);
|
||||
Assert.assertFalse(func.isConstructor());
|
||||
Assert.assertEquals(func.getFunctionDescriptor(), barDescriptor);
|
||||
Assert.assertNull(func.getRayRemoteAnnotation());
|
||||
|
||||
// Test actor constructor
|
||||
func = functionManager.getFunction(JobId.NIL, barConstructorDescriptor);
|
||||
Assert.assertTrue(func.isConstructor());
|
||||
Assert.assertEquals(func.getFunctionDescriptor(), barConstructorDescriptor);
|
||||
Assert.assertNotNull(func.getRayRemoteAnnotation());
|
||||
|
||||
// Test raise overload exception
|
||||
Assert.expectThrows(RuntimeException.class, () -> {
|
||||
|
||||
Reference in New Issue
Block a user