Skip to content

Commit

Permalink
Merge pull request kruize#1493 from msvinaykumar/bulk_new_format_3
Browse files Browse the repository at this point in the history
3. Bulk new format - Get Job details using filter
  • Loading branch information
dinogun authored Feb 17, 2025
2 parents bca6ab7 + 5e755e3 commit 3ffe5ad
Show file tree
Hide file tree
Showing 4 changed files with 170 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,13 @@
import java.util.concurrent.atomic.AtomicInteger;
import java.util.regex.Pattern;

import static com.autotune.utils.KruizeConstants.KRUIZE_BULK_API.JOB_ID;
import static com.autotune.utils.KruizeConstants.KRUIZE_BULK_API.*;
import static com.autotune.utils.KruizeConstants.KRUIZE_BULK_API.NotificationConstants.Status.UNPROCESSED;

/**
* Bulk API Response payload Object.
*/
@JsonFilter("jobFilter")
@JsonFilter(JOB_FILTER)
public class BulkJobStatus {
private static final Logger LOGGER = LoggerFactory.getLogger(BulkJobStatus.class);
private Summary summary;
Expand Down Expand Up @@ -108,6 +108,28 @@ public void setExperiments(Map<String, Experiment> experiments) {
this.experiments = experiments;
}

/**
* Copies entries from {@code experimentMap} to {@code experiments} based on a specified pattern.
* <p>
* If the provided regex is {@code null}, all entries from {@code experimentMap} are copied
* into {@code experiments}. If a regex is specified, only the entries whose keys match
* the pattern are copied.
* <p>
* This method clears the current contents of {@code experiments} before performing the copy operation.
* Access to {@code experimentMap} is synchronized to ensure thread safety.
*
* @param regex the regular expression used to filter entries by key, or {@code null} to copy all entries.
*
* <pre>
* Example Usage:
* Given a map containing:
* {"test1" -> "value1", "example2" -> "value2", "sample3" -> "value3"}
*
* copyByPattern("test") will result in:
* {"test1" -> "value1"} being copied to {@code experiments}.
* </pre>
*
*/
public void copyByPattern(String regex) {

experiments.clear();
Expand Down Expand Up @@ -143,7 +165,7 @@ public String getType() {
}
}

@JsonFilter("summaryFilter")
@JsonFilter(SUMMARY_FILTER)
public static class Summary {
@JsonProperty(JOB_ID)
private String jobID;
Expand Down Expand Up @@ -260,7 +282,7 @@ public void setInput(BulkInput input) {
}
}

@JsonFilter("experimentFilter")
@JsonFilter(EXPERIMENTS_FILTER)
public static class API_Response {
private CreateExperimentAPIResponse create = new CreateExperimentAPIResponse();
private GenerateRecommendationsAPIResponse recommendations = new GenerateRecommendationsAPIResponse();
Expand All @@ -282,7 +304,7 @@ public void setRecommendations(GenerateRecommendationsAPIResponse recommendation
}
}

@JsonFilter("experimentFilter")
@JsonFilter(EXPERIMENTS_FILTER)
public static class CreateExperimentAPIResponse {
private KruizeResponse response;
private CreateExperimentAPIObject request;
Expand All @@ -304,7 +326,7 @@ public void setRequest(CreateExperimentAPIObject request) {
}
}

@JsonFilter("experimentFilter")
@JsonFilter(EXPERIMENTS_FILTER)
public static class GenerateRecommendationsAPIResponse {

Object response = null;
Expand Down Expand Up @@ -347,7 +369,7 @@ public void setResponse(Object response) {

}

@JsonFilter("experimentFilter")
@JsonFilter(EXPERIMENTS_FILTER)
public static class Experiment {

private String name;
Expand Down
100 changes: 84 additions & 16 deletions src/main/java/com/autotune/analyzer/services/BulkService.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,7 @@
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.time.Instant;
import java.util.Map;
import java.util.UUID;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
Expand Down Expand Up @@ -72,6 +71,22 @@ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws Se
try {
String jobID = req.getParameter(JOB_ID);
String verboseParam = req.getParameter(VERBOSE);
// Read query parameters
String includeParams = req.getParameter("include");
String excludeParams = req.getParameter("exclude");
String experiment_name = req.getParameter("experiment_name");

LOGGER.debug(" include fields: {}", includeParams);
LOGGER.debug(" exclude fields: {}", excludeParams);

// Parse the include and exclude parameters into lists
Set<String> includeFields = includeParams != null ? new HashSet<>(Arrays.asList(includeParams.split(","))) : new HashSet<>(Arrays.asList("summary"));
Set<String> excludeFields = excludeParams != null ? new HashSet<>(Arrays.asList(excludeParams.split(","))) : Collections.emptySet();

LOGGER.debug(" include fields: {}", includeFields);
LOGGER.debug(" exclude fields: {}", excludeFields);
LOGGER.debug(" experiment_name: {}", experiment_name);

// If the parameter is not provided (null), default it to false
boolean verbose = verboseParam != null && Boolean.parseBoolean(verboseParam);
BulkJobStatus jobDetails;
Expand All @@ -86,7 +101,7 @@ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws Se
return;
}
jobDetails = jobStatusMap.get(jobID);
LOGGER.info("Job Status: " + jobDetails.getSummary().getStatus());
LOGGER.info("Job Status: {}" + jobDetails.getSummary().getStatus());
resp.setContentType(JSON_CONTENT_TYPE);
resp.setCharacterEncoding(CHARACTER_ENCODING);
SimpleFilterProvider filters = new SimpleFilterProvider();
Expand All @@ -101,19 +116,9 @@ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws Se
} else {
try {
resp.setStatus(HttpServletResponse.SC_OK);
// Return the JSON representation of the JobStatus object
ObjectMapper objectMapper = new ObjectMapper();
if (!verbose) {
filters.addFilter("jobFilter", SimpleBeanPropertyFilter.serializeAllExcept("experiments"));
} else {
filters.addFilter("jobFilter", SimpleBeanPropertyFilter.serializeAll());
}
objectMapper.setFilterProvider(filters);
String jsonResponse = "";
synchronized (jobDetails) {
jsonResponse = objectMapper.writeValueAsString(jobDetails);
}
resp.getWriter().write(jsonResponse);
// Filter JSON
String filteredJson = filterJson(jobDetails, includeFields, excludeFields, experiment_name);
resp.getWriter().write(filteredJson);
statusValue = "success";
} catch (Exception e) {
e.printStackTrace();
Expand Down Expand Up @@ -186,4 +191,67 @@ public void sendErrorResponse(HttpServletResponse response, Exception e, int htt
}
response.sendError(httpStatusCode, errorMsg);
}

/**
* Filters the JSON representation of a BulkJobStatus object based on the specified include and exclude fields.
*
* <p>This method applies dynamic filtering to the JSON output, allowing selective inclusion or exclusion
* of specific fields within the JSON structure. It supports hierarchical filtering for summary and experiment fields.</p>
*
* @param jsonInput The BulkJobStatus object to be filtered and serialized to JSON.
* @param includeFields A set of fields to be included in the JSON output. If specified, only these fields will be included.
* Fields can be prefixed with "SUMMARY|" or "EXPERIMENTS|" to filter nested fields.
* @param excludeFields A set of fields to be excluded from the JSON output. If includeFields is empty, exclusion will be applied.
* @param experiment_name The experiment name, used for copying relevant data in jsonInput.
* @return A JSON string representation of the filtered BulkJobStatus object.
* @throws Exception If there is an error during JSON processing.
*/
public String filterJson(BulkJobStatus jsonInput, Set<String> includeFields, Set<String> excludeFields, String experiment_name) throws Exception {
ObjectMapper mapper = new ObjectMapper();
// Include or exclude fields
SimpleFilterProvider filters = new SimpleFilterProvider();
jsonInput.copyByPattern(experiment_name);
if (!includeFields.isEmpty()) {
LOGGER.debug("includeFields : {}", includeFields);
Set<String> jobFields = new HashSet<>();
for (String field : includeFields) {
if (field.startsWith(SUMMARY)) {
jobFields.add(SUMMARY);
if (field.startsWith(SUMMARY + "|")) {
Set<String> summaryFields = new HashSet<>();
for (String s : field.split("\\|")) {
summaryFields.add(s);
}
filters.addFilter(SUMMARY_FILTER, SimpleBeanPropertyFilter.filterOutAllExcept(summaryFields));
} else {
filters.addFilter(SUMMARY_FILTER, SimpleBeanPropertyFilter.serializeAll());
}
} else if (field.startsWith(EXPERIMENTS)) {
jobFields.add(EXPERIMENTS);
if (field.startsWith(EXPERIMENTS + "|")) {
Set<String> experimentFields = new HashSet<>();
for (String s : field.split("\\|")) {
experimentFields.add(s);
}
filters.addFilter(EXPERIMENTS_FILTER, SimpleBeanPropertyFilter.filterOutAllExcept(experimentFields));
} else {
filters.addFilter(EXPERIMENTS_FILTER, SimpleBeanPropertyFilter.serializeAll());
}
} else {
jobFields.add(field);
}
}
filters.addFilter(JOB_FILTER, SimpleBeanPropertyFilter.filterOutAllExcept(jobFields));
} else if (!excludeFields.isEmpty()) {
LOGGER.debug("excludeFields : {}", excludeFields);
filters.addFilter(JOB_FILTER, SimpleBeanPropertyFilter.serializeAllExcept(excludeFields));
}

// Assuming the input JSON has a filter identifier like @JsonFilter("dynamicFilter")
mapper.setFilterProvider(filters);
synchronized (jsonInput) {
return mapper.writeValueAsString(jsonInput);
}

}
}
Loading

0 comments on commit 3ffe5ad

Please sign in to comment.