From 8de013998566f526c076adfd27e5afeccabe6fe6 Mon Sep 17 00:00:00 2001 From: Hannu Varjoranta Date: Tue, 16 Dec 2014 12:48:17 +0100 Subject: [PATCH] fixed Postgres related storage issues * added getKeyspaces method to JmxProxy --- src/main/db/reaper_db.sql | 3 ++ .../spotify/reaper/cassandra/JmxProxy.java | 9 +++++ .../java/com/spotify/reaper/core/Cluster.java | 6 +++- .../reaper/resources/ClusterResource.java | 3 +- .../reaper/storage/PostgresStorage.java | 4 +++ .../postgresql/IStoragePostgreSQL.java | 4 +-- .../PostgresArrayArgumentFactory.java | 34 +++++++++++++++++++ src/test/resources/cassandra-reaper.yaml | 1 + 8 files changed, 60 insertions(+), 4 deletions(-) create mode 100644 src/main/java/com/spotify/reaper/storage/postgresql/PostgresArrayArgumentFactory.java diff --git a/src/main/db/reaper_db.sql b/src/main/db/reaper_db.sql index d0e9c036e..64a94d2d4 100644 --- a/src/main/db/reaper_db.sql +++ b/src/main/db/reaper_db.sql @@ -56,5 +56,8 @@ CREATE INDEX "repair_segment_state_idx" ON "repair_segment" USING BTREE ("state" GRANT SELECT, INSERT, UPDATE, DELETE ON TABLE cluster TO reaper; GRANT SELECT, INSERT, UPDATE, DELETE ON TABLE column_family TO reaper; +GRANT USAGE, SELECT ON SEQUENCE column_family_id_seq TO reaper; GRANT SELECT, INSERT, UPDATE, DELETE ON TABLE repair_run TO reaper; +GRANT USAGE, SELECT ON SEQUENCE repair_run_id_seq TO reaper; GRANT SELECT, INSERT, UPDATE, DELETE ON TABLE repair_segment TO reaper; +GRANT USAGE, SELECT ON SEQUENCE repair_segment_id_seq TO reaper; diff --git a/src/main/java/com/spotify/reaper/cassandra/JmxProxy.java b/src/main/java/com/spotify/reaper/cassandra/JmxProxy.java index 89287d37d..93a91c3e7 100644 --- a/src/main/java/com/spotify/reaper/cassandra/JmxProxy.java +++ b/src/main/java/com/spotify/reaper/cassandra/JmxProxy.java @@ -28,6 +28,7 @@ import java.io.Serializable; import java.math.BigInteger; import java.net.MalformedURLException; +import java.util.Arrays; import java.util.List; import javax.annotation.Nullable; @@ -159,6 +160,14 @@ public String getClusterName() { return toSymbolicName(ssProxy.getClusterName()); } + /** + * @return list of available keyspaces + */ + public List getKeySpaces() { + checkNotNull(ssProxy, "Looks like the proxy is not connected"); + return ssProxy.getKeyspaces(); + } + /** * Triggers a repair of range (beginToken, endToken] for given keyspace and column family. * diff --git a/src/main/java/com/spotify/reaper/core/Cluster.java b/src/main/java/com/spotify/reaper/core/Cluster.java index d4cc50a3d..4ead5addc 100644 --- a/src/main/java/com/spotify/reaper/core/Cluster.java +++ b/src/main/java/com/spotify/reaper/core/Cluster.java @@ -21,7 +21,11 @@ public class Cluster { @JsonProperty private final String name; - private final String partitioner; // Name of the partitioner class + + @JsonProperty + private final String partitioner; // Full name of the partitioner class + + @JsonProperty private final Set seedHosts; public String getName() { diff --git a/src/main/java/com/spotify/reaper/resources/ClusterResource.java b/src/main/java/com/spotify/reaper/resources/ClusterResource.java index cbd1e4dd8..45b0c05d5 100644 --- a/src/main/java/com/spotify/reaper/resources/ClusterResource.java +++ b/src/main/java/com/spotify/reaper/resources/ClusterResource.java @@ -23,10 +23,12 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.math.BigInteger; import java.net.URI; import java.net.URL; import java.util.Collection; import java.util.Collections; +import java.util.List; import javax.ws.rs.GET; import javax.ws.rs.POST; @@ -52,7 +54,6 @@ public ClusterResource(IStorage storage) { } @GET - @Path("/") public Response getClusterList() { LOG.info("get cluster list called"); Collection clusters = storage.getClusters(); diff --git a/src/main/java/com/spotify/reaper/storage/PostgresStorage.java b/src/main/java/com/spotify/reaper/storage/PostgresStorage.java index a3d0cd3a7..0ac41e8f8 100644 --- a/src/main/java/com/spotify/reaper/storage/PostgresStorage.java +++ b/src/main/java/com/spotify/reaper/storage/PostgresStorage.java @@ -21,6 +21,7 @@ import com.spotify.reaper.core.RepairSegment; import com.spotify.reaper.service.RingRange; import com.spotify.reaper.storage.postgresql.IStoragePostgreSQL; +import com.spotify.reaper.storage.postgresql.PostgresArrayArgumentFactory; import org.skife.jdbi.v2.DBI; import org.skife.jdbi.v2.Handle; @@ -82,6 +83,7 @@ public Collection getClusters() { @Override public Cluster addCluster(Cluster newCluster) { Handle h = jdbi.open(); + h.registerArgumentFactory(new PostgresArrayArgumentFactory()); IStoragePostgreSQL postgres = h.attach(IStoragePostgreSQL.class); int rowsAdded = postgres.insertCluster(newCluster); h.close(); @@ -95,6 +97,7 @@ public Cluster addCluster(Cluster newCluster) { @Override public boolean updateCluster(Cluster cluster) { Handle h = jdbi.open(); + h.registerArgumentFactory(new PostgresArrayArgumentFactory()); IStoragePostgreSQL postgres = h.attach(IStoragePostgreSQL.class); int rowsAdded = postgres.updateCluster(cluster); h.close(); @@ -114,6 +117,7 @@ public RepairRun getRepairRun(long id) { @Override public RepairRun addRepairRun(RepairRun.Builder newRepairRun) { Handle h = jdbi.open(); + h.registerArgumentFactory(new PostgresArrayArgumentFactory()); IStoragePostgreSQL postgres = h.attach(IStoragePostgreSQL.class); long insertedId = postgres.insertRepairRun(newRepairRun.build(-1)); h.close(); 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 79f2560cc..dab712b4a 100644 --- a/src/main/java/com/spotify/reaper/storage/postgresql/IStoragePostgreSQL.java +++ b/src/main/java/com/spotify/reaper/storage/postgresql/IStoragePostgreSQL.java @@ -75,7 +75,7 @@ public interface IStoragePostgreSQL { // static final String SQL_INSERT_REPAIR_RUN = "INSERT INTO repair_run (cause, owner, state, creation_time, start_time, end_time) " - + "VALUES (:cause, :owner, :state, :creationTime, :startTime, :endTime) RETURNING id"; + + "VALUES (:cause, :owner, :state, :creationTime, :startTime, :endTime)"; static final String SQL_UPDATE_REPAIR_RUN = "UPDATE repair_run SET cause = :cause, owner = :owner, state = :state, " @@ -101,7 +101,7 @@ public interface IStoragePostgreSQL { static final String SQL_INSERT_COLUMN_FAMILY = "INSERT INTO column_family (cluster_name, keyspace_name, name, segment_count, " + "snapshot_repair) VALUES (:clusterName, :keyspaceName, :name, :segmentCount, " - + ":snapshotRepair) RETURNING id"; + + ":snapshotRepair)"; static final String SQL_GET_COLUMN_FAMILY = "SELECT id, cluster_name, keyspace_name, name, segment_count, snapshot_repair " diff --git a/src/main/java/com/spotify/reaper/storage/postgresql/PostgresArrayArgumentFactory.java b/src/main/java/com/spotify/reaper/storage/postgresql/PostgresArrayArgumentFactory.java new file mode 100644 index 000000000..23a4142a7 --- /dev/null +++ b/src/main/java/com/spotify/reaper/storage/postgresql/PostgresArrayArgumentFactory.java @@ -0,0 +1,34 @@ +package com.spotify.reaper.storage.postgresql; + +import org.skife.jdbi.v2.StatementContext; +import org.skife.jdbi.v2.tweak.Argument; +import org.skife.jdbi.v2.tweak.ArgumentFactory; + +import java.sql.Array; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.util.Collection; + +/** + * Required as we are using JDBI, and it cannot do Array binding otherwise, duh. + */ +public class PostgresArrayArgumentFactory implements ArgumentFactory> { + + @Override + public boolean accepts(Class expectedType, Object value, StatementContext ctx) { + return value instanceof Collection; + } + + @Override + public Argument build(Class expectedType, final Collection value, + StatementContext ctx) { + return new Argument() { + public void apply(int position, + PreparedStatement statement, + StatementContext ctx) throws SQLException { + Array sqlArray = ctx.getConnection().createArrayOf("text", value.toArray()); + statement.setArray(position, sqlArray); + } + }; + } +} diff --git a/src/test/resources/cassandra-reaper.yaml b/src/test/resources/cassandra-reaper.yaml index 5f18a7dcd..2ecbe11ce 100644 --- a/src/test/resources/cassandra-reaper.yaml +++ b/src/test/resources/cassandra-reaper.yaml @@ -7,6 +7,7 @@ logging: level: DEBUG loggers: io.dropwizard: INFO + org.eclipse.jetty: INFO appenders: - type: console