Last active
May 3, 2019 20:16
-
-
Save zeryx/e933adefaaae1ea1cbfd8f9f5a20d6a3 to your computer and use it in GitHub Desktop.
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
package AlgorithmHandler.algorithms; | |
import java.util.HashMap; | |
public class AdvancedAlgorithm { | |
public class AlgoInput { | |
String name; | |
Integer age; | |
} | |
public String Apply(AlgoInput input, HashMap<String, String> context) throws Exception { | |
if (context.containsKey("local_file")) { | |
return "Hello " + input.name + " you are " + input.age + | |
" years old, and your model file is downloaded here " + context.get("local_file"); | |
} | |
return "hello " + input.name + " you are " + input.age + " years old"; | |
} | |
public HashMap<String, String> DownloadModel() throws Exception { | |
HashMap<String, String> context = new HashMap<>(); | |
context.put("local_file", "/tmp/somefile"); | |
return context; | |
} | |
} |
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
package AlgorithmHandler; | |
import AlgorithmHandler.algorithms.AdvancedAlgorithm; | |
import com.algorithmia.algorithmHandler.AlgorithmHandler; | |
import com.google.gson.JsonObject; | |
import org.junit.Assert; | |
import org.junit.Test; | |
import java.io.ByteArrayInputStream; | |
import java.io.InputStream; | |
import java.nio.file.Files; | |
import java.nio.file.Paths; | |
public class AdvancedAlgorithmTest extends AlgorithmHandlerTestBase { | |
@Test | |
public void RunAlgorithm()throws Exception{ | |
JsonObject expectedResponse = new JsonObject(); | |
JsonObject metadata = new JsonObject(); | |
metadata.addProperty("content_type", "text"); | |
expectedResponse.add("metadata", metadata); | |
expectedResponse.addProperty("result", "Hello james"); | |
AdvancedAlgorithm algo = new AdvancedAlgorithm(); | |
AlgorithmHandler handler = new AlgorithmHandler<>(algo::Apply, algo::DownloadModel); | |
InputStream fakeIn = new ByteArrayInputStream("{\"content_type\":\"json\", \"data\":{\"name\":\"james\", \"age\":25}}".getBytes()); | |
System.setIn(fakeIn); | |
handler.run(); | |
byte[] fifoBytes = Files.readAllBytes(Paths.get(FIFOPIPE)); | |
String rawData = new String(fifoBytes); | |
JsonObject actualResponse = parser.parse(rawData).getAsJsonObject(); | |
Assert.assertEquals(expectedResponse, actualResponse); | |
} | |
} |
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
package com.algorithmia.algorithmHandler; | |
import java.io.IOException; | |
// The user can define nearly any type of Input, State, and Output arguments, they don't need to be json serializable. | |
public class AlgorithmHandler<INPUT, STATE, OUTPUT> { | |
@FunctionalInterface | |
public interface BifunctionWithException<INPUT, STATE, OUTPUT> { | |
OUTPUT apply(INPUT t, STATE j) throws Throwable; | |
} | |
@FunctionalInterface | |
public interface FunctionWithException<INPUT, OUTPUT>{ | |
OUTPUT apply(INPUT t) throws Throwable; | |
} | |
@FunctionalInterface | |
public interface SupplierWithException<STATE> { | |
STATE apply() throws Throwable; | |
} | |
private BifunctionWithException<INPUT, STATE, OUTPUT> applyWState; | |
private FunctionWithException<INPUT, OUTPUT> apply; | |
private SupplierWithException<STATE> loadFunc; | |
private STATE state; | |
private void Load() throws Throwable{ | |
state = this.loadFunc.apply(); | |
System.out.println("PIPE_INIT_COMPLETE"); | |
System.out.flush(); | |
} | |
private void ExecuteWithoutState(RequestHandler<INPUT> in, ResponseHandler out) throws Throwable { | |
INPUT req = in.GetNextRequest(); | |
while(req != null){ | |
OUTPUT output = this.apply.apply(req); | |
out.writeToPipe(output); | |
req = in.GetNextRequest(); | |
} | |
} | |
private void ExecuteWithState(RequestHandler<INPUT> in, ResponseHandler out) throws Throwable{ | |
INPUT req = in.GetNextRequest(); | |
while (req != null) { | |
OUTPUT output = this.applyWState.apply(req, state); | |
out.writeToPipe(output); | |
req = in.GetNextRequest(); | |
} | |
} | |
public AlgorithmHandler(BifunctionWithException<INPUT, STATE, OUTPUT> applyWState, SupplierWithException<STATE> loadFunc){ | |
this.applyWState = applyWState; | |
this.loadFunc = loadFunc; | |
} | |
public AlgorithmHandler(BifunctionWithException<INPUT, STATE, OUTPUT> applyWState){ | |
this.applyWState = applyWState; | |
} | |
public AlgorithmHandler(FunctionWithException<INPUT, OUTPUT> apply){ | |
this.apply = apply; | |
} | |
public void setLoad(SupplierWithException<STATE> func){ | |
loadFunc = func; | |
} | |
public void run() throws IOException { | |
RequestHandler<INPUT> in = new RequestHandler<>(); | |
ResponseHandler out = new ResponseHandler(); | |
try { | |
if(this.applyWState != null && this.loadFunc != null) { | |
Load(); | |
ExecuteWithState(in, out); | |
} else { | |
ExecuteWithoutState(in, out); | |
} | |
} catch (Throwable e){ | |
out.writeErrorToPipe(e); | |
} | |
} | |
} |
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
package com.algorithmia.algorithmHandler; | |
import com.google.gson.*; | |
import java.lang.reflect.ParameterizedType; | |
import java.lang.reflect.Type; | |
import java.util.Scanner; | |
import org.apache.commons.codec.binary.Base64; | |
final class RequestHandler<INPUT> | |
{ | |
private Scanner input; | |
private JsonParser parser; | |
private Gson gson; | |
RequestHandler(){ | |
this.input = new Scanner(System.in); | |
this.parser = new JsonParser(); | |
this.gson = new Gson(); | |
} | |
//This function doesn't work, I don't know how to do this kind of branching paths with generic types. | |
INPUT ProcessRequest(Request request) throws Exception{ | |
INPUT response; | |
Type type = this.getClass().getTypeParameters()[0]; | |
if(type instanceof Class){ | |
response = gson.fromJson(request.data, ((Class) types[0]).getGenericSuperclass()); | |
} else if(types[0] instanceof String.class){ | |
response = (INPUT)request.data.getAsString(); | |
} | |
else if(types[0] instanceof JsonElement){ | |
response = (INPUT)request.data; | |
} | |
else{ | |
response = (INPUT)Base64.decodeBase64(request.data.getAsString()); | |
} | |
return request; | |
} | |
INPUT GetNextRequest() throws Exception{ | |
if(input.hasNextLine()){ | |
String line = input.nextLine(); | |
JsonObject json = parser.parse(line).getAsJsonObject(); | |
String contentType = json.get("content_type").getAsString(); | |
JsonElement data = json.get("data"); | |
Request request = new Request(contentType, data); | |
return ProcessRequest(request); | |
} | |
else { | |
return null; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment