diff --git a/src/main/java/com/spotify/reaper/resources/ClusterResource.java b/src/main/java/com/spotify/reaper/resources/ClusterResource.java index 2447290cc..81a017457 100644 --- a/src/main/java/com/spotify/reaper/resources/ClusterResource.java +++ b/src/main/java/com/spotify/reaper/resources/ClusterResource.java @@ -15,15 +15,11 @@ import com.google.common.base.Optional; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.PropertyNamingStrategy; -import com.fasterxml.jackson.datatype.joda.JodaModule; import com.spotify.reaper.AppContext; import com.spotify.reaper.ReaperException; import com.spotify.reaper.cassandra.JmxProxy; import com.spotify.reaper.core.Cluster; -import com.spotify.reaper.resources.view.ClusterRun; +import com.spotify.reaper.resources.view.RepairRunStatus; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -81,27 +77,18 @@ public Response getCluster( private Response viewCluster(String clusterName, Optional limit, Optional createdURI) { - Collection view = context.storage.getClusterRunOverview(clusterName, limit.or(10)); + Collection view = + context.storage.getClusterRunStatuses(clusterName, limit.or(10)); if (view == null) { return Response.status(Response.Status.NOT_FOUND) .entity("cluster with name \"" + clusterName + "\" not found").build(); + } else if (createdURI.isPresent()) { + return Response.created(createdURI.get()) + .entity(view).build(); } else { - ObjectMapper objectMapper = new ObjectMapper() - .setPropertyNamingStrategy( - PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES) - .registerModule(new JodaModule()); - try { - if (createdURI.isPresent()) { - return Response.created(createdURI.get()) - .entity(objectMapper.writeValueAsString(view)).build(); - } else { - return Response.ok() - .entity(objectMapper.writeValueAsString(view)).build(); - } - } catch (JsonProcessingException e) { - return Response.serverError().entity("JSON processing failed").build(); - } + return Response.ok() + .entity(view).build(); } } diff --git a/src/main/java/com/spotify/reaper/resources/view/ClusterRun.java b/src/main/java/com/spotify/reaper/resources/view/ClusterRun.java deleted file mode 100644 index 27546c36f..000000000 --- a/src/main/java/com/spotify/reaper/resources/view/ClusterRun.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.spotify.reaper.resources.view; - -import com.spotify.reaper.core.RepairRun; -import com.spotify.reaper.resources.CommonTools; -import com.spotify.reaper.storage.postgresql.RepairRunMapper; - -import org.apache.commons.lang.time.DurationFormatUtils; -import org.joda.time.DateTime; -import org.joda.time.Duration; -import org.skife.jdbi.v2.StatementContext; -import org.skife.jdbi.v2.tweak.ResultSetMapper; - -import java.sql.ResultSet; -import java.sql.SQLException; - -public class ClusterRun { - - public final long runId; - public final String cluserName; - public final String keyspaceName; - public final String[] columnFamilies; - public final int segmentsRepaired; - public final int totalSegments; - public final RepairRun.RunState state; - private final DateTime startTime; - public String getStartTime() { - return CommonTools.dateTimeToISO8601(startTime); - } - private final Duration duration; - public String getDuration() { - if (null == duration) { - return null; - } - return DurationFormatUtils.formatDurationWords(duration.getMillis(), false, false); - } - public final String cause; - public final String owner; - public final String lastEvent; - private final DateTime estimatedTimeOfArrival; - public String getEstimatedTimeOfArrival() { - return CommonTools.dateTimeToISO8601(estimatedTimeOfArrival); - } - - public ClusterRun(long runId, String clusterName, String keyspaceName, String[] columnFamilies, - int segmentsRepaired, int totalSegments, RepairRun.RunState state, DateTime startTime, - DateTime endTime, String cause, String owner, String lastEvent) { - this.runId = runId; - this.cluserName = clusterName; - this.keyspaceName = keyspaceName; - this.columnFamilies = columnFamilies; - this.segmentsRepaired = segmentsRepaired; - this.totalSegments = totalSegments; - this.state = state; - this.startTime = startTime; - this.cause = cause; - this.owner = owner; - this.lastEvent = lastEvent; - - if (startTime == null) { - estimatedTimeOfArrival = null; - duration = null; - } else if (endTime == null) { - duration = null; - if (state == RepairRun.RunState.ERROR || state == RepairRun.RunState.DELETED) { - estimatedTimeOfArrival = null; - } else { - long now = DateTime.now().getMillis(); - estimatedTimeOfArrival = new DateTime( - now + (now - startTime.getMillis()) / - segmentsRepaired * (totalSegments - segmentsRepaired)); - } - } else { - estimatedTimeOfArrival = null; - duration = new Duration(startTime.toInstant(), endTime.toInstant()); - } - } - - public static class Mapper implements ResultSetMapper { - - @Override - public ClusterRun map(int index, ResultSet r, StatementContext ctx) throws SQLException { - long runId = r.getLong("id"); - String clusterName = r.getString("cluster_name"); - String keyspaceName = r.getString("keyspace_name"); - String[] columnFamilies = (String[]) r.getArray("column_families").getArray(); - int segmentsRepaired = (int)r.getLong("count"); - int totalSegments = r.getInt("segment_count"); - RepairRun.RunState state = RepairRun.RunState.valueOf(r.getString("state")); - DateTime startTime = RepairRunMapper.getDateTimeOrNull(r, "start_time"); - DateTime endTime = RepairRunMapper.getDateTimeOrNull(r, "end_time"); - String cause = r.getString("cause"); - String owner = r.getString("owner"); - String lastEvent = r.getString("last_event"); - return new ClusterRun(runId, clusterName, keyspaceName, columnFamilies, segmentsRepaired, - totalSegments, state, startTime, endTime, cause, owner, lastEvent); - } - } -} diff --git a/src/main/java/com/spotify/reaper/storage/IStorage.java b/src/main/java/com/spotify/reaper/storage/IStorage.java index a8c1c8fb7..ace2f747b 100644 --- a/src/main/java/com/spotify/reaper/storage/IStorage.java +++ b/src/main/java/com/spotify/reaper/storage/IStorage.java @@ -20,7 +20,7 @@ import com.spotify.reaper.core.RepairSchedule; import com.spotify.reaper.core.RepairSegment; import com.spotify.reaper.core.RepairUnit; -import com.spotify.reaper.resources.view.ClusterRun; +import com.spotify.reaper.resources.view.RepairRunStatus; import com.spotify.reaper.service.RingRange; import java.util.Collection; @@ -125,5 +125,5 @@ Optional getRepairUnit(String cluster, String keyspace, */ Optional deleteRepairSchedule(long id); - Collection getClusterRunOverview(String clusterName, int limit); +Collection getClusterRunStatuses(String clusterName, int limit); } diff --git a/src/main/java/com/spotify/reaper/storage/MemoryStorage.java b/src/main/java/com/spotify/reaper/storage/MemoryStorage.java index 858ea479c..e78a74963 100644 --- a/src/main/java/com/spotify/reaper/storage/MemoryStorage.java +++ b/src/main/java/com/spotify/reaper/storage/MemoryStorage.java @@ -22,7 +22,7 @@ import com.spotify.reaper.core.RepairSchedule; import com.spotify.reaper.core.RepairSegment; import com.spotify.reaper.core.RepairUnit; -import com.spotify.reaper.resources.view.ClusterRun; +import com.spotify.reaper.resources.view.RepairRunStatus; import com.spotify.reaper.service.RingRange; import java.util.ArrayList; @@ -377,27 +377,25 @@ public Optional deleteRepairSchedule(long id) { } @Override - public Collection getClusterRunOverview(String clusterName, int limit) { + public Collection getClusterRunStatuses(String clusterName, int limit) { Optional cluster = getCluster(clusterName); if (!cluster.isPresent()) { return null; } else { - List clusterRuns = Lists.newArrayList(); - Collection runs = getRepairRunsForCluster(clusterName); - for (RepairRun run : runs) { + List runStatuses = Lists.newArrayList(); + for (RepairRun run : getRepairRunsForCluster(clusterName)) { RepairUnit unit = getRepairUnit(run.getRepairUnitId()).get(); - String[] tables = - unit.getColumnFamilies().toArray(new String[unit.getColumnFamilies().size()]); int segmentsRepaired = getSegmentAmountForRepairRunWithState(run.getId(), RepairSegment.State.DONE); int totalSegments = getSegmentAmountForRepairRun(run.getId()); - clusterRuns.add(new ClusterRun( - run.getId(), clusterName, unit.getKeyspaceName(), - tables, segmentsRepaired, totalSegments, - run.getRunState(), run.getStartTime(), run.getEndTime(), run.getCause(), - run.getOwner(), run.getLastEvent())); + runStatuses.add(new RepairRunStatus( + run.getId(), clusterName, unit.getKeyspaceName(), unit.getColumnFamilies(), + segmentsRepaired, totalSegments, run.getRunState(), run.getStartTime(), + run.getEndTime(), run.getCause(), run.getOwner(), run.getLastEvent(), + run.getCreationTime(), run.getPauseTime(), run.getIntensity(), + run.getRepairParallelism())); } - return clusterRuns; + return runStatuses; } } diff --git a/src/main/java/com/spotify/reaper/storage/PostgresStorage.java b/src/main/java/com/spotify/reaper/storage/PostgresStorage.java index 7b1d9b065..b5601e2e9 100644 --- a/src/main/java/com/spotify/reaper/storage/PostgresStorage.java +++ b/src/main/java/com/spotify/reaper/storage/PostgresStorage.java @@ -23,7 +23,7 @@ import com.spotify.reaper.core.RepairSchedule; import com.spotify.reaper.core.RepairSegment; import com.spotify.reaper.core.RepairUnit; -import com.spotify.reaper.resources.view.ClusterRun; +import com.spotify.reaper.resources.view.RepairRunStatus; import com.spotify.reaper.service.RingRange; import com.spotify.reaper.storage.postgresql.BigIntegerArgumentFactory; import com.spotify.reaper.storage.postgresql.IStoragePostgreSQL; @@ -457,7 +457,7 @@ public Optional deleteRepairSchedule(long id) { return Optional.fromNullable(result); } - public Collection getClusterRunOverview(String clusterName, int limit) { + public Collection getClusterRunStatuses(String clusterName, int limit) { try (Handle h = jdbi.open()) { return getPostgresStorage(h).getClusterRunOverview(clusterName, limit); } diff --git a/src/main/java/com/spotify/reaper/storage/postgresql/IStoragePostgreSQL.java b/src/main/java/com/spotify/reaper/storage/postgresql/IStoragePostgreSQL.java index a6dda3bb9..d7a9e708a 100644 --- a/src/main/java/com/spotify/reaper/storage/postgresql/IStoragePostgreSQL.java +++ b/src/main/java/com/spotify/reaper/storage/postgresql/IStoragePostgreSQL.java @@ -18,7 +18,7 @@ import com.spotify.reaper.core.RepairSchedule; import com.spotify.reaper.core.RepairSegment; import com.spotify.reaper.core.RepairUnit; -import com.spotify.reaper.resources.view.ClusterRun; +import com.spotify.reaper.resources.view.RepairRunStatus; import org.skife.jdbi.v2.sqlobject.Bind; import org.skife.jdbi.v2.sqlobject.BindBean; @@ -175,7 +175,8 @@ public interface IStoragePostgreSQL { static final String SQL_CLUSTER_RUN_OVERVIEW = "SELECT repair_run.id, repair_unit.cluster_name, keyspace_name, column_families, " + "COUNT(repair_segment.id), segment_count, repair_run.state, repair_run.start_time, " - + "repair_run.end_time, cause, owner, last_event\n" + + "repair_run.end_time, cause, owner, last_event, " + + "creation_time, pause_time, intensity, repair_parallelism\n" + "FROM repair_run " + "JOIN repair_segment ON run_id = repair_run.id " + "JOIN repair_unit ON repair_run.repair_unit_id = repair_unit.id\n" @@ -320,8 +321,8 @@ int getSegmentAmountForRepairRunWithState( @SqlQuery(SQL_CLUSTER_RUN_OVERVIEW) - @Mapper(ClusterRun.Mapper.class) - List getClusterRunOverview( + @Mapper(RepairRunStatusMapper.class) + List getClusterRunOverview( @Bind("clusterName") String clusterName, @Bind("limit") int limit); } diff --git a/src/main/java/com/spotify/reaper/storage/postgresql/RepairRunStatusMapper.java b/src/main/java/com/spotify/reaper/storage/postgresql/RepairRunStatusMapper.java new file mode 100644 index 000000000..fb545e439 --- /dev/null +++ b/src/main/java/com/spotify/reaper/storage/postgresql/RepairRunStatusMapper.java @@ -0,0 +1,43 @@ +package com.spotify.reaper.storage.postgresql; + +import com.google.common.collect.ImmutableSet; + +import com.spotify.reaper.core.RepairRun; +import com.spotify.reaper.resources.view.RepairRunStatus; + +import org.apache.cassandra.repair.RepairParallelism; +import org.joda.time.DateTime; +import org.skife.jdbi.v2.StatementContext; +import org.skife.jdbi.v2.tweak.ResultSetMapper; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Collection; + +public class RepairRunStatusMapper implements ResultSetMapper { + + @Override + public RepairRunStatus map(int index, ResultSet r, StatementContext ctx) throws SQLException { + long runId = r.getLong("id"); + String clusterName = r.getString("cluster_name"); + String keyspaceName = r.getString("keyspace_name"); + Collection columnFamilies = + ImmutableSet.copyOf((String[]) r.getArray("column_families").getArray()); + int segmentsRepaired = (int)r.getLong("count"); + int totalSegments = r.getInt("segment_count"); + RepairRun.RunState state = RepairRun.RunState.valueOf(r.getString("state")); + DateTime startTime = RepairRunMapper.getDateTimeOrNull(r, "start_time"); + DateTime endTime = RepairRunMapper.getDateTimeOrNull(r, "end_time"); + String cause = r.getString("cause"); + String owner = r.getString("owner"); + String lastEvent = r.getString("last_event"); + DateTime creationTime = RepairRunMapper.getDateTimeOrNull(r, "creation_time"); + DateTime pauseTime = RepairRunMapper.getDateTimeOrNull(r, "pause_time"); + Double intensity = r.getDouble("intensity"); + RepairParallelism repairParallelism = + RepairParallelism.valueOf(r.getString("repair_parallelism")); + return new RepairRunStatus(runId, clusterName, keyspaceName, columnFamilies, segmentsRepaired, + totalSegments, state, startTime, endTime, cause, owner, lastEvent, + creationTime, pauseTime, intensity, repairParallelism); + } +}