feat(01-02): add /ready endpoint with database connectivity check
- Add GET /ready endpoint that checks database connection - Returns 200 'ready' when connected, 503 when not - Update Routes to require DataSource dependency - Provide dataSourceLayer in Main.scala - Use 'hikari' prefix for HikariCP config to avoid ZIO config conflict
This commit is contained in:
@@ -5,7 +5,7 @@ server {
|
||||
port = ${?SERVER_PORT}
|
||||
}
|
||||
|
||||
# Database configuration for ZIO config (used by AppConfig)
|
||||
# Database configuration for ZIO config (used by AppConfig.DatabaseConfig)
|
||||
database {
|
||||
host = "localhost"
|
||||
host = ${?DB_HOST}
|
||||
@@ -20,8 +20,8 @@ database {
|
||||
}
|
||||
|
||||
# HikariCP configuration for Quill DataSource
|
||||
# Reads from "database" prefix via Quill.DataSource.fromPrefix
|
||||
database {
|
||||
# Uses separate prefix to avoid conflict with ZIO config "database" property
|
||||
hikari {
|
||||
dataSourceClassName = "org.postgresql.ds.PGSimpleDataSource"
|
||||
dataSource {
|
||||
serverName = "localhost"
|
||||
|
||||
@@ -4,6 +4,7 @@ import zio.config.typesafe.TypesafeConfigProvider
|
||||
|
||||
import api.Routes
|
||||
import _root_.config.{AppConfig as SummerConfig}
|
||||
import db.QuillContext
|
||||
|
||||
object Main extends ZIOAppDefault {
|
||||
|
||||
@@ -29,7 +30,11 @@ object Main extends ZIOAppDefault {
|
||||
_ <- Console.printLine(banner)
|
||||
_ <- Console.printLine(s" Starting on port ${cfg.server.port}...")
|
||||
_ <- Console.printLine("")
|
||||
_ <- Server.serve(Routes.routes).provide(Server.defaultWithPort(cfg.server.port))
|
||||
// Note: Migrations are NOT auto-run. Use CLI to run migrations (Phase 5).
|
||||
_ <- Server.serve(Routes.routes).provide(
|
||||
Server.defaultWithPort(cfg.server.port),
|
||||
QuillContext.dataSourceLayer
|
||||
)
|
||||
} yield ()
|
||||
|
||||
}
|
||||
|
||||
@@ -1,20 +1,33 @@
|
||||
package api
|
||||
|
||||
import zio.*
|
||||
import zio.http.*
|
||||
import javax.sql.DataSource
|
||||
|
||||
/** Health check endpoints
|
||||
*
|
||||
* Provides basic health check endpoint for load balancers and monitoring systems. The /health
|
||||
* endpoint returns 200 OK when the server is running.
|
||||
* Provides health check endpoints for load balancers and monitoring systems.
|
||||
*
|
||||
* Future endpoints:
|
||||
* - /ready will verify database connectivity
|
||||
* Endpoints:
|
||||
* - GET /health - Returns 200 OK when server is running (liveness probe)
|
||||
* - GET /ready - Returns 200 when database is connected, 503 when not (readiness probe)
|
||||
*/
|
||||
object HealthRoutes {
|
||||
|
||||
val routes: Routes[Any, Response] =
|
||||
val routes: Routes[DataSource, Response] =
|
||||
Routes(
|
||||
Method.GET / "health" -> Handler.text("ok")
|
||||
// Liveness probe - always 200 if server is running
|
||||
Method.GET / "health" -> Handler.text("ok"),
|
||||
// Readiness probe - checks database connectivity
|
||||
Method.GET / "ready" -> handler {
|
||||
ZIO.serviceWithZIO[DataSource] { ds =>
|
||||
ZIO.attempt {
|
||||
val conn = ds.getConnection
|
||||
conn.close()
|
||||
}.as(Response.text("ready"))
|
||||
.catchAll(_ => ZIO.succeed(Response.status(Status.ServiceUnavailable)))
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package api
|
||||
|
||||
import zio.http.*
|
||||
import javax.sql.DataSource
|
||||
|
||||
/** Route composition point
|
||||
*
|
||||
@@ -8,7 +9,7 @@ import zio.http.*
|
||||
*/
|
||||
object Routes {
|
||||
|
||||
val routes: Routes[Any, Response] =
|
||||
val routes: Routes[DataSource, Response] =
|
||||
HealthRoutes.routes
|
||||
|
||||
}
|
||||
|
||||
@@ -27,11 +27,12 @@ object QuillContext {
|
||||
|
||||
/** DataSource layer from HikariCP configuration
|
||||
*
|
||||
* Reads configuration from "database" prefix in application.conf.
|
||||
* Reads configuration from "hikari" prefix in application.conf.
|
||||
* Uses separate prefix from "database" to avoid conflict with ZIO config.
|
||||
* HikariCP manages the connection pool.
|
||||
*/
|
||||
val dataSourceLayer: ZLayer[Any, Throwable, DataSource] =
|
||||
Quill.DataSource.fromPrefix("database")
|
||||
Quill.DataSource.fromPrefix("hikari")
|
||||
|
||||
/** Quill PostgreSQL context with snake_case naming
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user