时间字段改由业务层生成并传入

This commit is contained in:
fish
2026-04-13 21:38:04 +08:00
parent 66e553c7c8
commit dc1056ffb0
4 changed files with 45 additions and 17 deletions

View File

@@ -162,7 +162,19 @@ OK
struct ApiResponse<T> { success: bool, message: String, data: Option<T> } struct ApiResponse<T> { success: bool, message: String, data: Option<T> }
``` ```
### 2. 环境变量 ### 3. 时间字段约定
所有表中的 `createdate` 和 `modifydate` **必须由业务层生成并传入**数据库Schema中**不设置** `DEFAULT CURRENT_TIMESTAMP`,也不使用触发器自动更新。
- 建表时:
```sql
createdate TIMESTAMP WITH TIME ZONE NOT NULL,
modifydate TIMESTAMP WITH TIME ZONE NOT NULL
```
- Rust 代码中使用 `chrono::Utc::now()` 生成时间戳,统一在事务开始前创建 `let now = Utc::now();`,确保同一笔业务中各表时间一致。
- `modifydate` 更新时同样需要在业务代码中显式传入 `Utc::now()`。
### 4. 环境变量
所有服务通过环境变量读取配置: 所有服务通过环境变量读取配置:
- `DATABASE_URL` — PostgreSQL 连接串(必需) - `DATABASE_URL` — PostgreSQL 连接串(必需)
@@ -171,13 +183,13 @@ OK
- `JWT_SECRET` — JWT 签名密钥 - `JWT_SECRET` — JWT 签名密钥
- `RUST_LOG` — 日志级别 - `RUST_LOG` — 日志级别
### 3. Docker 构建 ### 5. Docker 构建
- 各微服务 Dockerfile 的构建上下文为**项目根目录**`docker-compose.yml` 中使用 `context: ../..`)。 - 各微服务 Dockerfile 的构建上下文为**项目根目录**`docker-compose.yml` 中使用 `context: ../..`)。
- 构建采用多阶段builder + runtime基于 `rust:1.94.1-alpine3.23` 编译,最终运行在 `alpine:3.23`。 - 构建采用多阶段builder + runtime基于 `rust:1.94.1-alpine3.23` 编译,最终运行在 `alpine:3.23`。
- 共享代码更新时,需确保 `shared/` 目录在 Dockerfile 中被正确复制。 - 共享代码更新时,需确保 `shared/` 目录在 Dockerfile 中被正确复制。
### 4. 网关与路由 ### 6. 网关与路由
- Nginx 监听 80/443开发环境使用自签名证书。 - Nginx 监听 80/443开发环境使用自签名证书。
- 路由前缀约定: - 路由前缀约定:

View File

@@ -2,8 +2,8 @@
CREATE TABLE IF NOT EXISTS user_main ( CREATE TABLE IF NOT EXISTS user_main (
id UUID PRIMARY KEY, id UUID PRIMARY KEY,
deleted BOOLEAN NOT NULL DEFAULT FALSE, deleted BOOLEAN NOT NULL DEFAULT FALSE,
createdate TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP, createdate TIMESTAMP WITH TIME ZONE NOT NULL,
modifydate TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP modifydate TIMESTAMP WITH TIME ZONE NOT NULL
); );
-- 用户登录账号表 -- 用户登录账号表
@@ -12,8 +12,8 @@ CREATE TABLE IF NOT EXISTS user_login_account (
user_id UUID NOT NULL, user_id UUID NOT NULL,
account VARCHAR(100) NOT NULL, account VARCHAR(100) NOT NULL,
deleted BOOLEAN NOT NULL DEFAULT FALSE, deleted BOOLEAN NOT NULL DEFAULT FALSE,
createdate TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP, createdate TIMESTAMP WITH TIME ZONE NOT NULL,
modifydate TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP, modifydate TIMESTAMP WITH TIME ZONE NOT NULL,
CONSTRAINT fk_user_login_account_user_main FOREIGN KEY (user_id) REFERENCES user_main(id) CONSTRAINT fk_user_login_account_user_main FOREIGN KEY (user_id) REFERENCES user_main(id)
); );
@@ -27,8 +27,8 @@ CREATE TABLE IF NOT EXISTS user_login_password (
user_id UUID NOT NULL, user_id UUID NOT NULL,
password VARCHAR(255) NOT NULL, password VARCHAR(255) NOT NULL,
deleted BOOLEAN NOT NULL DEFAULT FALSE, deleted BOOLEAN NOT NULL DEFAULT FALSE,
createdate TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP, createdate TIMESTAMP WITH TIME ZONE NOT NULL,
modifydate TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP, modifydate TIMESTAMP WITH TIME ZONE NOT NULL,
CONSTRAINT fk_user_login_password_user_main FOREIGN KEY (user_id) REFERENCES user_main(id) CONSTRAINT fk_user_login_password_user_main FOREIGN KEY (user_id) REFERENCES user_main(id)
); );
@@ -41,8 +41,8 @@ CREATE TABLE IF NOT EXISTS user_login_email (
user_id UUID NOT NULL, user_id UUID NOT NULL,
email VARCHAR(255) NOT NULL, email VARCHAR(255) NOT NULL,
deleted BOOLEAN NOT NULL DEFAULT FALSE, deleted BOOLEAN NOT NULL DEFAULT FALSE,
createdate TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP, createdate TIMESTAMP WITH TIME ZONE NOT NULL,
modifydate TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP, modifydate TIMESTAMP WITH TIME ZONE NOT NULL,
CONSTRAINT fk_user_login_email_user_main FOREIGN KEY (user_id) REFERENCES user_main(id) CONSTRAINT fk_user_login_email_user_main FOREIGN KEY (user_id) REFERENCES user_main(id)
); );

View File

@@ -10,6 +10,7 @@ use serde::{Deserialize, Serialize};
use sqlx::PgPool; use sqlx::PgPool;
use std::env; use std::env;
use std::sync::Arc; use std::sync::Arc;
use chrono::Utc;
use tracing::{info, warn}; use tracing::{info, warn};
use uuid::Uuid; use uuid::Uuid;
use validator::Validate; use validator::Validate;
@@ -149,12 +150,15 @@ async fn register_handler(
} }
}; };
let now = Utc::now();
let user_id = Uuid::now_v7(); let user_id = Uuid::now_v7();
if let Err(e) = sqlx::query( if let Err(e) = sqlx::query(
"INSERT INTO user_main (id) VALUES ($1)" "INSERT INTO user_main (id, createdate, modifydate) VALUES ($1, $2, $3)"
) )
.bind(user_id) .bind(user_id)
.bind(now)
.bind(now)
.execute(&mut *tx) .execute(&mut *tx)
.await .await
{ {
@@ -172,11 +176,13 @@ async fn register_handler(
let account_id = Uuid::now_v7(); let account_id = Uuid::now_v7();
if let Err(e) = sqlx::query( if let Err(e) = sqlx::query(
"INSERT INTO user_login_account (id, user_id, account) VALUES ($1, $2, $3)" "INSERT INTO user_login_account (id, user_id, account, createdate, modifydate) VALUES ($1, $2, $3, $4, $5)"
) )
.bind(account_id) .bind(account_id)
.bind(user_id) .bind(user_id)
.bind(&req.data.username) .bind(&req.data.username)
.bind(now)
.bind(now)
.execute(&mut *tx) .execute(&mut *tx)
.await .await
{ {
@@ -194,11 +200,13 @@ async fn register_handler(
let password_id = Uuid::now_v7(); let password_id = Uuid::now_v7();
if let Err(e) = sqlx::query( if let Err(e) = sqlx::query(
"INSERT INTO user_login_password (id, user_id, password) VALUES ($1, $2, $3)" "INSERT INTO user_login_password (id, user_id, password, createdate, modifydate) VALUES ($1, $2, $3, $4, $5)"
) )
.bind(password_id) .bind(password_id)
.bind(user_id) .bind(user_id)
.bind(&password_hash) .bind(&password_hash)
.bind(now)
.bind(now)
.execute(&mut *tx) .execute(&mut *tx)
.await .await
{ {

View File

@@ -10,6 +10,7 @@ use serde::{Deserialize, Serialize};
use sqlx::PgPool; use sqlx::PgPool;
use std::env; use std::env;
use std::sync::Arc; use std::sync::Arc;
use chrono::Utc;
use tracing::{info, warn}; use tracing::{info, warn};
use uuid::Uuid; use uuid::Uuid;
use validator::Validate; use validator::Validate;
@@ -149,12 +150,15 @@ async fn register_handler(
} }
}; };
let now = Utc::now();
let user_id = Uuid::now_v7(); let user_id = Uuid::now_v7();
if let Err(e) = sqlx::query( if let Err(e) = sqlx::query(
"INSERT INTO user_main (id) VALUES ($1)" "INSERT INTO user_main (id, createdate, modifydate) VALUES ($1, $2, $3)"
) )
.bind(user_id) .bind(user_id)
.bind(now)
.bind(now)
.execute(&mut *tx) .execute(&mut *tx)
.await .await
{ {
@@ -172,11 +176,13 @@ async fn register_handler(
let email_id = Uuid::now_v7(); let email_id = Uuid::now_v7();
if let Err(e) = sqlx::query( if let Err(e) = sqlx::query(
"INSERT INTO user_login_email (id, user_id, email) VALUES ($1, $2, $3)" "INSERT INTO user_login_email (id, user_id, email, createdate, modifydate) VALUES ($1, $2, $3, $4, $5)"
) )
.bind(email_id) .bind(email_id)
.bind(user_id) .bind(user_id)
.bind(&req.data.email) .bind(&req.data.email)
.bind(now)
.bind(now)
.execute(&mut *tx) .execute(&mut *tx)
.await .await
{ {
@@ -194,11 +200,13 @@ async fn register_handler(
let password_id = Uuid::now_v7(); let password_id = Uuid::now_v7();
if let Err(e) = sqlx::query( if let Err(e) = sqlx::query(
"INSERT INTO user_login_password (id, user_id, password) VALUES ($1, $2, $3)" "INSERT INTO user_login_password (id, user_id, password, createdate, modifydate) VALUES ($1, $2, $3, $4, $5)"
) )
.bind(password_id) .bind(password_id)
.bind(user_id) .bind(user_id)
.bind(&password_hash) .bind(&password_hash)
.bind(now)
.bind(now)
.execute(&mut *tx) .execute(&mut *tx)
.await .await
{ {