Skip to content

Commit

Permalink
Merge pull request #845 from CDCgov/devex-753/connection_pooling
Browse files Browse the repository at this point in the history
Devex 753/connection pooling
  • Loading branch information
halprin authored Feb 6, 2024
2 parents 4e206a0 + 78a1033 commit c5d07b3
Show file tree
Hide file tree
Showing 20 changed files with 205 additions and 447 deletions.
19 changes: 19 additions & 0 deletions adr/017-connection-pooling.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# 17. Connection Pooling

Date: 2024-02-02

## Decision

We will use HikariCP for connection pooling because of the quality of documentation, and the significant margin in performance above the other available options. It is also still receiving active support and updates from the owners.

## Status

Accepted

## Context
Connection pooling is vital to the project for many reasons including resource management and conservation, performance improvement, latency reduction, scalability, and most importantly here managing connections.


### Related Issues

- 753
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,16 @@
import gov.hhs.cdc.trustedintermediary.domainconnector.DomainConnectorConstructionException;
import gov.hhs.cdc.trustedintermediary.domainconnector.DomainResponseHelper;
import gov.hhs.cdc.trustedintermediary.domainconnector.UnableToReadOpenApiSpecificationException;
import gov.hhs.cdc.trustedintermediary.external.HikariConnectionPool;
import gov.hhs.cdc.trustedintermediary.external.apache.ApacheClient;
import gov.hhs.cdc.trustedintermediary.external.azure.AzureDatabaseCredentialsProvider;
import gov.hhs.cdc.trustedintermediary.external.azure.AzureSecrets;
import gov.hhs.cdc.trustedintermediary.external.hapi.HapiFhirImplementation;
import gov.hhs.cdc.trustedintermediary.external.inmemory.KeyCache;
import gov.hhs.cdc.trustedintermediary.external.inmemory.LoggingMetricMetadata;
import gov.hhs.cdc.trustedintermediary.external.jackson.Jackson;
import gov.hhs.cdc.trustedintermediary.external.jjwt.JjwtEngine;
import gov.hhs.cdc.trustedintermediary.external.localfile.EnvironmentDatabaseCredentialsProvider;
import gov.hhs.cdc.trustedintermediary.external.localfile.LocalSecrets;
import gov.hhs.cdc.trustedintermediary.external.slf4j.DeployedLogger;
import gov.hhs.cdc.trustedintermediary.external.slf4j.LocalLogger;
Expand All @@ -25,6 +28,8 @@
import gov.hhs.cdc.trustedintermediary.wrappers.MetricMetadata;
import gov.hhs.cdc.trustedintermediary.wrappers.Secrets;
import gov.hhs.cdc.trustedintermediary.wrappers.YamlCombiner;
import gov.hhs.cdc.trustedintermediary.wrappers.database.ConnectionPool;
import gov.hhs.cdc.trustedintermediary.wrappers.database.DatabaseCredentialsProvider;
import gov.hhs.cdc.trustedintermediary.wrappers.formatter.Formatter;
import io.javalin.Javalin;
import java.util.Set;
Expand Down Expand Up @@ -87,5 +92,17 @@ private static void registerClasses() {
ApplicationContext.register(
OrganizationsSettings.class, OrganizationsSettings.getInstance());
ApplicationContext.register(MetricMetadata.class, LoggingMetricMetadata.getInstance());
if (ApplicationContext.getProperty("DB_URL") != null) {
if (ApplicationContext.getEnvironment().equalsIgnoreCase("local")) {
ApplicationContext.register(
DatabaseCredentialsProvider.class,
EnvironmentDatabaseCredentialsProvider.getInstance());
} else {
ApplicationContext.register(
DatabaseCredentialsProvider.class,
AzureDatabaseCredentialsProvider.getInstance());
}
ApplicationContext.register(ConnectionPool.class, HikariConnectionPool.getInstance());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,10 @@
import gov.hhs.cdc.trustedintermediary.etor.results.ResultResponse;
import gov.hhs.cdc.trustedintermediary.etor.results.ResultSender;
import gov.hhs.cdc.trustedintermediary.etor.results.SendResultUseCase;
import gov.hhs.cdc.trustedintermediary.external.azure.AzureClient;
import gov.hhs.cdc.trustedintermediary.external.azure.AzureDatabaseCredentialsProvider;
import gov.hhs.cdc.trustedintermediary.external.azure.AzureStorageAccountPartnerMetadataStorage;
import gov.hhs.cdc.trustedintermediary.external.database.DatabaseCredentialsProvider;
import gov.hhs.cdc.trustedintermediary.external.database.DatabasePartnerMetadataStorage;
import gov.hhs.cdc.trustedintermediary.external.database.DbDao;
import gov.hhs.cdc.trustedintermediary.external.database.EtorSqlDriverManager;
import gov.hhs.cdc.trustedintermediary.external.database.PostgresDao;
import gov.hhs.cdc.trustedintermediary.external.hapi.HapiOrderConverter;
import gov.hhs.cdc.trustedintermediary.external.localfile.EnvironmentDatabaseCredentialsProvider;
import gov.hhs.cdc.trustedintermediary.external.localfile.FilePartnerMetadataStorage;
import gov.hhs.cdc.trustedintermediary.external.localfile.MockRSEndpointClient;
import gov.hhs.cdc.trustedintermediary.external.reportstream.ReportStreamEndpointClient;
Expand All @@ -46,7 +40,6 @@
import gov.hhs.cdc.trustedintermediary.wrappers.FhirParseException;
import gov.hhs.cdc.trustedintermediary.wrappers.HapiFhir;
import gov.hhs.cdc.trustedintermediary.wrappers.Logger;
import gov.hhs.cdc.trustedintermediary.wrappers.SqlDriverManager;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
Expand Down Expand Up @@ -113,36 +106,20 @@ public Map<HttpEndpoint, Function<DomainRequest, DomainResponse>> domainRegistra
ApplicationContext.register(SendResultUseCase.class, SendResultUseCase.getInstance());

if (ApplicationContext.getProperty("DB_URL") != null) {
ApplicationContext.register(SqlDriverManager.class, EtorSqlDriverManager.getInstance());
ApplicationContext.register(DbDao.class, PostgresDao.getInstance());
ApplicationContext.register(
PartnerMetadataStorage.class, DatabasePartnerMetadataStorage.getInstance());
if (ApplicationContext.getEnvironment().equalsIgnoreCase("local")) {
ApplicationContext.register(
DatabaseCredentialsProvider.class,
EnvironmentDatabaseCredentialsProvider.getInstance());
} else {
ApplicationContext.register(
DatabaseCredentialsProvider.class,
AzureDatabaseCredentialsProvider.getInstance());
}
} else if (ApplicationContext.getEnvironment().equalsIgnoreCase("local")) {
ApplicationContext.register(
PartnerMetadataStorage.class, FilePartnerMetadataStorage.getInstance());
} else {
ApplicationContext.register(
PartnerMetadataStorage.class,
AzureStorageAccountPartnerMetadataStorage.getInstance());
}

if (ApplicationContext.getEnvironment().equalsIgnoreCase("local")) {
ApplicationContext.register(RSEndpointClient.class, MockRSEndpointClient.getInstance());
} else {
ApplicationContext.register(
RSEndpointClient.class, ReportStreamEndpointClient.getInstance());

ApplicationContext.register(AzureClient.class, AzureClient.getInstance());
}

return endpoints;
}

Expand Down

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
package gov.hhs.cdc.trustedintermediary.external.database;

import gov.hhs.cdc.trustedintermediary.context.ApplicationContext;
import gov.hhs.cdc.trustedintermediary.etor.metadata.partner.PartnerMetadata;
import gov.hhs.cdc.trustedintermediary.etor.metadata.partner.PartnerMetadataStatus;
import gov.hhs.cdc.trustedintermediary.wrappers.Logger;
import gov.hhs.cdc.trustedintermediary.wrappers.SqlDriverManager;
import gov.hhs.cdc.trustedintermediary.wrappers.database.ConnectionPool;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
Expand All @@ -13,7 +11,6 @@
import java.sql.Types;
import java.time.Instant;
import java.util.HashSet;
import java.util.Properties;
import java.util.Set;
import javax.inject.Inject;

Expand All @@ -22,56 +19,16 @@ public class PostgresDao implements DbDao {

private static final PostgresDao INSTANCE = new PostgresDao();

@Inject Logger logger;
@Inject SqlDriverManager driverManager;
@Inject DatabaseCredentialsProvider credentialsProvider;
@Inject ConnectionPool connectionPool;

private PostgresDao() {}

protected Connection connect() throws SQLException {
Connection conn;
String url =
"jdbc:postgresql://"
+ ApplicationContext.getProperty("DB_URL")
+ ":"
+ ApplicationContext.getProperty("DB_PORT")
+ "/"
+ ApplicationContext.getProperty("DB_NAME");

logger.logInfo("going to connect to db url {}", url);

// Ternaries prevent NullPointerException during testing since we decided not to mock env
// vars.
String user =
ApplicationContext.getProperty("DB_USER") == null
? ""
: ApplicationContext.getProperty("DB_USER");

String pass = credentialsProvider.getPassword();

String ssl =
ApplicationContext.getProperty("DB_SSL") == null
? ""
: ApplicationContext.getProperty("DB_SSL");

Properties props = new Properties();
props.setProperty("user", user);
props.setProperty("password", pass);

// If the below prop isn't set to require and we just set ssl=true it will expect a CA cert
// in azure which breaks it
props.setProperty("ssl", ssl);
conn = driverManager.getConnection(url, props);
logger.logInfo("DB Connected Successfully");
return conn;
}

public static PostgresDao getInstance() {
return INSTANCE;
}

@Override
public synchronized void upsertMetadata(
public void upsertMetadata(
String receivedSubmissionId,
String sentSubmissionId,
String sender,
Expand All @@ -83,7 +40,7 @@ public synchronized void upsertMetadata(
String failureReason)
throws SQLException {

try (Connection conn = connect();
try (Connection conn = connectionPool.getConnection();
PreparedStatement statement =
conn.prepareStatement(
"""
Expand Down Expand Up @@ -124,10 +81,9 @@ ON CONFLICT (received_message_id) DO UPDATE SET receiver = EXCLUDED.receiver, se
}

@Override
public synchronized Set<PartnerMetadata> fetchMetadataForSender(String sender)
throws SQLException {
public Set<PartnerMetadata> fetchMetadataForSender(String sender) throws SQLException {

try (Connection conn = connect();
try (Connection conn = connectionPool.getConnection();
PreparedStatement statement =
conn.prepareStatement("SELECT * FROM metadata WHERE sender = ?")) {
statement.setString(1, sender);
Expand All @@ -144,8 +100,8 @@ public synchronized Set<PartnerMetadata> fetchMetadataForSender(String sender)
}

@Override
public synchronized PartnerMetadata fetchMetadata(String submissionId) throws SQLException {
try (Connection conn = connect();
public PartnerMetadata fetchMetadata(String submissionId) throws SQLException {
try (Connection conn = connectionPool.getConnection();
PreparedStatement statement =
conn.prepareStatement(
"SELECT * FROM metadata where received_message_id = ? OR sent_message_id = ?")) {
Expand Down
Loading

0 comments on commit c5d07b3

Please sign in to comment.