Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
53 changes: 49 additions & 4 deletions src/main/java/com/mindee/MindeeClientV2.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import com.mindee.http.MindeeHttpExceptionV2;
import com.mindee.input.LocalInputSource;
import com.mindee.input.LocalResponse;
import com.mindee.input.URLInputSource;
import com.mindee.parsing.v2.ErrorResponse;
import com.mindee.parsing.v2.InferenceResponse;
import com.mindee.parsing.v2.JobResponse;
Expand Down Expand Up @@ -42,6 +43,16 @@ public JobResponse enqueueInference(
return mindeeApi.reqPostInferenceEnqueue(inputSource, params);
}


/**
* Enqueue a document in the asynchronous queue.
*/
public JobResponse enqueueInference(
URLInputSource inputSource,
InferenceParameters params) throws IOException {
return mindeeApi.reqPostInferenceEnqueue(inputSource, params);
}

/**
* Get the status of an inference that was previously enqueued.
* Can be used for polling.
Expand Down Expand Up @@ -78,24 +89,58 @@ public InferenceResponse enqueueAndGetInference(
InferenceParameters options) throws IOException, InterruptedException {

validatePollingOptions(options.getPollingOptions());
JobResponse job = enqueueInference(inputSource, options);
return pollAndFetch(job, options);
}



/**
* Send a local file to an async queue, poll, and parse when complete.
* @param inputSource The input source to send.
* @param options The options to send along with the file.
* @return an instance of {@link InferenceResponse}.
* @throws IOException Throws if the file can't be accessed.
* @throws InterruptedException Throws if the thread is interrupted.
*/
public InferenceResponse enqueueAndGetInference(
URLInputSource inputSource,
InferenceParameters options) throws IOException, InterruptedException {

validatePollingOptions(options.getPollingOptions());
JobResponse job = enqueueInference(inputSource, options);
return pollAndFetch(job, options);
}


/**
* Common logic for polling an asynchronous job until it is either processed
* successfully or fails / times out.
* @param initialJob The initial job response.
* @return an instance of {@link InferenceResponse}.
* @throws InterruptedException Throws if the thread is interrupted.
*/
private InferenceResponse pollAndFetch(JobResponse initialJob,
InferenceParameters options) throws InterruptedException {
Thread.sleep((long) (options.getPollingOptions().getInitialDelaySec() * 1000));
JobResponse resp = job;

JobResponse resp = initialJob;
int attempts = 0;
int max = options.getPollingOptions().getMaxRetries();

while (attempts < max) {
Thread.sleep((long) (options.getPollingOptions().getIntervalSec() * 1000));
resp = getJob(job.getJob().getId());
resp = getJob(initialJob.getJob().getId());

if (resp.getJob().getStatus().equals("Failed")) {
break;
attempts = max;
}
else if (resp.getJob().getStatus().equals("Processed")) {
if (resp.getJob().getStatus().equals("Processed")) {
return getInference(resp.getJob().getId());
}
attempts++;
}

ErrorResponse error = resp.getJob().getError();
if (error != null) {
throw new MindeeHttpExceptionV2(error.getStatus(), error.getDetail());
Expand Down
11 changes: 10 additions & 1 deletion src/main/java/com/mindee/http/MindeeApiV2.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.mindee.InferenceParameters;
import com.mindee.input.LocalInputSource;
import com.mindee.input.URLInputSource;
import com.mindee.parsing.v2.InferenceResponse;
import com.mindee.parsing.v2.JobResponse;
import java.io.IOException;
Expand All @@ -11,13 +12,21 @@
*/
public abstract class MindeeApiV2 extends MindeeApiCommon {
/**
* Send a file to the prediction queue.
* Send a file to the prediction queue with a local file.
*/
public abstract JobResponse reqPostInferenceEnqueue(
LocalInputSource inputSource,
InferenceParameters options
) throws IOException;

/**
* Send a file to the prediction queue with a remote file.
*/
public abstract JobResponse reqPostInferenceEnqueue(
URLInputSource inputSource,
InferenceParameters options
) throws IOException;

/**
* Attempts to poll the queue.
*/
Expand Down
59 changes: 47 additions & 12 deletions src/main/java/com/mindee/http/MindeeHttpApiV2.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import com.mindee.MindeeException;
import com.mindee.MindeeSettingsV2;
import com.mindee.input.LocalInputSource;
import com.mindee.input.URLInputSource;
import com.mindee.parsing.v2.CommonResponse;
import com.mindee.parsing.v2.ErrorResponse;
import com.mindee.parsing.v2.InferenceResponse;
Expand Down Expand Up @@ -79,8 +80,52 @@ public JobResponse reqPostInferenceEnqueue(
InferenceParameters options
) {
String url = this.mindeeSettings.getBaseUrl() + "/inferences/enqueue";
HttpPost post = buildHttpPost(url, inputSource, options);
HttpPost post = buildHttpPost(url, options);

MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setMode(HttpMultipartMode.EXTENDED);
builder.addBinaryBody(
"file",
inputSource.getFile(),
ContentType.DEFAULT_BINARY,
inputSource.getFilename()
);
post.setEntity(buildHttpBody(builder, options));
return executeEnqueue(post);
}


/**
* Enqueues a doc with the POST method.
*
* @param inputSource Input source to send.
* @param options Options to send the file along with.
* @return A job response.
*/
@Override
public JobResponse reqPostInferenceEnqueue(
URLInputSource inputSource,
InferenceParameters options
) {
String url = this.mindeeSettings.getBaseUrl() + "/inferences/enqueue";
HttpPost post = buildHttpPost(url, options);

MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setMode(HttpMultipartMode.EXTENDED);
builder.addTextBody(
"url",
inputSource.getUrl()
);
post.setEntity(buildHttpBody(builder, options));
return executeEnqueue(post);
}

/**
* Executes an enqueue action, common to URL & local inputs.
* @param post HTTP Post object.
* @return a valid job response.
*/
private JobResponse executeEnqueue(HttpPost post) {
mapper.findAndRegisterModules();
try (CloseableHttpClient httpClient = httpClientBuilder.build()) {
return httpClient.execute(
Expand Down Expand Up @@ -202,17 +247,9 @@ private MindeeHttpExceptionV2 getHttpError(ClassicHttpResponse response) {


private HttpEntity buildHttpBody(
LocalInputSource inputSource,
MultipartEntityBuilder builder,
InferenceParameters options
) {
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setMode(HttpMultipartMode.EXTENDED);
builder.addBinaryBody(
"file",
inputSource.getFile(),
ContentType.DEFAULT_BINARY,
inputSource.getFilename()
);

if (options.getAlias() != null) {
builder.addTextBody(
Expand All @@ -237,7 +274,6 @@ private HttpEntity buildHttpBody(

private HttpPost buildHttpPost(
String url,
LocalInputSource inputSource,
InferenceParameters options
) {
HttpPost post;
Expand All @@ -255,7 +291,6 @@ private HttpPost buildHttpPost(
post.setHeader(HttpHeaders.AUTHORIZATION, this.mindeeSettings.getApiKey().get());
}
post.setHeader(HttpHeaders.USER_AGENT, getUserAgent());
post.setEntity(buildHttpBody(inputSource, options));
return post;
}

Expand Down
1 change: 1 addition & 0 deletions src/main/java/com/mindee/input/URLInputSource.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
* Input source wrapper to load remote files locally.
*/
public class URLInputSource {
@Getter
private final String url;
private final String username;
private final String password;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,11 @@ public String toString(int indent) {
} else if (fieldValue.getObjectField() != null) {
strBuilder.append(fieldValue.getObjectField());
} else if (fieldValue.getSimpleField() != null) {
strBuilder.append(fieldValue.getSimpleField().getValue() != null ? fieldValue.getSimpleField().getValue() : "");
strBuilder.append(
fieldValue.getSimpleField().getValue() != null
? fieldValue.getSimpleField().toString()
: ""
);

}
joiner.add(strBuilder);
Expand Down
6 changes: 5 additions & 1 deletion src/main/java/com/mindee/parsing/v2/field/SimpleField.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ public final class SimpleField extends BaseField {

@Override
public String toString() {
return value == null ? "" : value.toString();
if (value == null) return "";
if (value.getClass().equals(Boolean.class)) {
return ((Boolean) value) ? "True" : "False";
}
return value.toString();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,24 @@ public SimpleField deserialize(JsonParser jp, DeserializationContext ctxt) throw
Object value = null;

if (valueNode != null && !valueNode.isNull()) {
if (valueNode.isTextual()) {
value = valueNode.asText();
} else if (valueNode.isNumber()) {
value = valueNode.doubleValue();
} else if (valueNode.isBoolean()) {
value = valueNode.asBoolean();
switch (valueNode.getNodeType()) {
case BOOLEAN:
value = valueNode.booleanValue();
break;

case NUMBER:
value = valueNode.doubleValue();
break;

case STRING:
value = valueNode.textValue();
break;

default:
value = codec.treeToValue(valueNode, Object.class);
}
}

return new SimpleField(value);
}
}
21 changes: 21 additions & 0 deletions src/test/java/com/mindee/MindeeClientV2IT.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,14 @@

import com.mindee.http.MindeeHttpExceptionV2;
import com.mindee.input.LocalInputSource;
import com.mindee.input.URLInputSource;
import com.mindee.parsing.v2.InferenceResponse;

import java.io.File;
import java.io.IOException;

import org.junit.jupiter.api.*;

import static org.junit.jupiter.api.Assertions.*;
import static org.junit.jupiter.api.Assumptions.assumeTrue;

Expand Down Expand Up @@ -83,6 +87,7 @@ void parseFile_filledSinglePage_mustSucceed() throws IOException, InterruptedExc
);
}


@Test
@DisplayName("Invalid model ID – enqueue must raise 422")
void invalidModel_mustThrowError() throws IOException {
Expand All @@ -109,4 +114,20 @@ void invalidJob_mustThrowError() {
assertEquals(422, ex.getStatus());
assertNotNull(ex);
}

@Test
@DisplayName("URL input source - A url param should not raise errors.")
void urlInputSource_mustNotRaiseErrors() throws IOException, InterruptedException {
URLInputSource urlSource = URLInputSource.builder(
"https://upload.wikimedia.org/wikipedia/commons/1/1d/Blank_Page.pdf"
).build();

InferenceParameters options =
InferenceParameters.builder(modelId).build();

InferenceResponse response = mindeeClient.enqueueAndGetInference(urlSource, options);

assertNotNull(response);
assertNotNull(response.getInference());
}
}
2 changes: 1 addition & 1 deletion src/test/java/com/mindee/parsing/v2/InferenceTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ void standardFieldTypes_mustExposeCorrectTypes() throws IOException {
assertNotNull(inf);

InferenceFields root = inf.getResult().getFields();
assertNotNull(root.get("field_simple").getSimpleField());
assertNotNull(root.get("field_simple_string").getSimpleField());
assertNotNull(root.get("field_object").getObjectField());
assertNotNull(root.get("field_simple_list").getListField());
assertNotNull(root.get("field_object_list").getListField());
Expand Down
Loading