Compare commits
3 Commits
c1ef717d17
...
1c19bac8bc
| Author | SHA1 | Date | |
|---|---|---|---|
| 1c19bac8bc | |||
| cec7fa25e3 | |||
| 774b907da8 |
@@ -14,6 +14,7 @@ JWT_SECRET=geo-web-Aa123456-change-me-in-production
|
|||||||
OPS_JWT_SECRET=geo-ops-Aa123456-change-me-in-production
|
OPS_JWT_SECRET=geo-ops-Aa123456-change-me-in-production
|
||||||
OPS_DEFAULT_ADMIN_PASSWORD=Aa123456
|
OPS_DEFAULT_ADMIN_PASSWORD=Aa123456
|
||||||
SCHEDULER_INTERNAL_METRICS_TOKEN=geo-scheduler-Aa123456-change-me-in-production
|
SCHEDULER_INTERNAL_METRICS_TOKEN=geo-scheduler-Aa123456-change-me-in-production
|
||||||
|
POSTGRES_PASSWORD=geo_dev
|
||||||
|
|
||||||
# ─── Optional: MinIO credentials ─────────────────────────────────────────────
|
# ─── Optional: MinIO credentials ─────────────────────────────────────────────
|
||||||
MINIO_ROOT_USER=admin
|
MINIO_ROOT_USER=admin
|
||||||
|
|||||||
@@ -20,6 +20,8 @@ bash deploy.sh
|
|||||||
docker compose -f docker-compose.yaml -f docker-compose.offline.yaml --env-file .env up -d
|
docker compose -f docker-compose.yaml -f docker-compose.offline.yaml --env-file .env up -d
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Runtime services connect to Postgres through PgBouncer in `session` pooling mode. The one-shot `migrate` job still connects directly to `postgres` and `monitoring-postgres` so DDL and seed work do not go through the pooler.
|
||||||
|
|
||||||
On a k3s host:
|
On a k3s host:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|||||||
+8
-8
@@ -3,24 +3,24 @@ server:
|
|||||||
mode: release
|
mode: release
|
||||||
|
|
||||||
database:
|
database:
|
||||||
host: postgres
|
host: pgbouncer
|
||||||
port: 5432
|
port: 5432
|
||||||
user: geo
|
user: geo
|
||||||
password: geo_dev
|
password: ${POSTGRES_PASSWORD:geo_dev}
|
||||||
dbname: geo
|
dbname: geo
|
||||||
sslmode: disable
|
sslmode: disable
|
||||||
max_open_conns: 25
|
max_open_conns: 12
|
||||||
max_idle_conns: 5
|
max_idle_conns: 3
|
||||||
|
|
||||||
monitoring_database:
|
monitoring_database:
|
||||||
host: monitoring-postgres
|
host: monitoring-pgbouncer
|
||||||
port: 5432
|
port: 5432
|
||||||
user: geo
|
user: geo
|
||||||
password: geo_dev
|
password: ${POSTGRES_PASSWORD:geo_dev}
|
||||||
dbname: geo_monitoring
|
dbname: geo_monitoring
|
||||||
sslmode: disable
|
sslmode: disable
|
||||||
max_open_conns: 25
|
max_open_conns: 8
|
||||||
max_idle_conns: 5
|
max_idle_conns: 2
|
||||||
|
|
||||||
rabbitmq:
|
rabbitmq:
|
||||||
url: amqp://geo:geo_dev@rabbitmq:5672/geo
|
url: amqp://geo:geo_dev@rabbitmq:5672/geo
|
||||||
|
|||||||
@@ -54,6 +54,12 @@ services:
|
|||||||
monitoring-postgres:
|
monitoring-postgres:
|
||||||
pull_policy: never
|
pull_policy: never
|
||||||
|
|
||||||
|
pgbouncer:
|
||||||
|
pull_policy: never
|
||||||
|
|
||||||
|
monitoring-pgbouncer:
|
||||||
|
pull_policy: never
|
||||||
|
|
||||||
rabbitmq:
|
rabbitmq:
|
||||||
pull_policy: never
|
pull_policy: never
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ name: geo-rankly
|
|||||||
|
|
||||||
x-app-env: &app-env
|
x-app-env: &app-env
|
||||||
CONFIG_PATH: /app/configs/config.yaml
|
CONFIG_PATH: /app/configs/config.yaml
|
||||||
|
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-geo_dev}
|
||||||
JWT_SECRET: ${JWT_SECRET:-geo-Aa123456-change-me-in-production}
|
JWT_SECRET: ${JWT_SECRET:-geo-Aa123456-change-me-in-production}
|
||||||
JWT_ACCESS_TTL: ${JWT_ACCESS_TTL:-15m}
|
JWT_ACCESS_TTL: ${JWT_ACCESS_TTL:-15m}
|
||||||
JWT_REFRESH_TTL: ${JWT_REFRESH_TTL:-720h}
|
JWT_REFRESH_TTL: ${JWT_REFRESH_TTL:-720h}
|
||||||
@@ -23,9 +24,9 @@ x-app-volumes: &app-volumes
|
|||||||
- ./prompts.yml:/app/configs/prompts.yml:ro
|
- ./prompts.yml:/app/configs/prompts.yml:ro
|
||||||
|
|
||||||
x-app-depends: &app-depends
|
x-app-depends: &app-depends
|
||||||
postgres:
|
pgbouncer:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
monitoring-postgres:
|
monitoring-pgbouncer:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
rabbitmq:
|
rabbitmq:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
@@ -49,7 +50,7 @@ services:
|
|||||||
environment:
|
environment:
|
||||||
POSTGRES_DB: geo
|
POSTGRES_DB: geo
|
||||||
POSTGRES_USER: geo
|
POSTGRES_USER: geo
|
||||||
POSTGRES_PASSWORD: geo_dev
|
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-geo_dev}
|
||||||
volumes:
|
volumes:
|
||||||
- pgdata:/var/lib/postgresql/data
|
- pgdata:/var/lib/postgresql/data
|
||||||
healthcheck:
|
healthcheck:
|
||||||
@@ -65,7 +66,7 @@ services:
|
|||||||
environment:
|
environment:
|
||||||
POSTGRES_DB: geo_monitoring
|
POSTGRES_DB: geo_monitoring
|
||||||
POSTGRES_USER: geo
|
POSTGRES_USER: geo
|
||||||
POSTGRES_PASSWORD: geo_dev
|
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-geo_dev}
|
||||||
volumes:
|
volumes:
|
||||||
- monitoring_pgdata:/var/lib/postgresql/data
|
- monitoring_pgdata:/var/lib/postgresql/data
|
||||||
healthcheck:
|
healthcheck:
|
||||||
@@ -74,6 +75,72 @@ services:
|
|||||||
timeout: 5s
|
timeout: 5s
|
||||||
retries: 10
|
retries: 10
|
||||||
|
|
||||||
|
pgbouncer:
|
||||||
|
image: edoburu/pgbouncer:v1.24.1-p1
|
||||||
|
container_name: geo-pgbouncer
|
||||||
|
restart: unless-stopped
|
||||||
|
depends_on:
|
||||||
|
postgres:
|
||||||
|
condition: service_healthy
|
||||||
|
environment:
|
||||||
|
DB_HOST: postgres
|
||||||
|
DB_PORT: 5432
|
||||||
|
DB_USER: geo
|
||||||
|
DB_PASSWORD: ${POSTGRES_PASSWORD:-geo_dev}
|
||||||
|
DB_NAME: geo
|
||||||
|
AUTH_TYPE: scram-sha-256
|
||||||
|
POOL_MODE: session
|
||||||
|
MAX_CLIENT_CONN: 200
|
||||||
|
DEFAULT_POOL_SIZE: 30
|
||||||
|
MIN_POOL_SIZE: 2
|
||||||
|
RESERVE_POOL_SIZE: 5
|
||||||
|
RESERVE_POOL_TIMEOUT: 5
|
||||||
|
SERVER_IDLE_TIMEOUT: 60
|
||||||
|
SERVER_LIFETIME: 1800
|
||||||
|
SERVER_CONNECT_TIMEOUT: 15
|
||||||
|
CLIENT_LOGIN_TIMEOUT: 15
|
||||||
|
IGNORE_STARTUP_PARAMETERS: extra_float_digits
|
||||||
|
ADMIN_USERS: geo
|
||||||
|
STATS_USERS: geo
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "PGPASSWORD=\"$${DB_PASSWORD}\" psql -h 127.0.0.1 -p 5432 -U geo -d geo -c 'SELECT 1' >/dev/null"]
|
||||||
|
interval: 5s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 10
|
||||||
|
|
||||||
|
monitoring-pgbouncer:
|
||||||
|
image: edoburu/pgbouncer:v1.24.1-p1
|
||||||
|
container_name: geo-monitoring-pgbouncer
|
||||||
|
restart: unless-stopped
|
||||||
|
depends_on:
|
||||||
|
monitoring-postgres:
|
||||||
|
condition: service_healthy
|
||||||
|
environment:
|
||||||
|
DB_HOST: monitoring-postgres
|
||||||
|
DB_PORT: 5432
|
||||||
|
DB_USER: geo
|
||||||
|
DB_PASSWORD: ${POSTGRES_PASSWORD:-geo_dev}
|
||||||
|
DB_NAME: geo_monitoring
|
||||||
|
AUTH_TYPE: scram-sha-256
|
||||||
|
POOL_MODE: session
|
||||||
|
MAX_CLIENT_CONN: 200
|
||||||
|
DEFAULT_POOL_SIZE: 30
|
||||||
|
MIN_POOL_SIZE: 2
|
||||||
|
RESERVE_POOL_SIZE: 5
|
||||||
|
RESERVE_POOL_TIMEOUT: 5
|
||||||
|
SERVER_IDLE_TIMEOUT: 60
|
||||||
|
SERVER_LIFETIME: 1800
|
||||||
|
SERVER_CONNECT_TIMEOUT: 15
|
||||||
|
CLIENT_LOGIN_TIMEOUT: 15
|
||||||
|
IGNORE_STARTUP_PARAMETERS: extra_float_digits
|
||||||
|
ADMIN_USERS: geo
|
||||||
|
STATS_USERS: geo
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "PGPASSWORD=\"$${DB_PASSWORD}\" psql -h 127.0.0.1 -p 5432 -U geo -d geo_monitoring -c 'SELECT 1' >/dev/null"]
|
||||||
|
interval: 5s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 10
|
||||||
|
|
||||||
rabbitmq:
|
rabbitmq:
|
||||||
image: rabbitmq:3.13-management-alpine
|
image: rabbitmq:3.13-management-alpine
|
||||||
container_name: geo-rabbitmq
|
container_name: geo-rabbitmq
|
||||||
@@ -161,9 +228,10 @@ services:
|
|||||||
- ./prompts.yml:/app/configs/prompts.yml:ro
|
- ./prompts.yml:/app/configs/prompts.yml:ro
|
||||||
entrypoint: >
|
entrypoint: >
|
||||||
/bin/sh -c "
|
/bin/sh -c "
|
||||||
/usr/local/bin/migrate -path /migrations -database 'postgres://geo:geo_dev@postgres:5432/geo?sslmode=disable' up &&
|
export PGPASSWORD='$${POSTGRES_PASSWORD:-geo_dev}' &&
|
||||||
/usr/local/bin/migrate -path /migrations_monitoring -database 'postgres://geo:geo_dev@monitoring-postgres:5432/geo_monitoring?sslmode=disable' up &&
|
/usr/local/bin/migrate -path /migrations -database 'postgres://geo@postgres:5432/geo?sslmode=disable' up &&
|
||||||
/usr/local/bin/migrate -path /migrations_ops -database 'postgres://geo:geo_dev@postgres:5432/geo?sslmode=disable&x-migrations-table=schema_migrations_ops' up &&
|
/usr/local/bin/migrate -path /migrations_monitoring -database 'postgres://geo@monitoring-postgres:5432/geo_monitoring?sslmode=disable' up &&
|
||||||
|
/usr/local/bin/migrate -path /migrations_ops -database 'postgres://geo@postgres:5432/geo?sslmode=disable&x-migrations-table=schema_migrations_ops' up &&
|
||||||
/usr/local/bin/seed-platform-templates
|
/usr/local/bin/seed-platform-templates
|
||||||
"
|
"
|
||||||
restart: "no"
|
restart: "no"
|
||||||
@@ -250,6 +318,8 @@ services:
|
|||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
environment:
|
environment:
|
||||||
CONFIG_PATH: /app/configs/ops-config.yaml
|
CONFIG_PATH: /app/configs/ops-config.yaml
|
||||||
|
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-geo_dev}
|
||||||
|
OPS_POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-geo_dev}
|
||||||
OPS_JWT_SECRET: ${OPS_JWT_SECRET:-change-me-in-production}
|
OPS_JWT_SECRET: ${OPS_JWT_SECRET:-change-me-in-production}
|
||||||
OPS_DEFAULT_ADMIN_USERNAME: ${OPS_DEFAULT_ADMIN_USERNAME:-admin}
|
OPS_DEFAULT_ADMIN_USERNAME: ${OPS_DEFAULT_ADMIN_USERNAME:-admin}
|
||||||
OPS_DEFAULT_ADMIN_PASSWORD: ${OPS_DEFAULT_ADMIN_PASSWORD:-}
|
OPS_DEFAULT_ADMIN_PASSWORD: ${OPS_DEFAULT_ADMIN_PASSWORD:-}
|
||||||
@@ -258,9 +328,9 @@ services:
|
|||||||
volumes:
|
volumes:
|
||||||
- ./ops-config.yaml:/app/configs/ops-config.yaml:ro
|
- ./ops-config.yaml:/app/configs/ops-config.yaml:ro
|
||||||
depends_on:
|
depends_on:
|
||||||
postgres:
|
pgbouncer:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
monitoring-postgres:
|
monitoring-pgbouncer:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
migrate:
|
migrate:
|
||||||
condition: service_completed_successfully
|
condition: service_completed_successfully
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
这套清单用于把当前 Docker Compose 拓扑搬到单节点或小集群 k3s 中。默认包含:
|
这套清单用于把当前 Docker Compose 拓扑搬到单节点或小集群 k3s 中。默认包含:
|
||||||
|
|
||||||
- infra: `postgres`, `monitoring-postgres`, `rabbitmq`, `redis`, `qdrant`, `minio`
|
- infra: `postgres`, `monitoring-postgres`, `pgbouncer`, `monitoring-pgbouncer`, `rabbitmq`, `redis`, `qdrant`, `minio`
|
||||||
- jobs: `migrate`, `minio-init`
|
- jobs: `migrate`, `minio-init`
|
||||||
- apps: `tenant-api`, `worker-generate`, `kol-assist-worker`, `scheduler`, `ops-api`, `frontend`, `ops-web`
|
- apps: `tenant-api`, `worker-generate`, `kol-assist-worker`, `scheduler`, `ops-api`, `frontend`, `ops-web`
|
||||||
- ingress: `geo-rankly.local` -> `frontend`, `ops.geo-rankly.local` -> `ops-web`
|
- ingress: `geo-rankly.local` -> `frontend`, `ops.geo-rankly.local` -> `ops-web`
|
||||||
@@ -38,7 +38,7 @@ sudo k3s ctr images import images.tar
|
|||||||
- `config/config.yaml` 里的 LLM / SiliconFlow API key
|
- `config/config.yaml` 里的 LLM / SiliconFlow API key
|
||||||
- `config.local.yaml` 里对应的数据库、RabbitMQ、MinIO、JWT 配置
|
- `config.local.yaml` 里对应的数据库、RabbitMQ、MinIO、JWT 配置
|
||||||
|
|
||||||
注意:`ops-api` 目前从 `deploy/k3s/config/ops-config.yaml` 读取数据库连接信息;如果改了 Postgres 密码,也同步改这个文件。
|
注意:应用运行时通过 `pgbouncer` / `monitoring-pgbouncer` 访问数据库;`migrate` 任务仍然直连 `postgres` / `monitoring-postgres`。数据库密码统一来自 `POSTGRES_PASSWORD` secret,应用配置和 PgBouncer 都会跟随这个 secret。
|
||||||
|
|
||||||
## 3. 部署
|
## 3. 部署
|
||||||
|
|
||||||
|
|||||||
@@ -38,6 +38,11 @@ spec:
|
|||||||
env:
|
env:
|
||||||
- name: CONFIG_PATH
|
- name: CONFIG_PATH
|
||||||
value: /app/configs/config.yaml
|
value: /app/configs/config.yaml
|
||||||
|
- name: POSTGRES_PASSWORD
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: geo-rankly-app-secret
|
||||||
|
key: POSTGRES_PASSWORD
|
||||||
- name: TZ
|
- name: TZ
|
||||||
value: Asia/Shanghai
|
value: Asia/Shanghai
|
||||||
- name: JWT_SECRET
|
- name: JWT_SECRET
|
||||||
@@ -125,6 +130,11 @@ spec:
|
|||||||
env:
|
env:
|
||||||
- name: CONFIG_PATH
|
- name: CONFIG_PATH
|
||||||
value: /app/configs/config.yaml
|
value: /app/configs/config.yaml
|
||||||
|
- name: POSTGRES_PASSWORD
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: geo-rankly-app-secret
|
||||||
|
key: POSTGRES_PASSWORD
|
||||||
- name: TZ
|
- name: TZ
|
||||||
value: Asia/Shanghai
|
value: Asia/Shanghai
|
||||||
- name: JWT_SECRET
|
- name: JWT_SECRET
|
||||||
@@ -193,6 +203,11 @@ spec:
|
|||||||
env:
|
env:
|
||||||
- name: CONFIG_PATH
|
- name: CONFIG_PATH
|
||||||
value: /app/configs/config.yaml
|
value: /app/configs/config.yaml
|
||||||
|
- name: POSTGRES_PASSWORD
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: geo-rankly-app-secret
|
||||||
|
key: POSTGRES_PASSWORD
|
||||||
- name: TZ
|
- name: TZ
|
||||||
value: Asia/Shanghai
|
value: Asia/Shanghai
|
||||||
- name: JWT_SECRET
|
- name: JWT_SECRET
|
||||||
@@ -278,6 +293,11 @@ spec:
|
|||||||
env:
|
env:
|
||||||
- name: CONFIG_PATH
|
- name: CONFIG_PATH
|
||||||
value: /app/configs/config.yaml
|
value: /app/configs/config.yaml
|
||||||
|
- name: POSTGRES_PASSWORD
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: geo-rankly-app-secret
|
||||||
|
key: POSTGRES_PASSWORD
|
||||||
- name: TZ
|
- name: TZ
|
||||||
value: Asia/Shanghai
|
value: Asia/Shanghai
|
||||||
- name: SCHEDULER_HTTP_HOST
|
- name: SCHEDULER_HTTP_HOST
|
||||||
@@ -384,6 +404,16 @@ spec:
|
|||||||
env:
|
env:
|
||||||
- name: CONFIG_PATH
|
- name: CONFIG_PATH
|
||||||
value: /app/configs/ops-config.yaml
|
value: /app/configs/ops-config.yaml
|
||||||
|
- name: POSTGRES_PASSWORD
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: geo-rankly-app-secret
|
||||||
|
key: POSTGRES_PASSWORD
|
||||||
|
- name: OPS_POSTGRES_PASSWORD
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: geo-rankly-app-secret
|
||||||
|
key: POSTGRES_PASSWORD
|
||||||
- name: TZ
|
- name: TZ
|
||||||
value: Asia/Shanghai
|
value: Asia/Shanghai
|
||||||
- name: OPS_JWT_SECRET
|
- name: OPS_JWT_SECRET
|
||||||
|
|||||||
@@ -3,24 +3,24 @@ server:
|
|||||||
mode: release
|
mode: release
|
||||||
|
|
||||||
database:
|
database:
|
||||||
host: postgres
|
host: pgbouncer
|
||||||
port: 5432
|
port: 5432
|
||||||
user: geo
|
user: geo
|
||||||
password: geo_dev
|
password: ${POSTGRES_PASSWORD:geo_dev}
|
||||||
dbname: geo
|
dbname: geo
|
||||||
sslmode: disable
|
sslmode: disable
|
||||||
max_open_conns: 25
|
max_open_conns: 12
|
||||||
max_idle_conns: 5
|
max_idle_conns: 3
|
||||||
|
|
||||||
monitoring_database:
|
monitoring_database:
|
||||||
host: monitoring-postgres
|
host: monitoring-pgbouncer
|
||||||
port: 5432
|
port: 5432
|
||||||
user: geo
|
user: geo
|
||||||
password: geo_dev
|
password: ${POSTGRES_PASSWORD:geo_dev}
|
||||||
dbname: geo_monitoring
|
dbname: geo_monitoring
|
||||||
sslmode: disable
|
sslmode: disable
|
||||||
max_open_conns: 25
|
max_open_conns: 8
|
||||||
max_idle_conns: 5
|
max_idle_conns: 2
|
||||||
|
|
||||||
rabbitmq:
|
rabbitmq:
|
||||||
url: amqp://geo:geo_dev@rabbitmq:5672/geo
|
url: amqp://geo:geo_dev@rabbitmq:5672/geo
|
||||||
|
|||||||
@@ -3,23 +3,23 @@ server:
|
|||||||
mode: release
|
mode: release
|
||||||
|
|
||||||
database:
|
database:
|
||||||
host: postgres
|
host: pgbouncer
|
||||||
port: 5432
|
port: 5432
|
||||||
user: geo
|
user: geo
|
||||||
password: geo_dev
|
password: ${OPS_POSTGRES_PASSWORD:geo_dev}
|
||||||
dbname: geo
|
dbname: geo
|
||||||
sslmode: disable
|
sslmode: disable
|
||||||
max_open_conns: 10
|
max_open_conns: 5
|
||||||
max_idle_conns: 2
|
max_idle_conns: 2
|
||||||
|
|
||||||
monitoring_database:
|
monitoring_database:
|
||||||
host: monitoring-postgres
|
host: monitoring-pgbouncer
|
||||||
port: 5432
|
port: 5432
|
||||||
user: geo
|
user: geo
|
||||||
password: geo_dev
|
password: ${OPS_POSTGRES_PASSWORD:geo_dev}
|
||||||
dbname: geo_monitoring
|
dbname: geo_monitoring
|
||||||
sslmode: disable
|
sslmode: disable
|
||||||
max_open_conns: 10
|
max_open_conns: 5
|
||||||
max_idle_conns: 2
|
max_idle_conns: 2
|
||||||
|
|
||||||
redis:
|
redis:
|
||||||
|
|||||||
@@ -0,0 +1,203 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: pgbouncer
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: pgbouncer
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
app.kubernetes.io/name: pgbouncer
|
||||||
|
ports:
|
||||||
|
- name: postgres
|
||||||
|
port: 5432
|
||||||
|
targetPort: postgres
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: pgbouncer
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: pgbouncer
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app.kubernetes.io/name: pgbouncer
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: pgbouncer
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: pgbouncer
|
||||||
|
image: edoburu/pgbouncer:v1.24.1-p1
|
||||||
|
imagePullPolicy: IfNotPresent
|
||||||
|
ports:
|
||||||
|
- name: postgres
|
||||||
|
containerPort: 5432
|
||||||
|
env:
|
||||||
|
- name: DB_HOST
|
||||||
|
value: postgres
|
||||||
|
- name: DB_PORT
|
||||||
|
value: "5432"
|
||||||
|
- name: DB_USER
|
||||||
|
value: geo
|
||||||
|
- name: DB_PASSWORD
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: geo-rankly-app-secret
|
||||||
|
key: POSTGRES_PASSWORD
|
||||||
|
- name: DB_NAME
|
||||||
|
value: geo
|
||||||
|
- name: AUTH_TYPE
|
||||||
|
value: scram-sha-256
|
||||||
|
- name: POOL_MODE
|
||||||
|
value: session
|
||||||
|
- name: MAX_CLIENT_CONN
|
||||||
|
value: "200"
|
||||||
|
- name: DEFAULT_POOL_SIZE
|
||||||
|
value: "30"
|
||||||
|
- name: MIN_POOL_SIZE
|
||||||
|
value: "2"
|
||||||
|
- name: RESERVE_POOL_SIZE
|
||||||
|
value: "5"
|
||||||
|
- name: RESERVE_POOL_TIMEOUT
|
||||||
|
value: "5"
|
||||||
|
- name: SERVER_IDLE_TIMEOUT
|
||||||
|
value: "60"
|
||||||
|
- name: SERVER_LIFETIME
|
||||||
|
value: "1800"
|
||||||
|
- name: SERVER_CONNECT_TIMEOUT
|
||||||
|
value: "15"
|
||||||
|
- name: CLIENT_LOGIN_TIMEOUT
|
||||||
|
value: "15"
|
||||||
|
- name: IGNORE_STARTUP_PARAMETERS
|
||||||
|
value: extra_float_digits
|
||||||
|
- name: ADMIN_USERS
|
||||||
|
value: geo
|
||||||
|
- name: STATS_USERS
|
||||||
|
value: geo
|
||||||
|
readinessProbe:
|
||||||
|
exec:
|
||||||
|
command:
|
||||||
|
- /bin/sh
|
||||||
|
- -ec
|
||||||
|
- PGPASSWORD="${DB_PASSWORD}" psql -h 127.0.0.1 -p 5432 -U geo -d geo -c 'SELECT 1' >/dev/null
|
||||||
|
initialDelaySeconds: 5
|
||||||
|
periodSeconds: 5
|
||||||
|
timeoutSeconds: 5
|
||||||
|
livenessProbe:
|
||||||
|
exec:
|
||||||
|
command: ["pg_isready", "-h", "127.0.0.1", "-p", "5432", "-U", "geo", "-d", "geo"]
|
||||||
|
initialDelaySeconds: 30
|
||||||
|
periodSeconds: 10
|
||||||
|
timeoutSeconds: 5
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 50m
|
||||||
|
memory: 64Mi
|
||||||
|
limits:
|
||||||
|
cpu: 500m
|
||||||
|
memory: 256Mi
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: monitoring-pgbouncer
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: monitoring-pgbouncer
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
app.kubernetes.io/name: monitoring-pgbouncer
|
||||||
|
ports:
|
||||||
|
- name: postgres
|
||||||
|
port: 5432
|
||||||
|
targetPort: postgres
|
||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: monitoring-pgbouncer
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: monitoring-pgbouncer
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app.kubernetes.io/name: monitoring-pgbouncer
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: monitoring-pgbouncer
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: pgbouncer
|
||||||
|
image: edoburu/pgbouncer:v1.24.1-p1
|
||||||
|
imagePullPolicy: IfNotPresent
|
||||||
|
ports:
|
||||||
|
- name: postgres
|
||||||
|
containerPort: 5432
|
||||||
|
env:
|
||||||
|
- name: DB_HOST
|
||||||
|
value: monitoring-postgres
|
||||||
|
- name: DB_PORT
|
||||||
|
value: "5432"
|
||||||
|
- name: DB_USER
|
||||||
|
value: geo
|
||||||
|
- name: DB_PASSWORD
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: geo-rankly-app-secret
|
||||||
|
key: POSTGRES_PASSWORD
|
||||||
|
- name: DB_NAME
|
||||||
|
value: geo_monitoring
|
||||||
|
- name: AUTH_TYPE
|
||||||
|
value: scram-sha-256
|
||||||
|
- name: POOL_MODE
|
||||||
|
value: session
|
||||||
|
- name: MAX_CLIENT_CONN
|
||||||
|
value: "200"
|
||||||
|
- name: DEFAULT_POOL_SIZE
|
||||||
|
value: "30"
|
||||||
|
- name: MIN_POOL_SIZE
|
||||||
|
value: "2"
|
||||||
|
- name: RESERVE_POOL_SIZE
|
||||||
|
value: "5"
|
||||||
|
- name: RESERVE_POOL_TIMEOUT
|
||||||
|
value: "5"
|
||||||
|
- name: SERVER_IDLE_TIMEOUT
|
||||||
|
value: "60"
|
||||||
|
- name: SERVER_LIFETIME
|
||||||
|
value: "1800"
|
||||||
|
- name: SERVER_CONNECT_TIMEOUT
|
||||||
|
value: "15"
|
||||||
|
- name: CLIENT_LOGIN_TIMEOUT
|
||||||
|
value: "15"
|
||||||
|
- name: IGNORE_STARTUP_PARAMETERS
|
||||||
|
value: extra_float_digits
|
||||||
|
- name: ADMIN_USERS
|
||||||
|
value: geo
|
||||||
|
- name: STATS_USERS
|
||||||
|
value: geo
|
||||||
|
readinessProbe:
|
||||||
|
exec:
|
||||||
|
command:
|
||||||
|
- /bin/sh
|
||||||
|
- -ec
|
||||||
|
- PGPASSWORD="${DB_PASSWORD}" psql -h 127.0.0.1 -p 5432 -U geo -d geo_monitoring -c 'SELECT 1' >/dev/null
|
||||||
|
initialDelaySeconds: 5
|
||||||
|
periodSeconds: 5
|
||||||
|
timeoutSeconds: 5
|
||||||
|
livenessProbe:
|
||||||
|
exec:
|
||||||
|
command: ["pg_isready", "-h", "127.0.0.1", "-p", "5432", "-U", "geo", "-d", "geo_monitoring"]
|
||||||
|
initialDelaySeconds: 30
|
||||||
|
periodSeconds: 10
|
||||||
|
timeoutSeconds: 5
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 50m
|
||||||
|
memory: 64Mi
|
||||||
|
limits:
|
||||||
|
cpu: 500m
|
||||||
|
memory: 256Mi
|
||||||
@@ -70,9 +70,10 @@ spec:
|
|||||||
- /bin/sh
|
- /bin/sh
|
||||||
- -ec
|
- -ec
|
||||||
- |
|
- |
|
||||||
/usr/local/bin/migrate -path /migrations -database "postgres://geo:${POSTGRES_PASSWORD}@postgres:5432/geo?sslmode=disable" up
|
export PGPASSWORD="${POSTGRES_PASSWORD}"
|
||||||
/usr/local/bin/migrate -path /migrations_monitoring -database "postgres://geo:${POSTGRES_PASSWORD}@monitoring-postgres:5432/geo_monitoring?sslmode=disable" up
|
/usr/local/bin/migrate -path /migrations -database "postgres://geo@postgres:5432/geo?sslmode=disable" up
|
||||||
/usr/local/bin/migrate -path /migrations_ops -database "postgres://geo:${POSTGRES_PASSWORD}@postgres:5432/geo?sslmode=disable&x-migrations-table=schema_migrations_ops" up
|
/usr/local/bin/migrate -path /migrations_monitoring -database "postgres://geo@monitoring-postgres:5432/geo_monitoring?sslmode=disable" up
|
||||||
|
/usr/local/bin/migrate -path /migrations_ops -database "postgres://geo@postgres:5432/geo?sslmode=disable&x-migrations-table=schema_migrations_ops" up
|
||||||
/usr/local/bin/seed-platform-templates
|
/usr/local/bin/seed-platform-templates
|
||||||
volumes:
|
volumes:
|
||||||
- name: app-config
|
- name: app-config
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ resources:
|
|||||||
- secrets.yaml
|
- secrets.yaml
|
||||||
- infra-postgres.yaml
|
- infra-postgres.yaml
|
||||||
- infra-monitoring-postgres.yaml
|
- infra-monitoring-postgres.yaml
|
||||||
|
- infra-pgbouncer.yaml
|
||||||
- infra-rabbitmq.yaml
|
- infra-rabbitmq.yaml
|
||||||
- infra-redis.yaml
|
- infra-redis.yaml
|
||||||
- infra-qdrant-minio.yaml
|
- infra-qdrant-minio.yaml
|
||||||
|
|||||||
@@ -14,10 +14,10 @@ stringData:
|
|||||||
SCHEDULER_INTERNAL_METRICS_TOKEN: geo-metrics-token
|
SCHEDULER_INTERNAL_METRICS_TOKEN: geo-metrics-token
|
||||||
config.local.yaml: |
|
config.local.yaml: |
|
||||||
database:
|
database:
|
||||||
password: geo_dev
|
password: ${POSTGRES_PASSWORD:geo_dev}
|
||||||
|
|
||||||
monitoring_database:
|
monitoring_database:
|
||||||
password: geo_dev
|
password: ${POSTGRES_PASSWORD:geo_dev}
|
||||||
|
|
||||||
rabbitmq:
|
rabbitmq:
|
||||||
url: amqp://geo:geo_dev@rabbitmq:5672/geo
|
url: amqp://geo:geo_dev@rabbitmq:5672/geo
|
||||||
|
|||||||
@@ -3,23 +3,23 @@ server:
|
|||||||
mode: release
|
mode: release
|
||||||
|
|
||||||
database:
|
database:
|
||||||
host: postgres
|
host: pgbouncer
|
||||||
port: 5432
|
port: 5432
|
||||||
user: geo
|
user: geo
|
||||||
password: geo_dev
|
password: ${OPS_POSTGRES_PASSWORD:geo_dev}
|
||||||
dbname: geo
|
dbname: geo
|
||||||
sslmode: disable
|
sslmode: disable
|
||||||
max_open_conns: 10
|
max_open_conns: 5
|
||||||
max_idle_conns: 2
|
max_idle_conns: 2
|
||||||
|
|
||||||
monitoring_database:
|
monitoring_database:
|
||||||
host: monitoring-postgres
|
host: monitoring-pgbouncer
|
||||||
port: 5432
|
port: 5432
|
||||||
user: geo
|
user: geo
|
||||||
password: geo_dev
|
password: ${OPS_POSTGRES_PASSWORD:geo_dev}
|
||||||
dbname: geo_monitoring
|
dbname: geo_monitoring
|
||||||
sslmode: disable
|
sslmode: disable
|
||||||
max_open_conns: 10
|
max_open_conns: 5
|
||||||
max_idle_conns: 2
|
max_idle_conns: 2
|
||||||
|
|
||||||
redis:
|
redis:
|
||||||
|
|||||||
@@ -108,6 +108,7 @@ fi
|
|||||||
echo "==> [2/5] 拉取基础设施镜像 (platform: ${PLATFORM})"
|
echo "==> [2/5] 拉取基础设施镜像 (platform: ${PLATFORM})"
|
||||||
INFRA_IMAGES=(
|
INFRA_IMAGES=(
|
||||||
"postgres:16-alpine"
|
"postgres:16-alpine"
|
||||||
|
"edoburu/pgbouncer:v1.24.1-p1"
|
||||||
"rabbitmq:3.13-management-alpine"
|
"rabbitmq:3.13-management-alpine"
|
||||||
"redis:7-alpine"
|
"redis:7-alpine"
|
||||||
"qdrant/qdrant:v1.13.2"
|
"qdrant/qdrant:v1.13.2"
|
||||||
@@ -134,6 +135,7 @@ ALL_IMAGES=(
|
|||||||
"${LOCAL_PREFIX}/frontend:${IMAGE_TAG}"
|
"${LOCAL_PREFIX}/frontend:${IMAGE_TAG}"
|
||||||
"${LOCAL_PREFIX}/ops-web:${IMAGE_TAG}"
|
"${LOCAL_PREFIX}/ops-web:${IMAGE_TAG}"
|
||||||
"postgres:16-alpine"
|
"postgres:16-alpine"
|
||||||
|
"edoburu/pgbouncer:v1.24.1-p1"
|
||||||
"rabbitmq:3.13-management-alpine"
|
"rabbitmq:3.13-management-alpine"
|
||||||
"redis:7-alpine"
|
"redis:7-alpine"
|
||||||
"qdrant/qdrant:v1.13.2"
|
"qdrant/qdrant:v1.13.2"
|
||||||
|
|||||||
@@ -236,3 +236,12 @@
|
|||||||
- Gitea Registry secret name is `REGISTRY_PASSWORD`; Gitea rejects secret names beginning with `GITEA_`.
|
- Gitea Registry secret name is `REGISTRY_PASSWORD`; Gitea rejects secret names beginning with `GITEA_`.
|
||||||
- CD workflows verify required commit8 image tags in Gitea Registry before pulling or deploying. Missing images are treated as a failed prerequisite, not as a signal to build during CD.
|
- CD workflows verify required commit8 image tags in Gitea Registry before pulling or deploying. Missing images are treated as a failed prerequisite, not as a signal to build during CD.
|
||||||
- Offline packaging pulls previously published Gitea Registry images into the package; it does not rebuild business images when `SOURCE_IMAGE_REGISTRY` is set by the workflow.
|
- Offline packaging pulls previously published Gitea Registry images into the package; it does not rebuild business images when `SOURCE_IMAGE_REGISTRY` is set by the workflow.
|
||||||
|
|
||||||
|
## Stable PgBouncer Deployment - 2026-05-03
|
||||||
|
- Before this change the deployment had no PgBouncer/pooler service. Runtime services used `pgxpool` and connected directly to `postgres` / `monitoring-postgres`.
|
||||||
|
- Stable-first decision: add PgBouncer in `session` pooling mode, not transaction pooling, so current `pgx` behavior and any session-level assumptions remain compatible.
|
||||||
|
- Runtime services now target `pgbouncer` and `monitoring-pgbouncer`; migration and seed jobs continue to connect directly to the underlying Postgres services.
|
||||||
|
- Application-side pools are intentionally smaller: tenant runtime config uses 12 main DB connections and 8 monitoring DB connections per process; ops runtime uses 5 for each DB.
|
||||||
|
- Offline packages must include `edoburu/pgbouncer:v1.24.1-p1` alongside the existing infra images.
|
||||||
|
- Postgres passwords are passed through environment placeholders instead of hard-coded in deploy configs. The Go DSN builder now URL-escapes credentials so strong passwords containing `@`, `:`, `/`, or `?` remain valid.
|
||||||
|
- Local smoke validation used the existing `server/docker-compose.yaml` Postgres containers on `server_default`; PgBouncer successfully returned `SELECT 1` through the pooler and the temporary test container was removed.
|
||||||
|
|||||||
+17
@@ -706,3 +706,20 @@
|
|||||||
- Added commit8 image verification to compose/k3s/offline deployment paths so CD fails if CI has not produced the required image.
|
- Added commit8 image verification to compose/k3s/offline deployment paths so CD fails if CI has not produced the required image.
|
||||||
- Changed offline package defaults to use commit8 instead of tag names and to pull business images from the Gitea Registry.
|
- Changed offline package defaults to use commit8 instead of tag names and to pull business images from the Gitea Registry.
|
||||||
- Verification passed: workflow YAML parse, deploy script `bash -n`, and `sh -n` over all workflow run blocks.
|
- Verification passed: workflow YAML parse, deploy script `bash -n`, and `sh -n` over all workflow run blocks.
|
||||||
|
|
||||||
|
## 2026-05-03T03:03:09Z - Stable PgBouncer Deployment
|
||||||
|
|
||||||
|
- Confirmed the existing repository topology uses application-side `pgxpool` and direct Postgres service names; no PgBouncer service/config existed before this change.
|
||||||
|
- Started Phase 40 to add stable PgBouncer deployment with session pooling, app runtime traffic through PgBouncer, and migration jobs remaining direct to Postgres.
|
||||||
|
- Added `pgbouncer` and `monitoring-pgbouncer` to production Docker Compose and k3s using `edoburu/pgbouncer:v1.24.1-p1`, `POOL_MODE=session`, and `AUTH_TYPE=scram-sha-256`.
|
||||||
|
- Changed runtime app configs to target PgBouncer while keeping Docker/k3s migration jobs direct to `postgres` / `monitoring-postgres`.
|
||||||
|
- Lowered application-side Postgres pools: tenant runtime uses 12 main / 8 monitoring connections per process; ops runtime uses 5 / 5.
|
||||||
|
- Made deployment passwords flow from `POSTGRES_PASSWORD` / `OPS_POSTGRES_PASSWORD` placeholders and changed `DatabaseConfig.DSN()` to URL-escape credentials for stronger production passwords.
|
||||||
|
- Included PgBouncer in offline packaging and docs.
|
||||||
|
- Verification passed:
|
||||||
|
- `docker compose -f deploy/docker-compose.yaml --env-file deploy/.env.example config`
|
||||||
|
- `kubectl kustomize deploy/k3s` plus local YAML parse
|
||||||
|
- `bash -n deploy/scripts/package.sh`
|
||||||
|
- `git diff --check`
|
||||||
|
- `go test ./internal/shared/config ./internal/shared/repository/postgres ./internal/ops/config`
|
||||||
|
- Temporary PgBouncer container attached to existing `server_default` network returned `SELECT 1` through PgBouncer, then was removed.
|
||||||
|
|||||||
@@ -11,6 +11,9 @@ database:
|
|||||||
user: geo
|
user: geo
|
||||||
password: geo_dev
|
password: geo_dev
|
||||||
dbname: geo
|
dbname: geo
|
||||||
|
sslmode: disable
|
||||||
|
max_open_conns: 12
|
||||||
|
max_idle_conns: 3
|
||||||
|
|
||||||
monitoring_database:
|
monitoring_database:
|
||||||
host: localhost
|
host: localhost
|
||||||
@@ -19,8 +22,8 @@ monitoring_database:
|
|||||||
password: geo_dev
|
password: geo_dev
|
||||||
dbname: geo_monitoring
|
dbname: geo_monitoring
|
||||||
sslmode: disable
|
sslmode: disable
|
||||||
max_open_conns: 25
|
max_open_conns: 8
|
||||||
max_idle_conns: 5
|
max_idle_conns: 2
|
||||||
|
|
||||||
rabbitmq:
|
rabbitmq:
|
||||||
url: amqp://geo:geo_dev@localhost:5672/geo
|
url: amqp://geo:geo_dev@localhost:5672/geo
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ database:
|
|||||||
password: geo_dev
|
password: geo_dev
|
||||||
dbname: geo
|
dbname: geo
|
||||||
sslmode: disable
|
sslmode: disable
|
||||||
max_open_conns: 25
|
max_open_conns: 12
|
||||||
max_idle_conns: 5
|
max_idle_conns: 3
|
||||||
|
|
||||||
monitoring_database:
|
monitoring_database:
|
||||||
host: localhost
|
host: localhost
|
||||||
@@ -19,8 +19,8 @@ monitoring_database:
|
|||||||
password: geo_dev
|
password: geo_dev
|
||||||
dbname: geo_monitoring
|
dbname: geo_monitoring
|
||||||
sslmode: disable
|
sslmode: disable
|
||||||
max_open_conns: 25
|
max_open_conns: 8
|
||||||
max_idle_conns: 5
|
max_idle_conns: 2
|
||||||
|
|
||||||
rabbitmq:
|
rabbitmq:
|
||||||
url: amqp://geo:geo_dev@localhost:5672/geo
|
url: amqp://geo:geo_dev@localhost:5672/geo
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ database:
|
|||||||
password: geo_dev
|
password: geo_dev
|
||||||
dbname: geo
|
dbname: geo
|
||||||
sslmode: disable
|
sslmode: disable
|
||||||
max_open_conns: 10
|
max_open_conns: 5
|
||||||
max_idle_conns: 2
|
max_idle_conns: 2
|
||||||
|
|
||||||
monitoring_database:
|
monitoring_database:
|
||||||
@@ -19,7 +19,7 @@ monitoring_database:
|
|||||||
password: geo_dev
|
password: geo_dev
|
||||||
dbname: geo_monitoring
|
dbname: geo_monitoring
|
||||||
sslmode: disable
|
sslmode: disable
|
||||||
max_open_conns: 10
|
max_open_conns: 5
|
||||||
max_idle_conns: 2
|
max_idle_conns: 2
|
||||||
|
|
||||||
redis:
|
redis:
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ import (
|
|||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@@ -53,8 +55,16 @@ type DatabaseConfig struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d DatabaseConfig) DSN() string {
|
func (d DatabaseConfig) DSN() string {
|
||||||
return fmt.Sprintf("postgres://%s:%s@%s:%d/%s?sslmode=%s",
|
u := url.URL{
|
||||||
d.User, d.Password, d.Host, d.Port, d.DBName, d.SSLMode)
|
Scheme: "postgres",
|
||||||
|
User: url.UserPassword(d.User, d.Password),
|
||||||
|
Host: net.JoinHostPort(d.Host, fmt.Sprintf("%d", d.Port)),
|
||||||
|
Path: "/" + d.DBName,
|
||||||
|
}
|
||||||
|
q := u.Query()
|
||||||
|
q.Set("sslmode", d.SSLMode)
|
||||||
|
u.RawQuery = q.Encode()
|
||||||
|
return u.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
type RedisConfig struct {
|
type RedisConfig struct {
|
||||||
|
|||||||
@@ -27,6 +27,23 @@ llm:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDatabaseConfigDSNEscapesCredentials(t *testing.T) {
|
||||||
|
cfg := DatabaseConfig{
|
||||||
|
Host: "db.internal",
|
||||||
|
Port: 5432,
|
||||||
|
User: "geo",
|
||||||
|
Password: "p@ss:word/with?symbols",
|
||||||
|
DBName: "geo",
|
||||||
|
SSLMode: "disable",
|
||||||
|
}
|
||||||
|
|
||||||
|
got := cfg.DSN()
|
||||||
|
want := "postgres://geo:p%40ss%3Aword%2Fwith%3Fsymbols@db.internal:5432/geo?sslmode=disable"
|
||||||
|
if got != want {
|
||||||
|
t.Fatalf("DSN() = %q, want %q", got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestLoadFallsBackToConfigLLMAPIKey(t *testing.T) {
|
func TestLoadFallsBackToConfigLLMAPIKey(t *testing.T) {
|
||||||
t.Setenv("LLM_API_KEY", "")
|
t.Setenv("LLM_API_KEY", "")
|
||||||
|
|
||||||
|
|||||||
+10
-1
@@ -4,7 +4,7 @@
|
|||||||
Continue the desktop AI monitoring implementation by first adding a client-side local scheduler with durable queueing and adaptive execution policy, then adding a reusable hidden Playwright CDP execution layer that attaches to Electron Chromium and reuses existing account partitions.
|
Continue the desktop AI monitoring implementation by first adding a client-side local scheduler with durable queueing and adaptive execution policy, then adding a reusable hidden Playwright CDP execution layer that attaches to Electron Chromium and reuses existing account partitions.
|
||||||
|
|
||||||
## Current Phase
|
## Current Phase
|
||||||
Phase 37
|
Phase 40
|
||||||
|
|
||||||
## Phases
|
## Phases
|
||||||
### Phase 1: Progress Verification
|
### Phase 1: Progress Verification
|
||||||
@@ -276,6 +276,14 @@ Phase 37
|
|||||||
- [x] Run workflow YAML and shell syntax checks
|
- [x] Run workflow YAML and shell syntax checks
|
||||||
- **Status:** complete
|
- **Status:** complete
|
||||||
|
|
||||||
|
### Phase 40: Stable PgBouncer Deployment
|
||||||
|
- [x] Add PgBouncer infrastructure to Docker Compose and k3s
|
||||||
|
- [x] Route runtime services through PgBouncer while keeping migrations direct to Postgres
|
||||||
|
- [x] Lower application-side connection pools for stability
|
||||||
|
- [x] Include PgBouncer in offline packaging and deployment docs
|
||||||
|
- [x] Validate rendered deployment/config files
|
||||||
|
- **Status:** complete
|
||||||
|
|
||||||
## Key Questions
|
## Key Questions
|
||||||
1. How should the desktop client defer and locally optimize monitor-task execution without violating one-task-per-platform serialism?
|
1. How should the desktop client defer and locally optimize monitor-task execution without violating one-task-per-platform serialism?
|
||||||
2. What is the smallest durable local cache that allows same-day resume while safely dropping stale next-day monitor tasks?
|
2. What is the smallest durable local cache that allows same-day resume while safely dropping stale next-day monitor tasks?
|
||||||
@@ -343,6 +351,7 @@ Phase 37
|
|||||||
| `connectOverCDP()` is not wired yet even though `playwright-core` is installed | 1 | Add a dedicated hidden-browser manager instead of pushing CDP code directly into adapters or the runtime controller |
|
| `connectOverCDP()` is not wired yet even though `playwright-core` is installed | 1 | Add a dedicated hidden-browser manager instead of pushing CDP code directly into adapters or the runtime controller |
|
||||||
| `pnpm --filter @geo/desktop-client typecheck` fails in `electron.vite.config.ts` due to a pre-existing Vite 5/8 plugin type mismatch | 1 | Verified this change with `pnpm --filter @geo/desktop-client build` and `pnpm --filter @geo/desktop-client test`; leave config dependency alignment as a separate fix |
|
| `pnpm --filter @geo/desktop-client typecheck` fails in `electron.vite.config.ts` due to a pre-existing Vite 5/8 plugin type mismatch | 1 | Verified this change with `pnpm --filter @geo/desktop-client build` and `pnpm --filter @geo/desktop-client test`; leave config dependency alignment as a separate fix |
|
||||||
| `kubectl apply --dry-run=client` still attempted to contact the local kube-apiserver, which is not running at `127.0.0.1:26443` | 1 | Verified with `kubectl kustomize`, parsed the rendered YAML locally, and recorded that live API validation should run on the target k3s cluster |
|
| `kubectl apply --dry-run=client` still attempted to contact the local kube-apiserver, which is not running at `127.0.0.1:26443` | 1 | Verified with `kubectl kustomize`, parsed the rendered YAML locally, and recorded that live API validation should run on the target k3s cluster |
|
||||||
|
| Production compose PgBouncer smoke test could not start bundled Postgres containers because existing `server/docker-compose.yaml` containers already own `geo-postgres` / `geo-monitoring-postgres` names | 1 | Did not stop user/local DB containers; verified PgBouncer with a temporary test container attached to the existing `server_default` network and removed it after `SELECT 1` passed |
|
||||||
|
|
||||||
## Notes
|
## Notes
|
||||||
- Re-check task_plan.md before major implementation decisions.
|
- Re-check task_plan.md before major implementation decisions.
|
||||||
|
|||||||
Reference in New Issue
Block a user