Skip to content

Commit b5c39d8

Browse files
authored
use backend filtering on engagements. - region, type, status, categor… (#182)
* use backend filtering on engagements. - region, type, status, category. some error handling for service outage * search queries for engagement and customer * remove commented code
1 parent 37089ce commit b5c39d8

File tree

10 files changed

+165
-125
lines changed

10 files changed

+165
-125
lines changed
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package com.redhat.labs.lodestar.model.filter;
2+
3+
import lombok.*;
4+
import org.eclipse.microprofile.openapi.annotations.parameters.Parameter;
5+
6+
import javax.ws.rs.DefaultValue;
7+
import javax.ws.rs.HeaderParam;
8+
import javax.ws.rs.QueryParam;
9+
import java.util.*;
10+
11+
@Data
12+
@NoArgsConstructor
13+
@AllArgsConstructor
14+
public class EngagementFilterOptions {
15+
16+
@Parameter(name = "Accept-version", description = "Valid Values are 'v1' or 'v2'. v2 pages results by default. v1 sets per page to 500.")
17+
@HeaderParam(value = "Accept-version")
18+
String apiVersion;
19+
20+
@Parameter(name = "search", description = "Deprecated. search string used to query engagements. allows =, not like, like, not exists, exists")
21+
@QueryParam("search")
22+
@Deprecated
23+
private String search;
24+
25+
@Parameter(name = "q", description = "Free search string. Currently supports Engagement and Customer names.")
26+
@QueryParam("q")
27+
private String q;
28+
29+
@Parameter(description = "sort value. Default Dir to ASC. Ex. field1|DESC,field2,field3|DESC. Always last sort by uuid")
30+
@QueryParam("sortFields")
31+
@DefaultValue("lastUpdate|desc")
32+
private String sortFields;
33+
34+
@Parameter(name = "page", description = "page to be returned. Starts at 1")
35+
@QueryParam("page")
36+
@DefaultValue("1")
37+
private Integer page;
38+
39+
@Parameter(name = "perPage", description = "number of results per page to return")
40+
@QueryParam("perPage")
41+
@DefaultValue("1000")
42+
private Integer perPage;
43+
44+
@Parameter(name = "regions", description = "include only these regions. All regions if empty")
45+
@QueryParam("regions")
46+
private Set<String> regions;
47+
48+
@Parameter(name = "types", description = "include only these types. All types if empty")
49+
@QueryParam("types")
50+
private Set<String> types;
51+
52+
@Parameter(name = "states", description = "include only these states. All states if empty")
53+
@QueryParam("states")
54+
private Set<String> states;
55+
56+
@Parameter(name = "category", description = "find by category")
57+
@QueryParam("category")
58+
private String category;
59+
60+
//Relic
61+
public Set<String> getV2Regions() {
62+
return regions;
63+
}
64+
}

src/main/java/com/redhat/labs/lodestar/resource/EngagementResource.java

Lines changed: 5 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import javax.ws.rs.core.UriInfo;
2727

2828
import com.redhat.labs.lodestar.model.EngagementUserSummary;
29+
import com.redhat.labs.lodestar.model.filter.EngagementFilterOptions;
2930
import com.redhat.labs.lodestar.service.ParticipantService;
3031
import org.eclipse.microprofile.jwt.JsonWebToken;
3132
import org.eclipse.microprofile.openapi.annotations.Operation;
@@ -57,8 +58,6 @@
5758
public class EngagementResource {
5859
private static final Logger LOGGER = LoggerFactory.getLogger(EngagementResource.class);
5960

60-
private static final String ACCEPT_VERSION_1 = "v1";
61-
6261
public static final String ACCESS_CONTROL_EXPOSE_HEADER = "Access-Control-Expose-Headers";
6362
public static final String LAST_UPDATE_HEADER = "last-update";
6463

@@ -86,11 +85,9 @@ public class EngagementResource {
8685
@APIResponses(value = { @APIResponse(responseCode = "401", description = "Missing or Invalid JWT"),
8786
@APIResponse(responseCode = "200", description = "A list or empty list of engagement resources returned") })
8887
@Operation(summary = "Returns all engagement resources from the database. Can be empty list if none found.")
89-
public Response getAll(@Context UriInfo uriInfo, @BeanParam ListFilterOptions filterOptions) {
90-
91-
// create one page with many results for v1
92-
setDefaultPagingFilterOptions(filterOptions);
88+
public Response getAll(@Context UriInfo uriInfo, @BeanParam EngagementFilterOptions filterOptions) {
9389

90+
LOGGER.debug("sort fields {}", filterOptions.getSortFields());
9491
return engagementService.getEngagementsPaged(filterOptions);
9592
}
9693

@@ -188,7 +185,7 @@ public Response get(@PathParam("id") String uuid, @BeanParam FilterOptions filte
188185
* GET - Queries
189186
*/
190187

191-
// Not sure if this one is being used currently
188+
// Not sure if this one is being used currently - should be covered by regular get. no?
192189
@GET
193190
@Path("/state/{state}")
194191
@SecurityRequirement(name = "jwt")
@@ -198,19 +195,7 @@ public Response get(@PathParam("id") String uuid, @BeanParam FilterOptions filte
198195
public Response getByState(@Context UriInfo uriInfo, @PathParam("state") String state,
199196
@Parameter(name = "start", required = true, description = "start date of range") @NotBlank @QueryParam("start") String start,
200197
@Parameter(name = "end", required = true, description = "end date of range") @NotBlank @QueryParam("end") String end,
201-
@BeanParam ListFilterOptions filterOptions) {
202-
203-
// set defaults for paging if not already set
204-
setDefaultPagingFilterOptions(filterOptions);
205-
206-
// set state parameter
207-
filterOptions.addEqualsSearchCriteria("state", state);
208-
209-
// set start parameter
210-
filterOptions.addEqualsSearchCriteria("start", start);
211-
212-
// set end parameter
213-
filterOptions.addEqualsSearchCriteria("end", end);
198+
@BeanParam EngagementFilterOptions filterOptions) {
214199

215200
PagedEngagementResults page = new PagedEngagementResults(); //TODO engagementService.getEngagementsPaged(filterOptions);
216201
ResponseBuilder builder = Response.ok(page.getResults()).links(page.getLinks(uriInfo.getAbsolutePathBuilder()));
@@ -233,9 +218,6 @@ public Response getUserSummary(@QueryParam("search") String search) {
233218
for (String param : params) {
234219
String[] keyValues = param.split("=");
235220

236-
if(keyValues.length == 0) {
237-
Response.status(Response.Status.BAD_REQUEST).build();
238-
}
239221
if (keyValues[0].equals("engagement_region")) {
240222
String[] regionsArray = keyValues[1].split(",");
241223
regions = Arrays.asList(regionsArray);
@@ -320,33 +302,6 @@ public Response post(@Valid Engagement engagement, @Context UriInfo uriInfo) {
320302

321303
}
322304

323-
@PUT
324-
@Deprecated
325-
@SecurityRequirement(name = "jwt")
326-
@Path("/customers/{customerName}/projects/{projectName}")
327-
@APIResponses(value = { @APIResponse(responseCode = "401", description = "Missing or Invalid JWT"),
328-
@APIResponse(responseCode = "403", description = "Not authorized for engagement type"),
329-
@APIResponse(responseCode = "404", description = "Engagement resource not found to update"),
330-
@APIResponse(responseCode = "200", description = "Engagement updated in the database") })
331-
@Operation(deprecated = true, summary = "Updates the engagement resource in the database.")
332-
public Response put(@PathParam("customerName") String customerName, @PathParam("projectName") String projectName,
333-
@Valid Engagement engagement) {
334-
335-
LOGGER.warn("Deprecated put method used /customers/{}/projects/{}", customerName, projectName);
336-
337-
boolean writer = jwtUtils.isAllowedToWriteEngagement(jwt, configService.getPermission(engagement.getType()));
338-
if(!writer) {
339-
return forbiddenResponse(engagement.getType());
340-
}
341-
342-
// pull user info from token
343-
engagement.setLastUpdateByName(jwtUtils.getUsernameFromToken(jwt));
344-
engagement.setLastUpdateByEmail(jwtUtils.getUserEmailFromToken(jwt));
345-
346-
return Response.ok(engagementService.update(engagement)).build();
347-
348-
}
349-
350305
@PUT
351306
@SecurityRequirement(name = "jwt")
352307
@Path("/{id}")
@@ -420,21 +375,11 @@ public Response delete(@PathParam("id") String uuid) {
420375

421376
engagementService.deleteEngagement(uuid);
422377
return Response.accepted().build();
423-
424378
}
425379

426380
private Response forbiddenResponse(String type) {
427381
String message = String.format("{\"message\": \"You cannot modify %s engagements\"}", type);
428382
return Response.status(403).entity(message).build();
429383
}
430384

431-
private void setDefaultPagingFilterOptions(ListFilterOptions options) {
432-
433-
boolean isV1 = null == options.getApiVersion() || ACCEPT_VERSION_1.equals(options.getApiVersion());
434-
435-
options.setPage(options.getPage().orElse(1));
436-
options.setPerPage(options.getPerPage().orElse(isV1 ? 500 : 20));
437-
438-
}
439-
440385
}

src/main/java/com/redhat/labs/lodestar/resource/RefreshResource.java

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
import javax.ws.rs.*;
1818
import javax.ws.rs.core.MediaType;
1919
import javax.ws.rs.core.Response;
20+
import java.util.ArrayList;
21+
import java.util.List;
2022
import java.util.Set;
2123

2224
@RequestScoped
@@ -51,45 +53,45 @@ public Response refresh(
5153
@Parameter(description = "Refresh hosting environments") @QueryParam("hosting") boolean refreshHosting,
5254
@Parameter(description = "Refresh engagements") @QueryParam("engagements") boolean refreshEngagements) {
5355

54-
boolean didPickSomething = false;
56+
List<String> refreshed = new ArrayList<>();
5557

5658
if (refreshEngagements) { //Engagements done first since all others are predicated on this content.
5759
//Engagements will be synchronous
5860
engagementService.refresh(uuids);
59-
didPickSomething = true;
61+
refreshed.add("engagements");
6062
}
6163

6264
if(refreshHosting) {
6365
eventBus.publish(EventType.RELOAD_HOSTING_EVENT_ADDRESS, EventType.RELOAD_HOSTING_EVENT_ADDRESS);
64-
didPickSomething = true;
66+
refreshed.add("hosting");
6567
}
6668

6769
if (refreshActivity) {
6870
eventBus.publish(EventType.RELOAD_ACTIVITY_EVENT_ADDRESS, EventType.RELOAD_ACTIVITY_EVENT_ADDRESS);
69-
didPickSomething = true;
71+
refreshed.add("activity");
7072
}
7173

7274
if (refreshParticipants) {
7375
eventBus.publish(EventType.RELOAD_PARTICIPANTS_EVENT_ADDRESS,
7476
EventType.RELOAD_PARTICIPANTS_EVENT_ADDRESS);
75-
didPickSomething = true;
77+
refreshed.add("participants");
7678
}
7779

7880
if (refreshArtifacts) {
7981
eventBus.publish(EventType.RELOAD_ARTIFACTS_EVENT_ADDRESS, EventType.RELOAD_ARTIFACTS_EVENT_ADDRESS);
80-
didPickSomething = true;
82+
refreshed.add("artifacts");
8183
}
8284

8385
if (refreshStatus) {
8486
eventBus.publish(EventType.RELOAD_ENGAGEMENT_STATUS_EVENT_ADDRESS, EventType.RELOAD_ENGAGEMENT_STATUS_EVENT_ADDRESS);
85-
didPickSomething = true;
87+
refreshed.add("status");
8688
}
8789

88-
if (didPickSomething) {
89-
return Response.accepted().build();
90+
if (refreshed.isEmpty()) {
91+
return Response.status(400).entity("{ \"message\" : \"No refresh source was selected\" }").build();
9092
}
9193

92-
return Response.status(400).entity("{ \"message\" : \"No refresh source was selected\" }").build();
94+
return Response.accepted().entity(refreshed).build();
9395

9496
}
9597

src/main/java/com/redhat/labs/lodestar/rest/client/EngagementApiClient.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@
1717
public interface EngagementApiClient {
1818

1919
@GET
20-
Response getEngagements(@QueryParam("page") int page, @QueryParam("pageSize") int pageSize, @QueryParam("region") Set<String> region);
20+
Response getEngagements(@QueryParam("page") int page, @QueryParam("pageSize") int pageSize, @QueryParam("region") Set<String> region,
21+
@QueryParam("types") Set<String> types, @QueryParam("inStates") Set<String> states, @QueryParam("q") String search,
22+
@QueryParam("category") String category, @QueryParam("sort") String sort);
2123

2224
//TODO support time shifting
2325
@GET
@@ -26,7 +28,8 @@ public interface EngagementApiClient {
2628

2729
@GET
2830
@Path("category/{category}")
29-
List<Engagement> getEngagementsWithCategory(@PathParam("category") String category);
31+
List<Engagement> getEngagementsWithCategory(@QueryParam("page") int page, @QueryParam("pageSize") int pageSize, @QueryParam("region") Set<String> region,
32+
@QueryParam("types") Set<String> types, @QueryParam("inStates") Set<String> states, @PathParam("category") String category, @QueryParam("sort") String sort);
3033

3134
@GET
3235
@Path("{uuid}")

src/main/java/com/redhat/labs/lodestar/service/ArtifactService.java

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
package com.redhat.labs.lodestar.service;
22

3-
import java.util.List;
4-
import java.util.Map;
5-
import java.util.Optional;
6-
import java.util.Set;
3+
import java.util.*;
74

85
import javax.enterprise.context.ApplicationScoped;
96
import javax.inject.Inject;
@@ -43,9 +40,15 @@ public List<Artifact> getArtifacts(String engagementUuid) {
4340
ArtifactOptions options = ArtifactOptions.builder().page(0).pageSize(1000)
4441
.engagementUuid(engagementUuid).build();
4542

46-
Response response = artifactRestClient.getArtifacts(options);
47-
48-
return response.readEntity(new GenericType<>(){});
43+
try {
44+
return artifactRestClient.getArtifacts(options).readEntity(new GenericType<>(){});
45+
} catch (WebApplicationException wex) {
46+
if(wex.getResponse().getStatus() >= 500) {
47+
LOGGER.error("Artifact Server error ({}) from hosting env for euuid {}", wex.getResponse().getStatus(), engagementUuid);
48+
return Collections.EMPTY_LIST;
49+
}
50+
throw wex;
51+
}
4952
}
5053

5154
public Response getArtifacts(ListFilterOptions filterOptions, String engagementUuid, String type, List<String> region, boolean dashboardView) {

src/main/java/com/redhat/labs/lodestar/service/EngagementService.java

Lines changed: 14 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import com.redhat.labs.lodestar.model.*;
44
import com.redhat.labs.lodestar.model.Engagement.EngagementState;
5+
import com.redhat.labs.lodestar.model.filter.EngagementFilterOptions;
56
import com.redhat.labs.lodestar.model.filter.ListFilterOptions;
67
import com.redhat.labs.lodestar.model.pagination.PagedEngagementResults;
78
import com.redhat.labs.lodestar.rest.client.CategoryApiClient;
@@ -19,6 +20,7 @@
1920

2021
import javax.enterprise.context.ApplicationScoped;
2122
import javax.inject.Inject;
23+
import javax.ws.rs.ProcessingException;
2224
import javax.ws.rs.WebApplicationException;
2325
import javax.ws.rs.core.GenericType;
2426
import javax.ws.rs.core.Response;
@@ -116,6 +118,8 @@ private Status getStatus(String uuid) {
116118
} else {
117119
LOGGER.error("Exception occurred retrieving status for engagement {}", uuid);
118120
}
121+
} catch (ProcessingException pe) {
122+
LOGGER.error("Cannot connect to lodestar-engagement-status for engagement {}", uuid, pe);
119123
}
120124

121125
return null;
@@ -321,51 +325,37 @@ public Map<EngagementState, Integer> getEngagementCountByStatus(Instant currentT
321325
* Returns a {@link PagedEngagementResults} of {@link Engagement} that matches
322326
* the {@link ListFilterOptions}.
323327
*
324-
* @param listFilterOptions
328+
* @param filter
325329
* @return ?
326330
*/
327-
public Response getEngagementsPaged(ListFilterOptions listFilterOptions) {
331+
public Response getEngagementsPaged(EngagementFilterOptions filter) {
328332
//TODO hacking for v1
329333
//TODO should probably better align last activity field on engagement object so that
330334
// we can just filter on engagement instead of hitting the activity service
331-
String sort = listFilterOptions.getSortFields().orElse("");
332-
int pageSize = listFilterOptions.getPerPage().orElse(5);
335+
String sort = filter.getSortFields();
336+
int pageSize = filter.getPerPage();
333337

334338
if(pageSize == 5 && sort.equals("last_update")) {
335-
List<String> activity = activityService.getLatestActivity(0,5, listFilterOptions.getV2Regions());
339+
List<String> activity = activityService.getLatestActivity(0,5, filter.getV2Regions());
336340
List<Engagement> engagements = activity.stream().map(this::getEngagement).collect(Collectors.toList());
337341
return Response.ok(engagements).build();
338342
}
339343

340-
int page = listFilterOptions.getPage().orElse(1) - 1;
341-
pageSize = listFilterOptions.getPerPage().orElse(1000);
344+
int page = filter.getPage() - 1;
345+
pageSize = filter.getPerPage();
342346

343-
Response response = engagementApiClient.getEngagements(page, pageSize, listFilterOptions.getV2Regions());
347+
Response response = engagementApiClient.getEngagements(page, pageSize, filter.getRegions(), filter.getTypes(), filter.getStates(), filter.getQ(), filter.getCategory(), sort);
344348
List<Engagement> engagements = response.readEntity(new GenericType<>(){});
349+
String total = response.getHeaderString("x-total-engagements");
345350

346351
Map<String, String> engagementOptions = configService.getEngagementOptions();
347352

348353
//TODO this loop is to allow frontend to change after v2 deployment.
349354
// FE should use participant, artifact count field, and categories (string version)
350355
for(Engagement e : engagements) {
351-
352-
for(int i=0; i<e.getParticipantCount(); i++) {
353-
e.addParticipant(EngagementUser.builder().email(String.valueOf(i)).build());
354-
}
355-
356-
for(int i=0; i<e.getArtifactCount(); i++) {
357-
e.addArtifact(Artifact.builder().type("temp").build());
358-
}
359-
360-
if(e.getCategoriesV2() != null) {
361-
for (String cat : e.getCategoriesV2()) {
362-
e.addCategory(cat);
363-
}
364-
}
365-
366356
e.setPrettyType(engagementOptions.containsKey(e.getType()) ? engagementOptions.get(e.getType()) : e.getType());
367357
}
368-
return Response.ok(engagements).header("x-total-engagements", response.getHeaderString("x-total-engagements")).build();
358+
return Response.ok(engagements).header("x-total-engagements", total).build();
369359
}
370360

371361
/**

0 commit comments

Comments
 (0)