package com.airbnb.airpal.resources; import com.airbnb.airpal.api.Job; import com.airbnb.airpal.api.JobState; import com.airbnb.airpal.core.AirpalUser; import com.airbnb.airpal.core.AuthorizationUtil; import com.airbnb.airpal.core.execution.ExecutionClient; import com.airbnb.airpal.core.store.history.JobHistoryStore; import com.airbnb.airpal.presto.PartitionedTable; import com.airbnb.airpal.presto.Table; import com.facebook.presto.client.Column; import com.google.common.base.Optional; import com.google.common.collect.ImmutableList; import com.google.common.collect.Iterables; import com.google.common.collect.Ordering; import com.google.inject.Inject; import org.secnod.shiro.jaxrs.Auth; import javax.ws.rs.DELETE; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import java.util.Collections; import java.util.List; import java.util.UUID; import static com.airbnb.airpal.resources.QueryResource.JOB_ORDERING; @Path("/api/queries") @Produces({MediaType.APPLICATION_JSON}) public class QueriesResource { private final JobHistoryStore jobHistoryStore; private final ExecutionClient executionClient; @Inject public QueriesResource( JobHistoryStore jobHistoryStore, ExecutionClient executionClient) { this.jobHistoryStore = jobHistoryStore; this.executionClient = executionClient; } @GET public Response getQueries( @Auth AirpalUser user, @QueryParam("results") int numResults, @QueryParam("table") List<PartitionedTable> tables) { Iterable<Job> recentlyRun; int results = Optional.of(numResults).or(200); if (tables.size() < 1) { recentlyRun = jobHistoryStore.getRecentlyRun(results); } else { recentlyRun = jobHistoryStore.getRecentlyRun( results, Iterables.transform(tables, new PartitionedTable.PartitionedTableToTable())); } ImmutableList.Builder<Job> filtered = ImmutableList.builder(); for (Job job : recentlyRun) { if (job.getTablesUsed().isEmpty() && (job.getState() == JobState.FAILED)) { filtered.add(job); continue; } for (Table table : job.getTablesUsed()) { if (AuthorizationUtil.isAuthorizedRead(user, table)) { filtered.add(new Job( job.getUser(), job.getQuery(), job.getUuid(), job.getOutput(), job.getQueryStats(), job.getState(), Collections.<Column>emptyList(), Collections.<Table>emptySet(), job.getQueryStartedDateTime(), job.getError(), job.getQueryFinishedDateTime())); } } } List<Job> sortedResult = Ordering .natural() .nullsLast() .onResultOf(JOB_ORDERING) .reverse() .immutableSortedCopy(filtered.build()); return Response.ok(sortedResult).build(); } @DELETE @Path("/{uuid}") public Response cancelQuery( @Auth AirpalUser user, @PathParam("uuid") UUID uuid) { boolean success = executionClient.cancelQuery(user, uuid); if (success) { return Response.ok().build(); } else { return Response.status(Response.Status.NOT_FOUND).build(); } } }