65a7b1226f
style: 全项目格式规范化(cargo fmt)+ Docker daemon 断连容错
...
- 全项目 .rs 统一 cargo fmt 排版(换行/缩进/参数分行/导入排序)
- infra/docker: DOCKER_CLIENT 连接失败不 panic,降级返回 None
(博客不依赖 Docker,panic=abort 下会导致整个进程崩溃)
- infra/mod: 去除多余空行
- database/mod: 模块声明按字母序重新排序
2026-07-15 17:22:06 +08:00
8da678b3b4
refactor(cache): 抽取 invalidate_post_metadata() 封装 4 行失效组合
...
文章写操作后总要一起失效 lists/tags/stats/search 四项元数据缓存。
新增 invalidate_post_metadata() 封装这个固定组合,替换 create/delete/
update/trash 中的 8 处重复 4 行序列。
保留定向失效(invalidate_post_by_slug / invalidate_tag_posts_for)
和批量回退路径(invalidate_all_post_caches + invalidate_search_results)
的显式调用——它们是按实际涉及数据细粒度控制的,不应被封装吞掉。
2026-07-14 14:44:00 +08:00
9c3f2242ba
feat(stats): add trash count to PostStats for posts page badge
...
为合并回收站到 /admin/posts 的 tab 设计铺路:PostStats 新增 trash 字段,
统计 deleted_at IS NOT NULL 的文章数,供文章列表页「回收站」tab 角标使用。
- stats.rs: 条件聚合查询增加 trash 列,server/非 server 构造同步补字段
- models/post.rs: PostStats 加 pub trash: i64
- cache.rs: post_stats_cache_roundtrip 测试 fixture 补 trash 字段
2026-07-08 16:40:32 +08:00
c4c490b881
feat(admin): add server status tab (sysinfo host metrics + cache hit rate)
...
新增 sysinfo 依赖(optional+server),sysinfo_sampler 后台采样任务
(SYSINFO_SAMPLE_SECS 可配,默认 0.5s)周期刷新 CPU/内存/磁盘/load 到 RwLock
快照,get_server_status 只读快照零成本。cache.rs 给 9 个缓存加 AtomicU64
hit/miss 计数 + cache_stats() 聚合命中率。
前端 ServerStatusTab:应用内指标(运行时间/连接池/会话/CPU/内存/磁盘/load)+
缓存命中率表 + 刷新按钮 + 自动刷新开关(500ms/1s/2s/5s/手动,默认手动)。
2026-06-29 18:45:02 +08:00
373498870a
style: apply cargo fmt to workspace
CI / check (push) Failing after 5m35s
CI / build (push) Has been skipped
2026-06-29 13:47:40 +08:00
53bfb1b7c0
feat(session): invalidate all sessions on role/status change via generation
...
users 表加 session_generation 列。get_user_by_token 缓存命中后回查 DB
generation,不匹配则逐出缓存并视为未登录,消除降级/封禁用户的权限残留
窗口(H2)。新增 invalidate_user_sessions 用于 bump generation,当前仓库
无运行时角色变更入口,作为未来用户管理功能的基础设施预留。
- 迁移 012:ADD COLUMN IF NOT EXISTS session_generation INT DEFAULT 0
- User/SessionUser 同步加字段,From<User> 如实传递
- 缓存校验走主键查询,亚毫秒级
2026-06-18 13:26:09 +08:00
79cb809010
perf(posts): add optional pagination to get_posts_by_tag, fix total count
...
- get_posts_by_tag 现接受 page/per_page 可选参数;两者均 None 时返回全部
(上限 200,用于无翻页 UI 的标签详情页),均提供时走标准分页。
- 修正 total:不再用 posts.len(),改为真实 COUNT(*),即使被 LIMIT 截断
也返回完整计数。
- 新增 CacheKey::PostsByTagPage 分页缓存键,与不分页键 PostsByTag 共存。
- 前端 tags.rs 传 (None, None) 保持原全部展示行为。
2026-06-18 11:14:56 +08:00
411e565465
docs(cache,search): update module and function comments
2026-06-18 09:55:45 +08:00
518b4e5d64
refactor(auth): store SessionUser instead of full User in session cache
2026-06-18 09:55:00 +08:00
c40a771989
feat(search): cache search results with short TTL
2026-06-17 17:20:54 +08:00
1d216faa2f
feat(auth): add in-memory session cache
2026-06-17 17:20:47 +08:00
7bd02d0ea9
perf(cache): run tag post invalidations concurrently
2026-06-17 16:59:29 +08:00
c528936abb
feat(cache): add invalidate_tag_posts_for helper
2026-06-17 16:37:20 +08:00
170c021b37
feat(cache): add PostListItem DTO and use it in list/tag/search caches
2026-06-17 15:51:19 +08:00
d1c9cea683
refactor(cache): remove unused per-post comment count cache
2026-06-17 11:52:57 +08:00
2caca3a48d
fix(dead_code): 清理假阳性与真死代码
...
CI / build (push) Has been cancelled
CI / check (push) Has been cancelled
- settings.rs: retention 常量与 clamp_retention 仅服务端使用,加 #[cfg(feature = "server")]
- comment.rs: 删除未使用的 Comment 结构体
- cache.rs: 删除未使用的 invalidate_all_comment_caches 及其测试
验证: cargo check (server/wasm), cargo test (311 passed), dx check, cargo clippy
2026-06-16 17:48:47 +08:00
054d7450f7
feat(model): Post 新增 deleted_at 字段并用 try_get 兼容现有查询
2026-06-16 12:29:37 +08:00
2db652137d
docs(models, db, cache): 补充中文注释
2026-06-12 18:56:56 +08:00
041cdf4102
test(cache): mark cache tests serial to fix parallel flakiness
2026-06-12 17:40:15 +08:00
294d60afab
style: format rust code
CI / build (push) Has been cancelled
CI / check (push) Has been cancelled
2026-06-12 17:14:31 +08:00
04737300e6
feat(comments): add complete comment system with guest commenting, moderation, and admin UI
...
Implements a fully self-built comment system for the blog:
Data layer:
- comments table with BIGSERIAL PK, parent_id self-reference (ON DELETE SET NULL),
depth tracking (max 20), status workflow (pending/approved/spam/trash),
content hashing for dedup, GDPR consent tracking, IP/UA storage with auto-purge
- 5 partial indexes optimized for read patterns
- updated_at auto-trigger
API (9 Dioxus server functions):
- Public: get_comments, get_comment_count, create_comment
- Admin: get_pending_comments, get_pending_count, get_all_comments,
approve_comment (with ancestor auto-approval), spam_comment, trash_comment,
batch_update_comment_status
Security:
- Function-level rate limiting (1/sec, burst 5) via FullstackContext IP extraction
- Input validation (name, email, URL scheme, content length, consent)
- Parent chain validation (must be approved, same post)
- Strict comment Markdown renderer (headings→strong, no img/id/data URIs, nofollow links)
- Honeypot anti-spam field
- 5-minute dedup window via SHA-256 content hash
Frontend:
- CommentSection with SuspenseBoundary isolation
- Flat-list rendering with depth-based CSS indentation (responsive)
- Gravatar via cravatar.cn (server-computed, email never exposed)
- Inline reply forms (one-at-a-time via Signal)
- Admin action buttons (approve/spam/delete) visible per-comment
- CommentForm with privacy consent, Markdown hint, loading states
Admin:
- /admin/comments page with status tabs, batch operations, pagination
- Pending count badge on admin dashboard
Infrastructure:
- Shared get_current_admin_user moved from posts/helpers to auth module
- COMMENT_LIMITER rate limiter tier
- Moka caches (60s TTL for comments, 10s for pending count)
- IP/UA purge background task (daily, 90-day retention)
2026-06-11 12:34:26 +08:00
311ddbe204
perf(cache): cache COUNT(*) result separately to avoid redundant queries
...
- Add TotalPublishedPosts cache key for reusing total count across pages
- list_published_posts now checks total cache before running COUNT(*)
- Add note to get_posts_by_tag about total = posts.len() assumption
- Remove unused invalidate_total_published_posts helper
2026-06-10 14:44:53 +08:00
116f3281a4
feat: update post list cache to store total count
2026-06-10 13:59:41 +08:00
b7220c28ef
Fix WebpError trait impls missing #[cfg(feature = "server")]
2026-06-09 18:30:10 +08:00
263771e403
test(cache): fix invalidation test isolation
2026-06-09 17:24:14 +08:00
73b4d28135
test(cache): use unique key in roundtrip test to avoid parallelism conflict
2026-06-09 17:20:03 +08:00
3041535cf7
test(cache): add cache key and roundtrip tests
2026-06-09 17:18:39 +08:00
0b594ff719
refactor(cache): use CacheKey directly, remove unnecessary async
2026-06-09 16:56:41 +08:00
62e2045b35
feat: add cache module with moka-backed post/tag/stats caching
...
- Create src/cache.rs with CacheKey enum, moka cache instances,
getter/setter functions, and invalidation helpers.
- TTLs: post list 60s, tags 300s, single post 600s, stats 60s,
tag posts 120s.
- Register mod cache in src/main.rs.
- All cache internals gated behind #[cfg(feature = "server")]
2026-06-09 16:47:17 +08:00