Skip to content

Commit

Permalink
Merge pull request #41 from CXwudi/switch-to-postgres
Browse files Browse the repository at this point in the history
  • Loading branch information
CXwudi authored Dec 6, 2024
2 parents 9d4673d + ecf4bf1 commit ffc561c
Show file tree
Hide file tree
Showing 26 changed files with 263 additions and 128 deletions.
4 changes: 4 additions & 0 deletions .github/workflows/decompose-frontend-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ name: Frontend Decompose Module Tests

on:
push:
branches:
- main
- master
- 'renovate/**'
paths:
- 'conduit-frontend/frontend-decompose-logic/**'
- 'build-src/**'
Expand Down
44 changes: 43 additions & 1 deletion .github/workflows/http4k-backend-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ name: Http4k Backend Tests

on:
push:
branches:
- main
- master
- 'renovate/**'
paths:
- 'conduit-backend/**'
- 'build-src/**'
Expand All @@ -10,6 +14,31 @@ jobs:
test:
runs-on: ubuntu-latest

services:
postgres:
image: postgres:alpine
env:
POSTGRES_DB: test-db
POSTGRES_USER: test-user
POSTGRES_PASSWORD: test-password
options: >-
--health-cmd pg_isready
--health-interval 3s
--health-timeout 5s
--health-retries 5
ports:
- 5432:5432

redis:
image: redis:alpine
options: >-
--health-cmd "redis-cli ping"
--health-interval 3s
--health-timeout 5s
--health-retries 5
ports:
- 6379:6379

steps:
- name: Checkout code
uses: actions/checkout@v4
Expand All @@ -20,13 +49,26 @@ jobs:
java-version: '21'
distribution: 'temurin'

- name: Run Database Migrations
uses: red-gate/FlywayGitHubAction@main
with:
url: jdbc:postgresql://localhost:5432/test-db
user: test-user
password: test-password
locations: filesystem:./conduit-backend/db-migration/main,filesystem:./conduit-backend/db-migration/test
extraArgs: -cleanDisabled=false -clean=true

- name: Setup Gradle
uses: gradle/actions/setup-gradle@v4

- name: Run Backend Tests
working-directory: conduit-backend
env:
DB__URL: jdbc:postgresql://localhost:5432/test-db
DB__USER: test-user
DB__PASSWORD: test-password
run: |
./gradlew check
./gradlew check
- name: Upload build reports
uses: actions/upload-artifact@v4
Expand Down
4 changes: 2 additions & 2 deletions build-src/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ dev-backend-kotestBom = "io.kotest:kotest-bom:5.9.1"
dev-backend-kotestKoin = "io.kotest.extensions:kotest-extensions-koin:1.3.0"
dev-backend-mockk = "io.mockk:mockk:1.13.13"
dev-backend-hoplite-yaml = "com.sksamuel.hoplite:hoplite-yaml:2.9.0"
dev-backend-sqlite = "org.xerial:sqlite-jdbc:3.47.1.0"
dev-backend-postgresql = "org.postgresql:postgresql:42.7.4"
dev-backend-hikari = "com.zaxxer:HikariCP:6.2.1"
dev-backend-flyway = "org.flywaydb:flyway-core:11.0.1"
dev-backend-logback = "ch.qos.logback:logback-classic:1.5.12"
Expand Down Expand Up @@ -104,4 +104,4 @@ kotlinCompose = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kot
compose = { id = "org.jetbrains.compose", version.ref = "compose" }
ktorfit = { id = "de.jensklingenberg.ktorfit", version.ref = "ktorfit" }
# a plugin used by gradle files for precompiled script plugin
buildConfig = { id = "com.github.gmazzo.buildconfig", version = "5.5.1" }
buildConfig = { id = "com.github.gmazzo.buildconfig", version = "5.5.1" }
16 changes: 16 additions & 0 deletions conduit-backend/.run/Docker for Dev.run.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Docker for Dev" type="docker-deploy" factoryName="docker-compose.yml" server-name="Docker Window">
<deployment type="docker-compose.yml">
<settings>
<option name="envFilePath" value="D:\coding-workspace\jvm\conduit-related\realworld-compose-http4k-example-app\conduit-backend\docker\.env" />
<option name="secondarySourceFiles">
<list>
<option value="docker/compose.dev.yml" />
</list>
</option>
<option name="sourceFilePath" value="docker/compose.base.yml" />
</settings>
</deployment>
<method v="2" />
</configuration>
</component>
3 changes: 1 addition & 2 deletions conduit-backend/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,8 @@ dependencies {
implementation("org.jetbrains.exposed:exposed-core")
implementation("org.jetbrains.exposed:exposed-dao")
implementation("org.jetbrains.exposed:exposed-jdbc")
implementation(libs.dev.backend.sqlite)
implementation(libs.dev.backend.postgresql)
implementation(libs.dev.backend.hikari)
implementation(libs.dev.backend.flyway)
implementation(libs.dev.backend.inlineLogging)
implementation(libs.dev.backend.slf4j)
runtimeOnly(libs.dev.backend.logback)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
-- V1__CreateUsersTable.sql
create table users
(
id integer primary key autoincrement,
id serial primary key,
email varchar(255) not null unique,
username varchar(255) not null unique,
password varchar(255) not null,
Expand Down
8 changes: 8 additions & 0 deletions conduit-backend/db-migration/test/V999__insert_test_data.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
-- V999__insert_test_data.sql
INSERT INTO users (email, username, password, bio, image)
VALUES
('[email protected]', 'john', '$2a$10$8BxPYyqz2.X5TKk2R6gGIeZ.Tkk2KmcC6yN1BxLLGCgMgMNEZpgjK', 'Hi, I''m John!', 'https://api.realworld.io/images/john.jpg'),
('[email protected]', 'jane', '$2a$10$8BxPYyqz2.X5TKk2R6gGIeZ.Tkk2KmcC6yN1BxLLGCgMgMNEZpgjK', 'Hi, I''m Jane!', 'https://api.realworld.io/images/jane.jpg'),
('[email protected]', 'bob', '$2a$10$8BxPYyqz2.X5TKk2R6gGIeZ.Tkk2KmcC6yN1BxLLGCgMgMNEZpgjK', NULL, NULL),
('[email protected]', 'alice', '$2a$10$8BxPYyqz2.X5TKk2R6gGIeZ.Tkk2KmcC6yN1BxLLGCgMgMNEZpgjK', 'Software developer', 'https://api.realworld.io/images/alice.jpg'),
('[email protected]', 'test', '$2a$10$8BxPYyqz2.X5TKk2R6gGIeZ.Tkk2KmcC6yN1BxLLGCgMgMNEZpgjK', NULL, NULL);
5 changes: 5 additions & 0 deletions conduit-backend/docker/.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# PostgreSQL
POSTGRES_DB=conduit-db
POSTGRES_USER=conduit-user
POSTGRES_PASSWORD=conduit-password

52 changes: 52 additions & 0 deletions conduit-backend/docker/compose.base.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
services:
postgres:
image: postgres:alpine
container_name: conduit-postgres
environment:
POSTGRES_DB: ${POSTGRES_DB}
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
interval: 3s
timeout: 5s
retries: 5

redis:
image: redis:alpine
container_name: conduit-redis
volumes:
- redis_data:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 3s
timeout: 5s
retries: 5

flyway:
image: flyway/flyway:latest-alpine
container_name: conduit-flyway
profiles: ["migration"]
environment:
FLYWAY_URL: jdbc:postgresql://postgres:5432/${POSTGRES_DB}
FLYWAY_USER: ${POSTGRES_USER}
FLYWAY_PASSWORD: ${POSTGRES_PASSWORD}
FLYWAY_CONNECT_RETRIES: 10
volumes: # consider having different migration files for different environments, see https://documentation.red-gate.com/fd/configuration-files-224003079.html
- ../db/migration:/flyway/sql
depends_on:
postgres:
condition: service_healthy
command: migrate

volumes:
postgres_data:
name: conduit-postgres-data
redis_data:
name: conduit-redis-data

networks:
default:
name: conduit-network
21 changes: 21 additions & 0 deletions conduit-backend/docker/compose.dev.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# This file contains development-specific overrides
# Use with compose.base.yml like this:
# docker compose -f compose.base.yml -f compose.dev.yml up

services:
postgres:
ports:
- "5432:5432"

redis:
ports:
- "6379:6379"

flyway:
volumes:
- ../db-migration/main:/flyway/sql # Regular migrations
- ../db-migration/test:/flyway/sql-test # Test migrations in separate directory
environment:
FLYWAY_LOCATIONS: filesystem:/flyway/sql,filesystem:/flyway/sql-test
FLYWAY_CLEAN_DISABLED: false
command: clean migrate
Original file line number Diff line number Diff line change
Expand Up @@ -2,36 +2,15 @@ package mikufan.cx.conduit.backend

import mikufan.cx.conduit.backend.controller.ConduitServer
import mikufan.cx.inlinelogging.KInlineLogging
import org.flywaydb.core.Flyway

class Bootstrap(
private val flyway: Flyway,
private val server: ConduitServer
) : Runnable {

override fun run() {
dbMigration()
startServer()
}

private fun dbMigration() {
log.info { "Performing DB migrations if any" }
val migrateResult = flyway.migrate()
if (migrateResult.migrationsExecuted > 0) {
if (migrateResult.success) {
log.info { "Database migration successful. Migrations applied: ${migrateResult.migrationsExecuted}" }
} else {
val failureString = migrateResult.failedMigrations.joinToString(separator = "\n ", prefix = "[\n", postfix = "\n") {
"${it.type} ${it.version} @ ${it.filepath} - ${it.description}"
}
val errorMessage = "Database migration failed: \n$failureString"
log.error { errorMessage }
throw IllegalStateException(errorMessage)
}
} else { // no migration applied
log.info { "No migration applied" }
}
}

private fun startServer() {
log.info { "Starting server" }
server.start()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package mikufan.cx.conduit.backend.config

import com.sksamuel.hoplite.ConfigLoaderBuilder
import com.sksamuel.hoplite.addEnvironmentSource
import com.sksamuel.hoplite.addResourceOrFileSource
import com.sksamuel.hoplite.sources.CommandLinePropertySource

fun loadConfig(args: Array<String>): Config = ConfigLoaderBuilder.default()
.addPropertySource(CommandLinePropertySource(args, prefix = "--", delimiter = "=")) // can handle empty array
.addEnvironmentSource()
.addResourceOrFileSource("/application-prod.yml", optional = true, allowEmpty = true)
.addResourceOrFileSource("/application.yml", allowEmpty = true)
.build()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class RegisterUserHandler(

override fun invoke(request: Request): Response {
val userDto = userRegistrationLen(request).user
val UserRegisterDto = userService.registerUser(userDto)
return userRspLens(UserRsp(UserRegisterDto), Response(Status.CREATED))
val userRegisterDto = userService.registerUser(userDto)
return userRspLens(UserRsp(userRegisterDto), Response(Status.CREATED))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import org.http4k.server.Http4kServer
import org.http4k.server.JettyLoom
import org.http4k.server.asServer

//// route setup ////

fun conduitRoute(apiRoute: RoutingHttpHandler): RoutingHttpHandler = routes(
"/healthcheck" bind GET to { Response(Status.OK).body("OK") },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,13 @@ import org.jetbrains.exposed.sql.Transaction
import org.jetbrains.exposed.sql.transactions.transaction

interface TransactionManager {
val db: Database

fun <T> tx(block: Transaction.() -> T): T {
return transaction(db) {
block()
}
}
fun <T> tx(block: Transaction.() -> T): T
}

class TransactionManagerImpl(
override val db: Database
) : TransactionManager
val db: Database
) : TransactionManager {
override fun <T> tx(block: Transaction.() -> T): T = transaction(db) {
block()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,8 @@ import org.koin.dsl.module
*/
val dbModule = module {
single { creatDataSource(get<Config>().db) }
singleOf(::createFlyway)
singleOf(::createExposedDb)
singleOf(::createTransactionManager)
singleOf(::createConduitTransactionManager)

singleOf(::UserRepo)
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package mikufan.cx.conduit.backend.db

import org.jetbrains.exposed.dao.IntEntity
import org.jetbrains.exposed.dao.IntEntityClass
import org.jetbrains.exposed.dao.id.EntityID
import org.jetbrains.exposed.dao.id.IntIdTable

object Users : IntIdTable() {
Expand All @@ -9,3 +12,13 @@ object Users : IntIdTable() {
val bio = varchar("bio", 255).nullable()
val image = varchar("image", 255).nullable()
}

class User(id: EntityID<Int>) : IntEntity(id) {
companion object : IntEntityClass<User>(Users)

var email by Users.email
var username by Users.username
var password by Users.password
var bio by Users.bio
var image by Users.image
}
Loading

0 comments on commit ffc561c

Please sign in to comment.