Skip to content

Commit

Permalink
Added ConnectionCredentials (#92)
Browse files Browse the repository at this point in the history
Co-authored-by: ivan.vakhrushev <[email protected]>
  • Loading branch information
mfvanek and ivan.vakhrushev authored May 5, 2020
1 parent ef97245 commit 091051c
Show file tree
Hide file tree
Showing 15 changed files with 437 additions and 136 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
* Copyright (c) 2019-2020. Ivan Vakhrushev and others.
* https://github.com/mfvanek/pg-index-health
*
* This file is a part of "pg-index-health" - a Java library for
* analyzing and maintaining indexes health in PostgreSQL databases.
*
* Licensed under the Apache License 2.0
*/

package io.github.mfvanek.pg.common.health;

import io.github.mfvanek.pg.connection.HighAvailabilityPgConnection;

import javax.annotation.Nonnull;

public interface DatabaseHealthFactory {

@Nonnull
DatabaseHealth of(@Nonnull HighAvailabilityPgConnection haPgConnection);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* Copyright (c) 2019-2020. Ivan Vakhrushev and others.
* https://github.com/mfvanek/pg-index-health
*
* This file is a part of "pg-index-health" - a Java library for
* analyzing and maintaining indexes health in PostgreSQL databases.
*
* Licensed under the Apache License 2.0
*/

package io.github.mfvanek.pg.common.health;

import io.github.mfvanek.pg.common.maintenance.MaintenanceFactory;
import io.github.mfvanek.pg.connection.HighAvailabilityPgConnection;

import javax.annotation.Nonnull;
import java.util.Objects;

public class DatabaseHealthFactoryImpl implements DatabaseHealthFactory {

private final MaintenanceFactory maintenanceFactory;

public DatabaseHealthFactoryImpl(@Nonnull final MaintenanceFactory maintenanceFactory) {
this.maintenanceFactory = Objects.requireNonNull(maintenanceFactory);
}

@Nonnull
@Override
public DatabaseHealth of(@Nonnull HighAvailabilityPgConnection haPgConnection) {
return new DatabaseHealthImpl(haPgConnection, maintenanceFactory);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@
package io.github.mfvanek.pg.common.health.logger;

import io.github.mfvanek.pg.common.health.DatabaseHealth;
import io.github.mfvanek.pg.common.health.DatabaseHealthFactory;
import io.github.mfvanek.pg.connection.ConnectionCredentials;
import io.github.mfvanek.pg.connection.HighAvailabilityPgConnection;
import io.github.mfvanek.pg.connection.HighAvailabilityPgConnectionFactory;
import io.github.mfvanek.pg.model.BloatAware;
import io.github.mfvanek.pg.model.PgContext;
import io.github.mfvanek.pg.model.index.DuplicatedIndexes;
Expand Down Expand Up @@ -41,11 +45,17 @@ public abstract class AbstractHealthLogger implements HealthLogger {

private static final Logger LOGGER = LoggerFactory.getLogger(AbstractHealthLogger.class);

private final DatabaseHealth databaseHealth;
private final ConnectionCredentials credentials;
private final HighAvailabilityPgConnectionFactory connectionFactory;
private final DatabaseHealthFactory databaseHealthFactory;

@SuppressWarnings("WeakerAccess")
protected AbstractHealthLogger(@Nonnull final DatabaseHealth databaseHealth) {
this.databaseHealth = Objects.requireNonNull(databaseHealth);
protected AbstractHealthLogger(@Nonnull final ConnectionCredentials credentials,
@Nonnull final HighAvailabilityPgConnectionFactory connectionFactory,
@Nonnull final DatabaseHealthFactory databaseHealthFactory) {
this.credentials = Objects.requireNonNull(credentials);
this.connectionFactory = Objects.requireNonNull(connectionFactory);
this.databaseHealthFactory = Objects.requireNonNull(databaseHealthFactory);
}

/**
Expand All @@ -57,17 +67,19 @@ public final List<String> logAll(@Nonnull final Exclusions exclusions,
@Nonnull final PgContext pgContext) {
Objects.requireNonNull(exclusions);
Objects.requireNonNull(pgContext);
final HighAvailabilityPgConnection haPgConnection = connectionFactory.of(credentials);
final DatabaseHealth databaseHealth = databaseHealthFactory.of(haPgConnection);
final List<String> logResult = new ArrayList<>();
logResult.add(logInvalidIndexes(pgContext));
logResult.add(logDuplicatedIndexes(exclusions, pgContext));
logResult.add(logIntersectedIndexes(exclusions, pgContext));
logResult.add(logUnusedIndexes(exclusions, pgContext));
logResult.add(logForeignKeysNotCoveredWithIndex(pgContext));
logResult.add(logTablesWithMissingIndexes(exclusions, pgContext));
logResult.add(logTablesWithoutPrimaryKey(exclusions, pgContext));
logResult.add(logIndexesWithNullValues(exclusions, pgContext));
logResult.add(logIndexesBloat(exclusions, pgContext));
logResult.add(logTablesBloat(exclusions, pgContext));
logResult.add(logInvalidIndexes(databaseHealth, pgContext));
logResult.add(logDuplicatedIndexes(databaseHealth, exclusions, pgContext));
logResult.add(logIntersectedIndexes(databaseHealth, exclusions, pgContext));
logResult.add(logUnusedIndexes(databaseHealth, exclusions, pgContext));
logResult.add(logForeignKeysNotCoveredWithIndex(databaseHealth, pgContext));
logResult.add(logTablesWithMissingIndexes(databaseHealth, exclusions, pgContext));
logResult.add(logTablesWithoutPrimaryKey(databaseHealth, exclusions, pgContext));
logResult.add(logIndexesWithNullValues(databaseHealth, exclusions, pgContext));
logResult.add(logIndexesBloat(databaseHealth, exclusions, pgContext));
logResult.add(logTablesBloat(databaseHealth, exclusions, pgContext));
return logResult;
}

Expand All @@ -79,7 +91,8 @@ private String writeZeroToLog(@Nonnull final LoggingKey key) {
}

@Nonnull
private String logInvalidIndexes(@Nonnull final PgContext pgContext) {
private String logInvalidIndexes(@Nonnull final DatabaseHealth databaseHealth,
@Nonnull final PgContext pgContext) {
final List<Index> invalidIndexes = databaseHealth.getInvalidIndexes(pgContext);
final LoggingKey key = SimpleLoggingKey.INVALID_INDEXES;
if (CollectionUtils.isNotEmpty(invalidIndexes)) {
Expand All @@ -90,7 +103,8 @@ private String logInvalidIndexes(@Nonnull final PgContext pgContext) {
}

@Nonnull
private String logDuplicatedIndexes(@Nonnull final Exclusions exclusions,
private String logDuplicatedIndexes(@Nonnull final DatabaseHealth databaseHealth,
@Nonnull final Exclusions exclusions,
@Nonnull final PgContext pgContext) {
final List<DuplicatedIndexes> rawDuplicatedIndexes = databaseHealth.getDuplicatedIndexes(pgContext);
final List<DuplicatedIndexes> duplicatedIndexes = applyExclusions(rawDuplicatedIndexes,
Expand All @@ -104,7 +118,8 @@ private String logDuplicatedIndexes(@Nonnull final Exclusions exclusions,
}

@Nonnull
private String logIntersectedIndexes(@Nonnull final Exclusions exclusions,
private String logIntersectedIndexes(@Nonnull final DatabaseHealth databaseHealth,
@Nonnull final Exclusions exclusions,
@Nonnull final PgContext pgContext) {
final List<DuplicatedIndexes> rawIntersectedIndexes = databaseHealth.getIntersectedIndexes(pgContext);
final List<DuplicatedIndexes> intersectedIndexes = applyExclusions(rawIntersectedIndexes,
Expand All @@ -118,7 +133,8 @@ private String logIntersectedIndexes(@Nonnull final Exclusions exclusions,
}

@Nonnull
private String logUnusedIndexes(@Nonnull final Exclusions exclusions,
private String logUnusedIndexes(@Nonnull final DatabaseHealth databaseHealth,
@Nonnull final Exclusions exclusions,
@Nonnull final PgContext pgContext) {
final List<UnusedIndex> rawUnusedIndexes = databaseHealth.getUnusedIndexes(pgContext);
final List<UnusedIndex> filteredUnusedIndexes = applyIndexesExclusions(
Expand All @@ -134,7 +150,8 @@ private String logUnusedIndexes(@Nonnull final Exclusions exclusions,
}

@Nonnull
private String logForeignKeysNotCoveredWithIndex(@Nonnull final PgContext pgContext) {
private String logForeignKeysNotCoveredWithIndex(@Nonnull final DatabaseHealth databaseHealth,
@Nonnull final PgContext pgContext) {
final List<ForeignKey> foreignKeys = databaseHealth.getForeignKeysNotCoveredWithIndex(pgContext);
final LoggingKey key = SimpleLoggingKey.FOREIGN_KEYS;
if (CollectionUtils.isNotEmpty(foreignKeys)) {
Expand All @@ -145,9 +162,11 @@ private String logForeignKeysNotCoveredWithIndex(@Nonnull final PgContext pgCont
}

@Nonnull
private String logTablesWithMissingIndexes(@Nonnull final Exclusions exclusions,
private String logTablesWithMissingIndexes(@Nonnull final DatabaseHealth databaseHealth,
@Nonnull final Exclusions exclusions,
@Nonnull final PgContext pgContext) {
final List<TableWithMissingIndex> rawTablesWithMissingIndexes = databaseHealth.getTablesWithMissingIndexes(pgContext);
final List<TableWithMissingIndex> rawTablesWithMissingIndexes =
databaseHealth.getTablesWithMissingIndexes(pgContext);
final List<TableWithMissingIndex> tablesFilteredBySize = applyTableSizeExclusions(
rawTablesWithMissingIndexes, exclusions.getTableSizeThresholdInBytes());
final List<TableWithMissingIndex> tablesWithMissingIndexes = applyTablesExclusions(
Expand All @@ -161,7 +180,8 @@ private String logTablesWithMissingIndexes(@Nonnull final Exclusions exclusions,
}

@Nonnull
private String logTablesWithoutPrimaryKey(@Nonnull final Exclusions exclusions,
private String logTablesWithoutPrimaryKey(@Nonnull final DatabaseHealth databaseHealth,
@Nonnull final Exclusions exclusions,
@Nonnull final PgContext pgContext) {
final List<Table> rawTablesWithoutPrimaryKey = databaseHealth.getTablesWithoutPrimaryKey(pgContext);
final List<Table> tablesFilteredBySize = applyTableSizeExclusions(
Expand All @@ -177,7 +197,8 @@ private String logTablesWithoutPrimaryKey(@Nonnull final Exclusions exclusions,
}

@Nonnull
private String logIndexesWithNullValues(@Nonnull final Exclusions exclusions,
private String logIndexesWithNullValues(@Nonnull final DatabaseHealth databaseHealth,
@Nonnull final Exclusions exclusions,
@Nonnull final PgContext pgContext) {
final List<IndexWithNulls> rawIndexesWithNullValues = databaseHealth.getIndexesWithNullValues(pgContext);
final List<IndexWithNulls> indexesWithNullValues = applyIndexesExclusions(rawIndexesWithNullValues,
Expand All @@ -191,7 +212,8 @@ private String logIndexesWithNullValues(@Nonnull final Exclusions exclusions,
}

@Nonnull
private String logIndexesBloat(@Nonnull final Exclusions exclusions,
private String logIndexesBloat(@Nonnull final DatabaseHealth databaseHealth,
@Nonnull final Exclusions exclusions,
@Nonnull final PgContext pgContext) {
final List<IndexWithBloat> rawIndexesWithBloat = databaseHealth.getIndexesWithBloat(pgContext);
final List<IndexWithBloat> filteredIndexesWithBloat = applyIndexSizeExclusions(
Expand All @@ -207,7 +229,8 @@ private String logIndexesBloat(@Nonnull final Exclusions exclusions,
}

@Nonnull
private String logTablesBloat(@Nonnull final Exclusions exclusions,
private String logTablesBloat(@Nonnull final DatabaseHealth databaseHealth,
@Nonnull final Exclusions exclusions,
@Nonnull final PgContext pgContext) {
final List<TableWithBloat> rawTablesWithBloat = databaseHealth.getTablesWithBloat(pgContext);
final List<TableWithBloat> filteredTablesWithBloat = applyTableSizeExclusions(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@

package io.github.mfvanek.pg.common.health.logger;

import io.github.mfvanek.pg.common.health.DatabaseHealth;
import io.github.mfvanek.pg.common.health.DatabaseHealthFactory;
import io.github.mfvanek.pg.connection.ConnectionCredentials;
import io.github.mfvanek.pg.connection.HighAvailabilityPgConnectionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand All @@ -22,8 +24,10 @@ public class SimpleHealthLogger extends AbstractHealthLogger {

private static final Logger KV_LOG = LoggerFactory.getLogger("key-value.log");

public SimpleHealthLogger(@Nonnull final DatabaseHealth databaseHealth) {
super(databaseHealth);
public SimpleHealthLogger(@Nonnull final ConnectionCredentials credentials,
@Nonnull final HighAvailabilityPgConnectionFactory connectionFactory,
@Nonnull final DatabaseHealthFactory databaseHealthFactory) {
super(credentials, connectionFactory, databaseHealthFactory);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
/*
* Copyright (c) 2019-2020. Ivan Vakhrushev and others.
* https://github.com/mfvanek/pg-index-health
*
* This file is a part of "pg-index-health" - a Java library for
* analyzing and maintaining indexes health in PostgreSQL databases.
*
* Licensed under the Apache License 2.0
*/

package io.github.mfvanek.pg.connection;

import javax.annotation.Nonnull;
import java.util.Collection;
import java.util.Collections;
import java.util.Objects;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;

/**
* Parameters for connecting to the database.
*
* @author Ivan Vakhrushev
*/
public class ConnectionCredentials {

private final SortedSet<String> connectionUrls;
private final String userName;
private final String password;

private ConnectionCredentials(@Nonnull final Collection<String> connectionUrls,
@Nonnull final String userName,
@Nonnull final String password) {
PgConnectionValidators.connectionUrlsNotEmptyAndValid(connectionUrls);
this.connectionUrls = Collections.unmodifiableSortedSet(new TreeSet<>(connectionUrls));
this.userName = PgConnectionValidators.userNameNotBlank(userName);
this.password = PgConnectionValidators.passwordNotBlank(password);
}

/**
* Gets a set of connection strings for accessing all hosts in the database cluster.
*
* @return connection urls
*/
@Nonnull
public Collection<String> getConnectionUrls() {
return connectionUrls;
}

/**
* Gets the name of the user to connect to the database.
*
* @return the name of the user
*/
@Nonnull
public String getUserName() {
return userName;
}

/**
* Gets the user's password for connecting to the database.
*
* @return the user's password
*/
@Nonnull
public String getPassword() {
return password;
}

@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}

if (o == null || getClass() != o.getClass()) {
return false;
}

final ConnectionCredentials that = (ConnectionCredentials) o;
return Objects.equals(connectionUrls, that.connectionUrls) &&
Objects.equals(userName, that.userName) &&
Objects.equals(password, that.password);
}

@Override
public int hashCode() {
return Objects.hash(connectionUrls, userName, password);
}

@Override
public String toString() {
return ConnectionCredentials.class.getSimpleName() + '{' +
"connectionUrls=" + connectionUrls +
", userName='" + userName + '\'' +
", password='" + password + '\'' +
'}';
}

@Nonnull
public static ConnectionCredentials of(@Nonnull final Collection<String> connectionUrls,
@Nonnull final String userName,
@Nonnull final String password) {
return new ConnectionCredentials(connectionUrls, userName, password);
}

@Nonnull
public static ConnectionCredentials ofUrl(@Nonnull final String writeUrl,
@Nonnull final String userName,
@Nonnull final String password) {
final Set<String> connectionUrls = Collections.singleton(
PgConnectionValidators.pgUrlNotBlankAndValid(writeUrl, "writeUrl"));
return new ConnectionCredentials(connectionUrls, userName, password);
}
}
Loading

0 comments on commit 091051c

Please sign in to comment.