diff --git a/Package.resolved b/Package.resolved
index 8a3152b..0289bc7 100644
--- a/Package.resolved
+++ b/Package.resolved
@@ -27,6 +27,33 @@
"version" : "4.14.1"
}
},
+ {
+ "identity" : "fluent",
+ "kind" : "remoteSourceControl",
+ "location" : "https://github.com/vapor/fluent.git",
+ "state" : {
+ "revision" : "a586a5d4164f23a0ee4e02e1f467b9bbef0c9f1c",
+ "version" : "4.9.0"
+ }
+ },
+ {
+ "identity" : "fluent-kit",
+ "kind" : "remoteSourceControl",
+ "location" : "https://github.com/vapor/fluent-kit.git",
+ "state" : {
+ "revision" : "6cef8533c9ab87865de58fa3c6e6317e3e09857a",
+ "version" : "1.45.1"
+ }
+ },
+ {
+ "identity" : "fluent-postgres-driver",
+ "kind" : "remoteSourceControl",
+ "location" : "https://github.com/vapor/fluent-postgres-driver.git",
+ "state" : {
+ "revision" : "a538fc647f82d915eb84e0a12ca9b08c513e57c4",
+ "version" : "2.8.0"
+ }
+ },
{
"identity" : "multipart-kit",
"kind" : "remoteSourceControl",
@@ -36,6 +63,24 @@
"version" : "4.6.0"
}
},
+ {
+ "identity" : "postgres-kit",
+ "kind" : "remoteSourceControl",
+ "location" : "https://github.com/vapor/postgres-kit.git",
+ "state" : {
+ "revision" : "80ab7737dac4fccd4a8ad38743828dcb71ba7ac8",
+ "version" : "2.12.2"
+ }
+ },
+ {
+ "identity" : "postgres-nio",
+ "kind" : "remoteSourceControl",
+ "location" : "https://github.com/vapor/postgres-nio.git",
+ "state" : {
+ "revision" : "fa3137d39bca84843739db1c5a3db2d7f4ae65e6",
+ "version" : "1.20.0"
+ }
+ },
{
"identity" : "routing-kit",
"kind" : "remoteSourceControl",
@@ -45,6 +90,15 @@
"version" : "4.9.0"
}
},
+ {
+ "identity" : "sql-kit",
+ "kind" : "remoteSourceControl",
+ "location" : "https://github.com/vapor/sql-kit.git",
+ "state" : {
+ "revision" : "b2f128cb62a3abfbb1e3b2893ff3ee69e70f4f0f",
+ "version" : "3.28.0"
+ }
+ },
{
"identity" : "swift-algorithms",
"kind" : "remoteSourceControl",
diff --git a/Package.swift b/Package.swift
index 7479a9e..ce7999f 100644
--- a/Package.swift
+++ b/Package.swift
@@ -16,7 +16,11 @@ let package = Package(
],
dependencies: [
// 💧 A server-side Swift web framework.
- .package(url: "https://github.com/vapor/vapor.git", from: "4.0.0")
+ .package(url: "https://github.com/vapor/vapor.git", from: "4.0.0"),
+ // 🖋 Swift ORM (queries, models, and relations) for NoSQL and SQL databases.
+ .package(url: "https://github.com/vapor/fluent.git", from: "4.1.0"),
+ // 🐘 Swift ORM (queries, models, relations, etc) built on PostgreSQL.
+ .package(url: "https://github.com/vapor/fluent-postgres-driver.git", from: "2.1.1")
],
targets: [
// Targets are the basic building blocks of a package, defining a module or a test suite.
@@ -24,7 +28,9 @@ let package = Package(
.target(
name: "AppHealthChecks",
dependencies: [
- .product(name: "Vapor", package: "vapor")
+ .product(name: "Vapor", package: "vapor"),
+ .product(name: "Fluent", package: "fluent"),
+ .product(name: "FluentPostgresDriver", package: "fluent-postgres-driver")
]
),
.testTarget(
diff --git a/Sources/AppHealthChecks/HealthChecks.ApplicationStatus/AppHealthChecks.swift b/Sources/AppHealthChecks/ApplicationHealthChecks/AppHealthChecks.swift
similarity index 100%
rename from Sources/AppHealthChecks/HealthChecks.ApplicationStatus/AppHealthChecks.swift
rename to Sources/AppHealthChecks/ApplicationHealthChecks/AppHealthChecks.swift
diff --git a/Sources/AppHealthChecks/ChecksProtocol.swift b/Sources/AppHealthChecks/ChecksProtocol.swift
new file mode 100644
index 0000000..0324c0a
--- /dev/null
+++ b/Sources/AppHealthChecks/ChecksProtocol.swift
@@ -0,0 +1,33 @@
+// FS App Health Checks
+// Copyright (C) 2024 FREEDOM SPACE, LLC
+
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published
+// by the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+//
+// ChecksProtocol.swift
+//
+//
+// Created by Mykola Buhaiov on 06.02.2024.
+//
+
+import Vapor
+
+/// Groups func for get health check
+public protocol ChecksProtocol {
+ /// Check with setup options
+ /// - Parameter options: array of `MeasurementType`
+ /// - Returns: dictionary `[String: HealthCheckItem]`
+ func checkHealth(for options: [MeasurementType]) async -> [String: HealthCheckItem]
+}
diff --git a/Sources/AppHealthChecks/Extensions/Application+Extensions.swift b/Sources/AppHealthChecks/Extensions/Application+Extensions.swift
index 3d3bda8..c386c15 100644
--- a/Sources/AppHealthChecks/Extensions/Application+Extensions.swift
+++ b/Sources/AppHealthChecks/Extensions/Application+Extensions.swift
@@ -31,7 +31,7 @@ extension Application {
/// Less verbose typealias for `UUID`.
typealias Value = UUID
}
-
+
/// Setup `serviceId` in application storage
public var serviceId: UUID? {
get { storage[ServiceIdKey.self] }
@@ -49,4 +49,40 @@ extension Application {
get { storage[ReleaseIdKey.self] }
set { storage[ReleaseIdKey.self] = newValue }
}
+
+ /// A `psqlIdKey` conform to StorageKey protocol
+ private struct PsqlIdKey: StorageKey {
+ /// Less verbose typealias for `String`.
+ typealias Value = String
+ }
+
+ /// Setup `psqlIdKey` in application storage
+ public var psqlId: String? {
+ get { storage[PsqlIdKey.self] }
+ set { storage[PsqlIdKey.self] = newValue }
+ }
+}
+
+extension Application {
+ /// A `PostgresHealthChecksKey` conform to StorageKey protocol
+ public struct PostgresHealthChecksKey: StorageKey {
+ /// Less verbose typealias for `PostgresHealthChecksProtocol`.
+ public typealias Value = PostgresHealthChecksProtocol
+ }
+
+ /// Setup `psqlHealthChecks` in application storage
+ public var psqlHealthChecks: PostgresHealthChecksProtocol? {
+ get { storage[PostgresHealthChecksKey.self] }
+ set { storage[PostgresHealthChecksKey.self] = newValue }
+ }
+}
+
+extension Application {
+ /// Variable of date conform to DateFormatter protocol. ISO 8601 with date time format
+ /// Example: `2024-02-01T11:11:59.364`
+ public var dateTimeISOFormat: DateFormatter {
+ let formatter = DateFormatter()
+ formatter.dateFormat = Constants.dateFormat
+ return formatter
+ }
}
diff --git a/Sources/AppHealthChecks/Models/ComponentName.swift b/Sources/AppHealthChecks/Models/ComponentName.swift
new file mode 100644
index 0000000..0319ecc
--- /dev/null
+++ b/Sources/AppHealthChecks/Models/ComponentName.swift
@@ -0,0 +1,49 @@
+// FS App Health Checks
+// Copyright (C) 2024 FREEDOM SPACE, LLC
+
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published
+// by the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+//
+// ComponentName.swift
+//
+//
+// Created by Mykola Buhaiov on 29.01.2024.
+//
+
+import Vapor
+
+/// Human-readable name for the component
+public enum ComponentName: String {
+ /// The Central Processing Unit (CPU) is the primary component of a computer that acts as its "control center."
+ case cpu
+ /// Memory, also known as random access memory (RAM), is a PC component that stores data while the computer runs
+ case memory
+ /// Redis is an open-source in-memory storage, used as a distributed, in-memory key–value database
+ case redis
+ /// PostgreSQL also known as Postgres, is a free and open-source relational database management system (RDBMS) emphasizing extensibility
+ case postgresql
+ /// MongoDB is a source-available, cross-platform, document-oriented database program.
+ case mongo
+ /// Distributed messaging system between server applications in real time
+ case kafka
+ /// Consul is a service networking solution to automate network configurations, discover services, and enable secure connectivity across any cloud or runtime.
+ case consul
+ /// gRPC is a modern open source high performance Remote Procedure Call (RPC) framework that can run in any environment.
+ case grpc
+}
+
+extension ComponentName: Content {}
+
+extension ComponentName: CaseIterable {}
diff --git a/Sources/AppHealthChecks/Response/ComponentType.swift b/Sources/AppHealthChecks/Models/ComponentType.swift
similarity index 81%
rename from Sources/AppHealthChecks/Response/ComponentType.swift
rename to Sources/AppHealthChecks/Models/ComponentType.swift
index d2486c8..3debadd 100644
--- a/Sources/AppHealthChecks/Response/ComponentType.swift
+++ b/Sources/AppHealthChecks/Models/ComponentType.swift
@@ -26,8 +26,11 @@ import Vapor
/// Human-readable type for the component.
public enum ComponentType: String {
+ /// A part that combines with other parts to form something bigger
case component
+ /// A datastore is a repository for storing, managing and distributing data sets on an enterprise level
case datastore
+ /// A set of connected things or devices that operate together
case system
}
diff --git a/Sources/AppHealthChecks/Response/HealthCheck.swift b/Sources/AppHealthChecks/Models/HealthCheck.swift
similarity index 100%
rename from Sources/AppHealthChecks/Response/HealthCheck.swift
rename to Sources/AppHealthChecks/Models/HealthCheck.swift
diff --git a/Sources/AppHealthChecks/Models/HealthCheckItem+Equatable.swift b/Sources/AppHealthChecks/Models/HealthCheckItem+Equatable.swift
new file mode 100644
index 0000000..5f197f0
--- /dev/null
+++ b/Sources/AppHealthChecks/Models/HealthCheckItem+Equatable.swift
@@ -0,0 +1,59 @@
+// FS App Health Checks
+// Copyright (C) 2024 FREEDOM SPACE, LLC
+
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published
+// by the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+//
+// HealthCheckItem+Equatable.swift
+//
+//
+// Created by Mykola Buhaiov on 06.02.2024.
+//
+
+import Vapor
+
+/// Equatable protocol implementation for `HealthCheckItem` struct.
+///
+/// Two `HealthCheckItem` structs are considered equal if they have the same:
+///
+/// - componentId
+/// - componentType
+/// - observedValue
+/// - observedUnit
+/// - status
+/// - affectedEndpoints
+/// - time
+/// - output
+/// - links
+/// - node
+extension HealthCheckItem: Equatable {
+ /// Conform `HealthCheckItem` to `Equatable` protocol
+ /// - Parameters:
+ /// - lhs: `HealthCheckItem`
+ /// - rhs: `HealthCheckItem`
+ /// - Returns: `Bool`
+ public static func == (lhs: HealthCheckItem, rhs: HealthCheckItem) -> Bool {
+ return lhs.componentId == rhs.componentId &&
+ lhs.componentType == rhs.componentType &&
+ lhs.observedValue == rhs.observedValue &&
+ lhs.observedUnit == rhs.observedUnit &&
+ lhs.status == rhs.status &&
+ lhs.affectedEndpoints == rhs.affectedEndpoints &&
+ lhs.time == rhs.time &&
+ lhs.output == rhs.output &&
+ lhs.links == rhs.links &&
+ lhs.node == rhs.node
+ }
+}
diff --git a/Sources/AppHealthChecks/Response/HealthCheckItem.swift b/Sources/AppHealthChecks/Models/HealthCheckItem.swift
similarity index 100%
rename from Sources/AppHealthChecks/Response/HealthCheckItem.swift
rename to Sources/AppHealthChecks/Models/HealthCheckItem.swift
diff --git a/Sources/AppHealthChecks/Response/HealthCheckStatus.swift b/Sources/AppHealthChecks/Models/HealthCheckStatus.swift
similarity index 100%
rename from Sources/AppHealthChecks/Response/HealthCheckStatus.swift
rename to Sources/AppHealthChecks/Models/HealthCheckStatus.swift
diff --git a/Sources/AppHealthChecks/Response/MeasurementType.swift b/Sources/AppHealthChecks/Models/MeasurementType.swift
similarity index 77%
rename from Sources/AppHealthChecks/Response/MeasurementType.swift
rename to Sources/AppHealthChecks/Models/MeasurementType.swift
index f4336c9..af0923e 100644
--- a/Sources/AppHealthChecks/Response/MeasurementType.swift
+++ b/Sources/AppHealthChecks/Models/MeasurementType.swift
@@ -26,9 +26,13 @@ import Vapor
/// Name of the measurement type (a data point type) that the status is reported for
public enum MeasurementType: String {
+ /// An act or instance of making practical or profitable use of something
case utilization
+ /// The time lag between an electronic input and the output signal which depends upon the value of passive components used
case responseTime
+ /// The state of being connected
case connections
+ /// Uptime is a measure of system reliability, expressed as the percentage of time a machine
case uptime
}
diff --git a/Sources/AppHealthChecks/PostgresHealthChecks/PostgresChecksProtocol.swift b/Sources/AppHealthChecks/PostgresHealthChecks/PostgresChecksProtocol.swift
new file mode 100644
index 0000000..4410c70
--- /dev/null
+++ b/Sources/AppHealthChecks/PostgresHealthChecks/PostgresChecksProtocol.swift
@@ -0,0 +1,40 @@
+// FS App Health Checks
+// Copyright (C) 2024 FREEDOM SPACE, LLC
+
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published
+// by the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+//
+// PostgresChecksProtocol.swift
+//
+//
+// Created by Mykola Buhaiov on 31.01.2024.
+//
+
+import Vapor
+
+/// Groups func for get psql health check
+public protocol PostgresChecksProtocol {
+ /// Get Postgresql version
+ /// - Returns: `HealthCheckItem`
+ func connection() async -> HealthCheckItem
+
+ /// Get response time from postgresql
+ /// - Returns: `HealthCheckItem`
+ func getResponseTime() async -> HealthCheckItem
+
+ /// Get version from postgresql
+ /// - Returns: `String`
+ func getVersion() async -> String
+}
diff --git a/Sources/AppHealthChecks/PostgresHealthChecks/PostgresHealthChecks.swift b/Sources/AppHealthChecks/PostgresHealthChecks/PostgresHealthChecks.swift
new file mode 100644
index 0000000..6bcdf8d
--- /dev/null
+++ b/Sources/AppHealthChecks/PostgresHealthChecks/PostgresHealthChecks.swift
@@ -0,0 +1,102 @@
+// FS App Health Checks
+// Copyright (C) 2024 FREEDOM SPACE, LLC
+
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published
+// by the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+//
+// PostgresHealthChecks.swift
+//
+//
+// Created by Mykola Buhaiov on 31.01.2024.
+//
+
+import Vapor
+import Fluent
+import FluentPostgresDriver
+
+/// Service that provides psql health check functionality
+public struct PostgresHealthChecks: PostgresHealthChecksProtocol {
+ /// Instance of app as `Application`
+ public let app: Application
+
+ /// Get postgresql version
+ /// - Returns: `HealthCheckItem`
+ public func connection() async -> HealthCheckItem {
+ let dateNow = Date().timeIntervalSinceReferenceDate
+ let versionDescription = await getVersion()
+ let result = HealthCheckItem(
+ componentId: app.psqlId,
+ componentType: .datastore,
+ observedValue: Date().timeIntervalSinceReferenceDate - dateNow,
+ observedUnit: "s",
+ status: versionDescription.contains("PostgreSQL") ? .pass : .fail,
+ time: app.dateTimeISOFormat.string(from: Date()),
+ output: !versionDescription.contains("PostgreSQL") ? versionDescription : nil,
+ links: nil,
+ node: nil
+ )
+ return result
+ }
+
+ /// Get response time from postgresql
+ /// - Returns: `HealthCheckItem`
+ public func getResponseTime() async -> HealthCheckItem {
+ let dateNow = Date().timeIntervalSinceReferenceDate
+ let versionDescription = await getVersion()
+ let result = HealthCheckItem(
+ componentId: app.psqlId,
+ componentType: .datastore,
+ observedValue: Date().timeIntervalSinceReferenceDate - dateNow,
+ observedUnit: "s",
+ status: versionDescription.contains("PostgreSQL") ? .pass : .fail,
+ time: app.dateTimeISOFormat.string(from: Date()),
+ output: !versionDescription.contains("PostgreSQL") ? versionDescription : nil,
+ links: nil,
+ node: nil
+ )
+ return result
+ }
+
+ /// Get version from postgresql
+ /// - Returns: `String`
+ public func getVersion() async -> String {
+ let rows = try? await (app.db(.psql) as? PostgresDatabase)?.simpleQuery("SELECT version()").get()
+ let row = rows?.first?.makeRandomAccess()
+ var connectionDescription = "ERROR: No connect to Postgres database"
+ if let result = (row?[data: "version"].string) {
+ connectionDescription = result
+ }
+ return connectionDescription
+ }
+
+ /// Check with setup options
+ /// - Parameter options: array of `MeasurementType`
+ /// - Returns: dictionary `[String: HealthCheckItem]`
+ public func checkHealth(for options: [MeasurementType]) async -> [String: HealthCheckItem] {
+ var result = ["": HealthCheckItem()]
+ let measurementTypes = Array(Set(options))
+ for type in measurementTypes {
+ switch type {
+ case .responseTime:
+ result["\(ComponentName.postgresql):\(MeasurementType.responseTime)"] = await getResponseTime()
+ case .connections:
+ result["\(ComponentName.postgresql):\(MeasurementType.connections)"] = await connection()
+ default:
+ break
+ }
+ }
+ return result
+ }
+}
diff --git a/Sources/AppHealthChecks/PostgresHealthChecks/PostgresHealthChecksProtocol.swift b/Sources/AppHealthChecks/PostgresHealthChecks/PostgresHealthChecksProtocol.swift
new file mode 100644
index 0000000..ab22293
--- /dev/null
+++ b/Sources/AppHealthChecks/PostgresHealthChecks/PostgresHealthChecksProtocol.swift
@@ -0,0 +1,28 @@
+// FS App Health Checks
+// Copyright (C) 2024 FREEDOM SPACE, LLC
+
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published
+// by the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+//
+// PostgresHealthChecksProtocol.swift
+//
+//
+// Created by Mykola Buhaiov on 06.02.2024.
+//
+
+import Vapor
+
+/// Groups func for get psql health check
+public protocol PostgresHealthChecksProtocol: PostgresChecksProtocol, ChecksProtocol {}
diff --git a/Sources/AppHealthChecks/Response/ComponentName.swift b/Sources/AppHealthChecks/Utilities/Constants.swift
similarity index 68%
rename from Sources/AppHealthChecks/Response/ComponentName.swift
rename to Sources/AppHealthChecks/Utilities/Constants.swift
index 1cf6b02..f7b9357 100644
--- a/Sources/AppHealthChecks/Response/ComponentName.swift
+++ b/Sources/AppHealthChecks/Utilities/Constants.swift
@@ -16,26 +16,15 @@
// along with this program. If not, see .
//
-// ComponentName.swift
+// Constants.swift
//
//
-// Created by Mykola Buhaiov on 29.01.2024.
+// Created by Mykola Buhaiov on 06.02.2024.
//
import Vapor
-/// Human-readable name for the component
-public enum ComponentName: String {
- case cpu
- case memory
- case redis
- case postgresql
- case mongo
- case kafka
- case consul
- case grpc
+/// Constants
+public enum Constants {
+ static let dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS"
}
-
-extension ComponentName: Content {}
-
-extension ComponentName: CaseIterable {}
diff --git a/Tests/AppHealthChecksTests/HealthCheckItemTests.swift b/Tests/AppHealthChecksTests/HealthCheckItemTests.swift
new file mode 100644
index 0000000..ba8ce3a
--- /dev/null
+++ b/Tests/AppHealthChecksTests/HealthCheckItemTests.swift
@@ -0,0 +1,59 @@
+// FS App Health Checks
+// Copyright (C) 2024 FREEDOM SPACE, LLC
+
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published
+// by the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+//
+// HealthCheckItemTests.swift
+//
+//
+// Created by Mykola Buhaiov on 06.02.2024.
+//
+
+import Vapor
+import XCTest
+@testable import AppHealthChecks
+
+final class HealthCheckItemTests: XCTestCase {
+ func testPublicKeyEquatable() {
+ let firstHealthCheckItem = HealthCheckItem(
+ componentId: "adca7c3d-55f4-4ab3-a842-18b35f50cb0f",
+ componentType: .datastore,
+ observedValue: 1,
+ observedUnit: "s",
+ status: .pass,
+ affectedEndpoints: nil,
+ time: "2024-02-01T11:11:59.364",
+ output: "Ok",
+ links: nil,
+ node: nil
+ )
+ var secondHealthCheckItem = HealthCheckItem(
+ componentId: "adca7c3d-55f4-4ab3-a842-18b35f50cb0f",
+ componentType: .datastore,
+ observedValue: 1,
+ observedUnit: "s",
+ status: .pass,
+ affectedEndpoints: nil,
+ time: "2024-02-01T11:11:59.364",
+ output: "Ok",
+ links: nil,
+ node: nil
+ )
+ XCTAssertEqual(firstHealthCheckItem, secondHealthCheckItem)
+ secondHealthCheckItem.observedValue = 4
+ XCTAssertNotEqual(firstHealthCheckItem, secondHealthCheckItem)
+ }
+}
diff --git a/Tests/AppHealthChecksTests/Mocks/PostgresHealthChecksMock.swift b/Tests/AppHealthChecksTests/Mocks/PostgresHealthChecksMock.swift
new file mode 100644
index 0000000..920e56f
--- /dev/null
+++ b/Tests/AppHealthChecksTests/Mocks/PostgresHealthChecksMock.swift
@@ -0,0 +1,64 @@
+// FS App Health Checks
+// Copyright (C) 2024 FREEDOM SPACE, LLC
+
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published
+// by the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+//
+// PostgresHealthChecksMock.swift
+//
+//
+// Created by Mykola Buhaiov on 31.01.2024.
+//
+
+import Vapor
+import FluentPostgresDriver
+@testable import AppHealthChecks
+
+public struct PostgresHealthChecksMock: PostgresHealthChecksProtocol {
+ static let psqlId = "adca7c3d-55f4-4ab3-a842-18b35f50cb0f"
+ static let version = "database version - 15"
+ static let healthCheckItem = HealthCheckItem(
+ componentId: psqlId,
+ componentType: .datastore,
+ observedValue: 1,
+ observedUnit: "s",
+ status: .pass,
+ affectedEndpoints: nil,
+ time: "2024-02-01T11:11:59.364",
+ output: "Ok",
+ links: nil,
+ node: nil
+ )
+
+ public func connection() async -> HealthCheckItem {
+ PostgresHealthChecksMock.healthCheckItem
+ }
+
+ public func getResponseTime() async -> HealthCheckItem {
+ PostgresHealthChecksMock.healthCheckItem
+ }
+
+ public func getVersion() async -> String {
+ PostgresHealthChecksMock.version
+ }
+
+ public func checkHealth(for options: [MeasurementType]) async -> [String: HealthCheckItem] {
+ let result = [
+ "\(ComponentName.postgresql):\(MeasurementType.responseTime)": PostgresHealthChecksMock.healthCheckItem,
+ "\(ComponentName.postgresql):\(MeasurementType.connections)": PostgresHealthChecksMock.healthCheckItem
+ ]
+ return result
+ }
+}
diff --git a/Tests/AppHealthChecksTests/PostgresHealthChecksTests.swift b/Tests/AppHealthChecksTests/PostgresHealthChecksTests.swift
new file mode 100644
index 0000000..5302ede
--- /dev/null
+++ b/Tests/AppHealthChecksTests/PostgresHealthChecksTests.swift
@@ -0,0 +1,68 @@
+// FS App Health Checks
+// Copyright (C) 2024 FREEDOM SPACE, LLC
+
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published
+// by the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+//
+// PostgresHealthChecksTests.swift
+//
+//
+// Created by Mykola Buhaiov on 09.03.2023.
+//
+
+import Vapor
+import XCTest
+@testable import AppHealthChecks
+
+final class PostgresHealthChecksTests: XCTestCase {
+ func testConnection() async throws {
+ let app = Application(.testing)
+ defer { app.shutdown() }
+ app.psqlId = UUID().uuidString
+ app.psqlHealthChecks = PostgresHealthChecksMock()
+ let result = await app.psqlHealthChecks?.connection()
+ XCTAssertEqual(result, PostgresHealthChecksMock.healthCheckItem)
+ }
+
+ func testGetResponseTime() async throws {
+ let app = Application(.testing)
+ defer { app.shutdown() }
+ let dateFormat = app.dateTimeISOFormat
+ app.psqlHealthChecks = PostgresHealthChecksMock()
+ let result = await app.psqlHealthChecks?.getResponseTime()
+ XCTAssertEqual(result, PostgresHealthChecksMock.healthCheckItem)
+ }
+
+ func testCheckHealth() async throws {
+ let app = Application(.testing)
+ defer { app.shutdown() }
+ app.psqlId = UUID().uuidString
+ app.psqlHealthChecks = PostgresHealthChecksMock()
+ let result = await app.psqlHealthChecks?.checkHealth(for: [MeasurementType.responseTime, MeasurementType.connections])
+ let psqlConnections = result?["\(ComponentName.postgresql):\(MeasurementType.connections)"]
+ XCTAssertEqual(psqlConnections, PostgresHealthChecksMock.healthCheckItem)
+ let psqlResponseTimes = result?["\(ComponentName.postgresql):\(MeasurementType.responseTime)"]
+ XCTAssertEqual(psqlResponseTimes, PostgresHealthChecksMock.healthCheckItem)
+ }
+
+ func testGetVersion() async throws {
+ let app = Application(.testing)
+ defer { app.shutdown() }
+ app.psqlId = UUID().uuidString
+ app.psqlHealthChecks = PostgresHealthChecksMock()
+ let result = await app.psqlHealthChecks?.getVersion()
+ XCTAssertEqual(result, PostgresHealthChecksMock.version)
+ }
+}