Skip to content
Merged
22 changes: 11 additions & 11 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,18 +38,18 @@

## 2) REPOSITORY LAYOUT & MODULES

| Path | Purpose |
| -------------------------------------------------------------- | --------------------------------------------------------- |
| `backend/cmd/marketplace/product-query-svc` | 进程入口与依赖注入(路由、仓库、配置)。 |
| `apps/product-query-svc/domain` | 领域聚合与不变式(`Product`, `Comment`, `User`)。无 http/sql/env 依赖。 |
| `apps/product-query-svc/application` | 用例编排(实现入站端口),只依赖 `ports` 与 `domain`。 |
| `apps/product-query-svc/adapters` | 入站 HTTP handlers;出站持久化实现。禁止写业务规则。 |
| Path | Purpose |
| -------------------------------------------------- | --------------------------------------------------------- |
| `backend/cmd/product-query-svc` | 进程入口与依赖注入(路由、仓库、配置)。 |
| `apps/product-query-svc/domain` | 领域聚合与不变式(`Product`, `Comment`, `User`)。无 http/sql/env 依赖。 |
| `apps/product-query-svc/application` | 用例编排(实现入站端口),只依赖 `ports` 与 `domain`。 |
| `apps/product-query-svc/adapters` | 入站 HTTP handlers;出站持久化实现。禁止写业务规则。 |
| `apps/product-query-svc/adapters/outbound/postgres/migrations` | SQL 迁移(使用 `migrate` 工具)。 |
| `apps/product-query-svc/api/openapi.yaml` | OpenAPI 单一事实源。 |
| `apps/product-query-svc/api/gen` | oapi-codegen 生成物(**禁止手改**)。 |
| `test` | 端到端与集成测试(内存/PG 双路径)。 |
| `scripts`, `Makefile` | 开发脚本、构建、DB 设置、集成流程。 |
| `charts`, `k8s`, `kind` | 部署清单,配置变化时同步。 |
| `apps/product-query-svc/api/openapi.yaml` | OpenAPI 单一事实源。 |
| `apps/product-query-svc/api/gen` | oapi-codegen 生成物(**禁止手改**)。 |
| `test` | 端到端与集成测试(内存/PG 双路径)。 |
| `scripts`, `Makefile` | 开发脚本、构建、DB 设置、集成流程。 |
| `charts`, `k8s`, `kind` | 部署清单,配置变化时同步。 |

**分层约定**

Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ COPY . .
RUN --mount=type=cache,target=/go/pkg/mod \
--mount=type=cache,target=/root/.cache/go-build \
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 \
go build -o /out/product-query-svc ./backend/cmd/marketplace/product-query-svc
go build -o /out/product-query-svc ./backend/cmd/product-query-svc

# Runtime
FROM gcr.io/distroless/base-debian12:nonroot
Expand Down
7 changes: 5 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Makefile for common tasks
.PHONY: gen build run fmt tidy migrate-up migrate-down migrate-create db-init
.PHONY: gen build run fmt tidy migrate-up migrate-down migrate-create db-init test-repo-docker

SERVICE_PKG=./backend/cmd/marketplace/product-query-svc
SERVICE_PKG=./backend/cmd/product-query-svc
BIN_DIR=bin
BIN=$(BIN_DIR)/product-query-svc

Expand Down Expand Up @@ -41,6 +41,9 @@ db-init:
test-integration-docker:
bash scripts/test-integration-docker.sh ./test -run Postgres

test-repo-docker:
go test -tags docker ./apps/product-query-svc/adapters/outbound/postgres -run TestCommentRepository_WithDocker -count=1


# Notes:
# - Requires golang-migrate installed to use migrate-* targets
Expand Down
2 changes: 1 addition & 1 deletion Tiltfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
# Many Tilt installs don't provide that ext; omit the load to avoid startup errors.

# Settings
namespace = 'marketplace-dev'
namespace = 'gopractice-dev'
svc_name = 'product-query-svc'
# Starlark (Tiltfile) 不支持 Python f-strings,使用字符串连接
docker_ref = svc_name + ':dev'
Expand Down
2 changes: 1 addition & 1 deletion api/generate.go
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen@latest -config ./oapi-config.yaml ./openapi.yaml
package marketplaceapi
package gopracticeapi
2 changes: 1 addition & 1 deletion api/oapi-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ generate:
- chi-server # 生成 chi server 接口
- strict-server # 生成严格 server 接口(带类型安全)
- spec # 生成 embedded swagger spec
output: ../apps/product-query-svc/adapters/inbound/http/marketplaceapi.gen.go
output: ../apps/product-query-svc/adapters/inbound/http/gopracticeapi.gen.go
2 changes: 1 addition & 1 deletion api/openapi.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
openapi: 3.0.0
info:
title: Marketplace Demo API
title: gopractice Demo API
version: 1.0.0
tags:
- name: Products
Expand Down
2 changes: 1 addition & 1 deletion apps/product-query-svc/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ Domain
apps/product-query-svc/domain/product.go (实体/校验)

Composition Root(组装根)
backend/cmd/marketplace/product-query-svc/main.go
backend/cmd/gopractice/product-query-svc/main.go
- 读取配置,选择 inmem 或 postgres 作为 ProductRepository 的实现
- 构造 productapp.Service,并作为 ports/inbound.ProductUseCases 注入 HTTP 适配器
- 启动 HTTP 服务器
Expand Down
4 changes: 2 additions & 2 deletions charts/product-query-svc/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ resources:
env:
HTTP_ADDRESS: ":8080"
# App listen address; DATABASE_URL now comes from .Values.database.secret when enabled
DATABASE_URL: "postgres://app:app_password@postgres.marketplace-dev.svc.cluster.local:5432/productdb?sslmode=disable" # fallback only
DATABASE_URL: "postgres://app:app_password@postgres.gopractice-dev.svc.cluster.local:5432/productdb?sslmode=disable" # fallback only

podAnnotations: {}
replicaCount: 1
Expand All @@ -37,4 +37,4 @@ database:
key: DATABASE_URL
create: false
# If create=true, a Secret will be created with this URL as stringData.DATABASE_URL
url: "postgres://app:app_password@postgres.marketplace-dev.svc.cluster.local:5432/productdb?sslmode=disable"
url: "postgres://app:app_password@postgres.gopractice-dev.svc.cluster.local:5432/productdb?sslmode=disable"
6 changes: 3 additions & 3 deletions k8s/config-app.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ apiVersion: v1
kind: Secret
metadata:
name: pg-secret
namespace: marketplace-dev
namespace: gopractice-dev
stringData:
POSTGRES_DB: productdb
POSTGRES_USER: app
Expand All @@ -12,9 +12,9 @@ apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
namespace: marketplace-dev
namespace: gopractice-dev
data:
LOG_LEVEL: debug
HTTP_ADDRESS: ":8080"
DATABASE_URL: "postgres://app:app_password@postgres.marketplace-dev.svc.cluster.local:5432/productdb?sslmode=disable"
DATABASE_URL: "postgres://app:app_password@postgres.gopractice-dev.svc.cluster.local:5432/productdb?sslmode=disable"

2 changes: 1 addition & 1 deletion k8s/namespace.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
apiVersion: v1
kind: Namespace
metadata:
name: marketplace-dev
name: gopractice-dev

4 changes: 2 additions & 2 deletions k8s/postgres.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ apiVersion: v1
kind: Service
metadata:
name: postgres
namespace: marketplace-dev
namespace: gopractice-dev
spec:
ports:
- port: 5432
Expand All @@ -14,7 +14,7 @@ apiVersion: apps/v1
kind: StatefulSet
metadata:
name: postgres
namespace: marketplace-dev
namespace: gopractice-dev
spec:
selector:
matchLabels:
Expand Down
4 changes: 2 additions & 2 deletions k8s/product-query-svc.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ apiVersion: v1
kind: Service
metadata:
name: product-query-svc
namespace: marketplace-dev
namespace: gopractice-dev
spec:
selector:
app: product-query-svc
Expand All @@ -16,7 +16,7 @@ apiVersion: apps/v1
kind: Deployment
metadata:
name: product-query-svc
namespace: marketplace-dev
namespace: gopractice-dev
spec:
replicas: 1
selector:
Expand Down
28 changes: 14 additions & 14 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
│ ├── inmem/ # 内存仓储实现(开发/测试)
│ └── postgres/ # Postgres 仓储与迁移文件
├── backend/
│ └── cmd/marketplace/product-query-svc/ # 可执行入口(main.go),装配路由/依赖
│ └── cmd/product-query-svc/ # 可执行入口(main.go),装配路由/依赖
├── charts/product-query-svc/ # 最小 Helm Chart(含迁移 Job 与 ConfigMap)
├── k8s/ # 直接应用的 Kubernetes 清单(Service/Deployment/Postgres)
├── kind/ # kind 本地集群配置
Expand All @@ -55,7 +55,7 @@

## HTTP 适配器设计(Strict Server)

- **代码生成统一使用 `oapi-codegen strict-server`**:`api/oapi-config.yaml` 只保留严格服务输出,避免手写 handler 接口。每次变更 OpenAPI 需执行 `go generate ./api` 重新生成 `marketplaceapi.gen.go`。
- **代码生成统一使用 `oapi-codegen strict-server`**:`api/oapi-config.yaml` 只保留严格服务输出,避免手写 handler 接口。每次变更 OpenAPI 需执行 `go generate ./api` 重新生成 `gopracticeapi.gen.go`。
- **请求校验前移到 OpenAPI**:所有参数/请求体验证(`minimum`/`maxLength`/`enum` 等)写在 `api` 目录的 schema/parameter 中,由 `github.com/oapi-codegen/nethttp-middleware` 提供的 `OapiRequestValidator` 中间件统一拦截。
- **Handler 职责“三件套”**(`apps/product-query-svc/adapters/inbound/http/handler_*.go`):
1. 从生成的强类型 `RequestObject` 中取出入参(无需重复校验);
Expand Down Expand Up @@ -180,7 +180,7 @@ bash scripts/test-integration-docker.sh ./test -run Postgres
- 使用 `docker run -P` 启动 postgres:16-alpine,随机映射宿主端口,避免与 Tilt 的 5432 冲突。
- 通过 `migrate/migrate` 容器在同一网络命名空间内执行迁移。
- 自动导出 `DATABASE_URL` 为宿主上的随机端口,并运行 go test。
- 需要单独验证仓储层(含评论 CRUD)的 Docker 集成测试时,可运行 `go test -tags docker ./apps/product-query-svc/adapters/outbound/postgres -run TestCommentRepository_WithDocker -count=1`,确保本机 Docker 可用;若暂不具备条件,可设置 `SKIP_DOCKER_TESTS=1` 跳过。
- 需要单独验证仓储层(含评论 CRUD)的 Docker 集成测试时,可运行 `make test-repo-docker`(依赖本机 Docker);若暂不具备条件,可设置 `SKIP_DOCKER_TESTS=1 make test-repo-docker` 跳过实际容器启动。

</details>

Expand Down Expand Up @@ -209,9 +209,9 @@ curl -s http://localhost:8080/products/1 | jq
- Pod/日志排查

```sh
kubectl -n marketplace-dev get pods
kubectl -n marketplace-dev logs deploy/product-query-svc
kubectl -n marketplace-dev logs statefulset/postgres
kubectl -n -dev get pods
kubectl -n -dev logs deploy/product-query-svc
kubectl -n -dev logs statefulset/postgres
```

---
Expand All @@ -227,7 +227,7 @@ kubectl -n marketplace-dev logs statefulset/postgres
1. 启动 Postgres(示例):

```sh
docker run --name marketplace-postgres \
docker run --name -postgres \
-e POSTGRES_USER=app \
-e POSTGRES_PASSWORD=app_password \
-e POSTGRES_DB=productdb \
Expand All @@ -245,14 +245,14 @@ export LOG_LEVEL=debug
1. 运行服务(开发):

```sh
cd backend/cmd/marketplace/product-query-svc
cd backend/cmd/product-query-svc
go run .
```

或构建后运行:

```sh
go build -o bin/product-query-svc ./backend/cmd/marketplace/product-query-svc
go build -o bin/product-query-svc ./backend/cmd/product-query-svc
./bin/product-query-svc
```

Expand Down Expand Up @@ -313,7 +313,7 @@ psql "postgres://app:app_password@localhost:5432/productdb"
- 如需修改连接串,可在 Tiltfile 顶部调整 `MIGRATE_URL`。

- 在 K8s/Helm 中执行(集群内)
- 可选:用 Helm hook 或 Job 在集群内运行 `migrate/migrate`,`DATABASE_URL` 使用集群内 Service(例如 `postgres.marketplace-dev.svc.cluster.local`)。需要的话可以补充该 Job。
- 可选:用 Helm hook 或 Job 在集群内运行 `migrate/migrate`,`DATABASE_URL` 使用集群内 Service(例如 `postgres.-dev.svc.cluster.local`)。需要的话可以补充该 Job。

常见避坑:

Expand Down Expand Up @@ -362,7 +362,7 @@ Helm 迁移 Job:
docker build -t product-query-svc:dev .
```

注:Dockerfile 默认构建 backend/cmd/marketplace/product-query-svc 的二进制,用于镜像/部署。
注:Dockerfile 默认构建 backend/cmd/product-query-svc 的二进制,用于镜像/部署。

---

Expand All @@ -380,7 +380,7 @@ go generate ./api
# 或者根据 generate.go 的 //go:generate 指定路径
```

- 生成后的 `adapters/inbound/http/marketplaceapi.gen.go` **禁止手动修改**;需要调整校验或字段时改 OpenAPI 资源并重新生成。
- 生成后的 `adapters/inbound/http/api.gen.go` **禁止手动修改**;需要调整校验或字段时改 OpenAPI 资源并重新生成。
- HTTP handler 只能依赖生成的 `StrictServerInterface`,其实现位于 `handler_*.go`,必须配合 `response_helpers.go` 和 `request_mappers.go` 使用。
- `NewAPIHandler` 会自动加载最新的 Swagger 并注册 `OapiRequestValidator` 中间件,生产/测试入口都应通过该函数获取路由。

Expand Down Expand Up @@ -431,7 +431,7 @@ go generate ./api
<details>
<summary>批次 5 — 后端入口 / wiring / router</summary>

- 相关文件:backend/cmd/marketplace/product-query-svc、apps/product-query-svc/adapters/inbound/http/
- 相关文件:backend/cmd/product-query-svc、apps/product-query-svc/adapters/inbound/http/
- 建议 commit message:"chore: add service main and HTTP wiring (router & handlers)"

</details>
Expand Down Expand Up @@ -460,6 +460,6 @@ go generate ./api

- "FATAL: database \"app\" does not exist":确认 Postgres 启动时环境变量 POSTGRES_DB 与服务的 DATABASE_URL 中数据库名一致(示例使用 productdb);或手动创建数据库。
- Docker 构建报 "go.mod: unknown directive: tool":请使用与 go.mod 中 toolchain 对齐的 Go 版本(本项目使用 1.24)。
- Lens 中看不到资源:确认 Lens 使用的 kubeconfig 与 kubectl 当前上下文一致,并且查看正确命名空间(marketplace-dev)。
- Lens 中看不到资源:确认 Lens 使用的 kubeconfig 与 kubectl 当前上下文一致,并且查看正确命名空间(-dev)。

</details>
Loading