Skip to content

Commit 306bcf9

Browse files
authored
Merge: 문서 목록 CQRS Read Model 전환 및 Domain Event Outbox 추가
Refactor: 문서 목록 CQRS Read Model 전환 및 Domain Event Outbox 추가
2 parents 8334b6c + a3d0b4b commit 306bcf9

136 files changed

Lines changed: 3682 additions & 1593 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

build.gradle

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ repositories {
2525

2626
test {
2727
testLogging {
28-
events "passed", "skipped", "failed", "standardOut", "standardError"
28+
events "skipped", "failed"
29+
showStandardStreams = false
2930
exceptionFormat "full"
3031
showCauses true
3132
showExceptions true

infra/docker-compose.local.yml

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
name: docsa-local
2+
3+
services:
4+
mysql:
5+
image: mysql:9.4.0
6+
container_name: docsa-mysql-local
7+
restart: unless-stopped
8+
environment:
9+
MYSQL_DATABASE: ${LOCAL_MYSQL_DATABASE:-docsa}
10+
MYSQL_USER: ${LOCAL_MYSQL_USER:-docsa}
11+
MYSQL_PASSWORD: ${LOCAL_MYSQL_PASSWORD:-docsa}
12+
MYSQL_ROOT_PASSWORD: ${LOCAL_MYSQL_ROOT_PASSWORD:-root}
13+
TZ: Asia/Seoul
14+
ports:
15+
- "${LOCAL_MYSQL_PORT:-3306}:3306"
16+
volumes:
17+
- local_mysql_data:/var/lib/mysql
18+
- ./mysql/my.cnf:/etc/mysql/conf.d/my.cnf:ro
19+
healthcheck:
20+
test: ["CMD-SHELL", "mysqladmin ping -h 127.0.0.1 -u$${MYSQL_USER} -p$${MYSQL_PASSWORD}"]
21+
interval: 10s
22+
timeout: 5s
23+
retries: 10
24+
start_period: 20s
25+
networks:
26+
- docsa_local_net
27+
28+
mongo:
29+
image: mongo:8.0
30+
container_name: docsa-mongo-local
31+
restart: unless-stopped
32+
command: ["mongod", "--replSet", "rs0", "--bind_ip_all"]
33+
ports:
34+
- "${LOCAL_MONGO_PORT:-27017}:27017"
35+
volumes:
36+
- local_mongo_data:/data/db
37+
healthcheck:
38+
test:
39+
[
40+
"CMD-SHELL",
41+
"mongosh --quiet --eval 'try { rs.status().ok } catch (e) { rs.initiate({_id:\"rs0\",members:[{_id:0,host:\"localhost:27017\"}]}); 1 }' | grep 1"
42+
]
43+
interval: 10s
44+
timeout: 5s
45+
retries: 10
46+
start_period: 10s
47+
networks:
48+
- docsa_local_net
49+
50+
mailpit:
51+
image: axllent/mailpit:latest
52+
container_name: docsa-mailpit-local
53+
restart: unless-stopped
54+
environment:
55+
MP_SMTP_AUTH_ACCEPT_ANY: "1"
56+
MP_SMTP_AUTH_ALLOW_INSECURE: "1"
57+
MP_DATABASE: /data/mailpit.db
58+
MP_MAX_MESSAGES: "5000"
59+
ports:
60+
- "${LOCAL_MAILPIT_SMTP_PORT:-1025}:1025"
61+
- "${LOCAL_MAILPIT_WEB_PORT:-8025}:8025"
62+
volumes:
63+
- local_mailpit_data:/data
64+
healthcheck:
65+
test: ["CMD-SHELL", "wget -q --spider http://127.0.0.1:8025/readyz || exit 1"]
66+
interval: 10s
67+
timeout: 3s
68+
retries: 5
69+
start_period: 10s
70+
networks:
71+
- docsa_local_net
72+
73+
minio:
74+
image: minio/minio:latest
75+
container_name: docsa-minio-local
76+
restart: unless-stopped
77+
command: ["server", "/data", "--console-address", ":9001"]
78+
environment:
79+
MINIO_ROOT_USER: ${LOCAL_MINIO_ROOT_USER:-docsa-local}
80+
MINIO_ROOT_PASSWORD: ${LOCAL_MINIO_ROOT_PASSWORD:-docsa-local-password}
81+
MINIO_API_CORS_ALLOW_ORIGIN: ${LOCAL_MINIO_CORS_ALLOW_ORIGIN:-http://localhost:3000,http://localhost:5173}
82+
TZ: Asia/Seoul
83+
ports:
84+
- "${LOCAL_MINIO_API_PORT:-9000}:9000"
85+
- "${LOCAL_MINIO_CONSOLE_PORT:-9001}:9001"
86+
volumes:
87+
- local_minio_data:/data
88+
networks:
89+
- docsa_local_net
90+
91+
minio-init:
92+
image: minio/mc:latest
93+
container_name: docsa-minio-init-local
94+
depends_on:
95+
- minio
96+
environment:
97+
LOCAL_MINIO_ROOT_USER: ${LOCAL_MINIO_ROOT_USER:-docsa-local}
98+
LOCAL_MINIO_ROOT_PASSWORD: ${LOCAL_MINIO_ROOT_PASSWORD:-docsa-local-password}
99+
LOCAL_MINIO_BUCKET: ${LOCAL_MINIO_BUCKET:-docsa-local}
100+
entrypoint: >
101+
/bin/sh -c "
102+
until mc alias set local http://minio:9000 ${LOCAL_MINIO_ROOT_USER:-docsa-local} ${LOCAL_MINIO_ROOT_PASSWORD:-docsa-local-password}; do sleep 2; done;
103+
mc mb --ignore-existing local/${LOCAL_MINIO_BUCKET:-docsa-local};
104+
mc anonymous set download local/${LOCAL_MINIO_BUCKET:-docsa-local};
105+
"
106+
networks:
107+
- docsa_local_net
108+
109+
volumes:
110+
local_mysql_data:
111+
local_mongo_data:
112+
local_mailpit_data:
113+
local_minio_data:
114+
115+
networks:
116+
docsa_local_net:

infra/docker-compose.stg.yml

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,6 @@ services:
66
container_name: docsa-app-stg
77
restart: unless-stopped
88
env_file: .stg.env
9-
environment:
10-
SPRING_DATA_MONGODB_URI: ${SPRING_DATA_MONGODB_URI}
11-
SPRING_MAIL_USERNAME: ${SPRING_MAIL_USERNAME}
12-
#SPRING_MAIL_PASSWORD: ${SPRING_MAIL_PASSWORD}
13-
SPRING_DATASOURCE_URL: ${SPRING_DATASOURCE_URL}
14-
SPRING_DATASOURCE_USERNAME: ${SPRING_DATASOURCE_USERNAME}
15-
SPRING_DATASOURCE_PASSWORD: ${SPRING_DATASOURCE_PASSWORD}
16-
SERVER_SERVLET_SESSION_COOKIE_NAME: ${SESSION_COOKIE_NAME}
17-
SERVER_SERVLET_SESSION_COOKIE_DOMAIN: ${SESSION_COOKIE_DOMAIN}
18-
SPRINGDOC_SWAGGER-UI_SERVERS_URL: ${SWAGGER_SERVER_URL}
19-
SPRING_JPA_HIBERNATE_DDL_AUTO: ${DDL_AUTO}
209
depends_on:
2110
mysql:
2211
condition: service_healthy

infra/docker-compose.yml

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,6 @@ services:
66
container_name: docsa-app
77
restart: unless-stopped
88
env_file: .env
9-
environment:
10-
SPRING_DATA_MONGODB_URI: ${SPRING_DATA_MONGODB_URI}
11-
SPRING_MAIL_USERNAME: ${SPRING_MAIL_USERNAME}
12-
SPRING_MAIL_PASSWORD: ${SPRING_MAIL_PASSWORD}
13-
SPRING_DATASOURCE_URL: ${SPRING_DATASOURCE_URL}
14-
SPRING_DATASOURCE_USERNAME: ${SPRING_DATASOURCE_USERNAME}
15-
SPRING_DATASOURCE_PASSWORD: ${SPRING_DATASOURCE_PASSWORD}
16-
SERVER_SERVLET_SESSION_COOKIE_NAME: ${SESSION_COOKIE_NAME}
17-
SERVER_SERVLET_SESSION_COOKIE_DOMAIN: ${SESSION_COOKIE_DOMAIN}
18-
SPRINGDOC_SWAGGER-UI_SERVERS_URL: ${SWAGGER_SERVER_URL}
199
depends_on:
2010
mysql:
2111
condition: service_healthy
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
4+
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
5+
6+
COMPOSE_FILE="${BACKFILL_COMPOSE_FILE:-"$ROOT_DIR/infra/docker-compose.stg.yml"}"
7+
SERVICE="${BACKFILL_SERVICE:-app}"
8+
PROFILES="${BACKFILL_PROFILES:-stg,backfill}"
9+
BATCH_SIZE="${DOC_LIST_READ_MODEL_BACKFILL_BATCH_SIZE:-1000}"
10+
DDL_AUTO="${BACKFILL_DDL_AUTO:-validate}"
11+
12+
echo "[backfill] composeFile=$COMPOSE_FILE service=$SERVICE profiles=$PROFILES batchSize=$BATCH_SIZE ddlAuto=$DDL_AUTO"
13+
14+
docker compose -f "$COMPOSE_FILE" run --rm \
15+
-e SPRING_PROFILES_ACTIVE="$PROFILES" \
16+
-e SPRING_JPA_HIBERNATE_DDL_AUTO="$DDL_AUTO" \
17+
-e DDL_AUTO="$DDL_AUTO" \
18+
-e DOC_LIST_READ_MODEL_BACKFILL_BATCH_SIZE="$BATCH_SIZE" \
19+
-e MONGO_LOCAL_CLEANUP_ENABLED=false \
20+
-e PERF_SEED_USER_COUNT=0 \
21+
"$SERVICE"

infra/scripts/cert_renew.sh

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,21 @@ ENV_FILE="$ROOT/docsa-alert.env"
1111
notify_slack () {
1212
local msg="$1"
1313
[[ -z "${SLACK_WEBHOOK_URL:-}" ]] && return 0
14+
15+
local payload
16+
payload="$(python3 -c 'import json, sys; print(json.dumps({"text": sys.argv[1]}))' "$msg")"
17+
1418
curl -sS -X POST -H 'Content-type: application/json' \
15-
--data "{\"text\":${msg@Q}}" \
19+
--data "$payload" \
1620
"$SLACK_WEBHOOK_URL" >/dev/null 2>&1 || true
1721
}
1822

1923
# ---- 1) certbot renew 실행 ----
2024
out="$(
2125
docker compose run --rm --no-deps certbot_renew \
22-
certbot renew --webroot -w /var/www/certbot 2>&1 || true
26+
renew --webroot -w /var/www/certbot 2>&1 || true
2327
)"
2428

25-
echo "$out"
26-
2729
# ---- 2) 실패 감지 ----
2830
# certbot이 실패할 때 자주 나오는 문구 위주로 (오탐 줄임)
2931
if echo "$out" | grep -Eqi \

perf/cleanup_perf_docs.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ login_cookie() {
6161
cookie="$(
6262
grep -i '^set-cookie:' "${headers}" \
6363
| tr -d '\r' \
64-
| sed -n "s/^set-cookie:[[:space:]]*${SESSION_COOKIE_NAME}=\\([^;]*\\).*/\\1/p" \
64+
| sed -n "s/^[Ss][Ee][Tt]-[Cc][Oo][Oo][Kk][Ii][Ee]:[[:space:]]*${SESSION_COOKIE_NAME}=\\([^;]*\\).*/\\1/p" \
6565
| head -n 1
6666
)"
6767
rm -f "${headers}" "${body}"

src/main/java/io/ejangs/docsa/DocsaApplication.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
import io.swagger.v3.oas.annotations.info.Info;
55
import org.springframework.boot.SpringApplication;
66
import org.springframework.boot.autoconfigure.SpringBootApplication;
7-
import org.springframework.scheduling.annotation.EnableAsync;
87
import org.springframework.scheduling.annotation.EnableScheduling;
98

109
@OpenAPIDefinition(
@@ -14,7 +13,6 @@
1413
description = "Docsa의 백엔드 API 명세입니다."
1514
)
1615
)
17-
@EnableAsync
1816
@EnableScheduling
1917
@SpringBootApplication
2018
public class DocsaApplication {

src/main/java/io/ejangs/docsa/domain/branch/app/BranchQueryService.java renamed to src/main/java/io/ejangs/docsa/domain/branch/app/BranchReader.java

Lines changed: 1 addition & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,16 @@
44
import io.ejangs.docsa.domain.branch.entity.Branch;
55
import io.ejangs.docsa.domain.commit.entity.Commit;
66
import io.ejangs.docsa.domain.edge.dto.graph.BranchGraphDto;
7-
import io.ejangs.docsa.domain.doc.entity.Doc;
87
import io.ejangs.docsa.global.exception.CustomException;
98
import io.ejangs.docsa.global.exception.errorcode.BranchErrorCode;
10-
import io.ejangs.docsa.global.util.RenewUpdatedAtHelper;
119
import java.util.List;
1210
import lombok.RequiredArgsConstructor;
1311
import org.springframework.stereotype.Service;
1412
import org.springframework.transaction.annotation.Transactional;
1513

1614
@Service
1715
@RequiredArgsConstructor
18-
public class BranchQueryService {
16+
public class BranchReader {
1917

2018
private final BranchRepository branchRepository;
2119

@@ -29,31 +27,11 @@ public List<BranchGraphDto> getBranchGraphList(Long docId) {
2927
return branchRepository.findBranchGraphDtoList(docId);
3028
}
3129

32-
public Branch save(Branch branch) {
33-
return branchRepository.save(branch);
34-
}
35-
36-
public Branch createBranch(Doc doc, String branchName) {
37-
Branch branch = branchRepository.save(Branch.builder().name(branchName).doc(doc).build());
38-
RenewUpdatedAtHelper.touch(branch);
39-
return branch;
40-
}
41-
42-
public Branch createBranch(Doc doc, String branchName, Commit fromCommit) {
43-
Branch branch = Branch.builder().name(branchName).doc(doc).fromCommit(fromCommit).build();
44-
return branchRepository.save(branch);
45-
}
46-
4730
@Transactional(readOnly = true)
4831
public boolean existsSubBranchByFromCommitIds(List<Long> commitIds) {
4932
return branchRepository.existsByFromCommitIdIn(commitIds);
5033
}
5134

52-
public void delete(Branch branch) {
53-
branchRepository.delete(branch);
54-
}
55-
56-
//TODO: 검증하는 메소드는 별도의 ex.ValidationService로 분리(모든 도메인)
5735
public void checkBranchInDocOwnedByUser(Long documentId, Long branchId, Long userId) {
5836
boolean exists =
5937
branchRepository.existsByIdAndDocIdAndDocUserId(branchId, documentId, userId);

0 commit comments

Comments
 (0)