Skip to content

Refactor: stat service deprecated stats - #9658

Merged
RC-CHN merged 2 commits into
AstrBotDevs:masterfrom
RC-CHN:refactor/stat-service-deprecated-stats
Aug 13, 2026
Merged

Refactor: stat service deprecated stats#9658
RC-CHN merged 2 commits into
AstrBotDevs:masterfrom
RC-CHN:refactor/stat-service-deprecated-stats

Conversation

@RC-CHN

@RC-CHN RC-CHN commented Aug 13, 2026

Copy link
Copy Markdown
Member

Modifications / 改动点

  • StatService.get_stat (the endpoint behind the dashboard stats page) still relied on three methods that were deprecated in v4.0.0: get_base_stats, get_grouped_base_stats, and get_total_message_count. Every stats page load emitted a burst of DeprecationWarnings — one per method call plus one per row from instantiating the deprecated po.Platform/Stats dataclasses — and each call spawned a throwaway thread running asyncio.run to bridge sync to async.

  • This PR migrates get_stat to query PlatformStat directly while keeping the response shape byte-identical.

  • This is NOT a breaking change. / 这不是一个破坏性变更。

Screenshots or Test Results / 运行截图或测试结果


Checklist / 检查清单

  • 😊 If there are new features added in the PR, I have discussed it with the authors through issues/emails, etc.
    / 如果 PR 中有新加入的功能,已经通过 Issue / 邮件等方式和作者讨论过。

  • 👀 My changes have been well-tested, and "Verification Steps" and "Screenshots" have been provided above.
    / 我的更改经过了良好的测试,并已在上方提供了“验证步骤”和“运行截图”

  • 🤓 I have ensured that no new dependencies are introduced, OR if new dependencies are introduced, they have been added to the appropriate locations in requirements.txt and pyproject.toml.
    / 我确保没有引入新依赖库,或者引入了新依赖库的同时将其添加到 requirements.txtpyproject.toml 文件相应位置。

  • 😮 My changes do not introduce malicious code.
    / 我的更改没有引入恶意代码。

Summary by Sourcery

Refactor dashboard stat retrieval to use PlatformStat directly while preserving the existing response schema for the stats endpoint.

Enhancements:

  • Simplify StatService.get_stat to compute per-platform aggregates, global totals, and hourly time-series directly from PlatformStat rows instead of deprecated helper methods.

Tests:

  • Add unit tests for StatService.get_stat to verify aggregation logic, window behavior, and response structure for non-empty and empty stat windows.

RC-CHN added 2 commits August 13, 2026 14:40
Rewrite StatService.get_stat to query PlatformStat directly via
db_helper.get_db(), following the existing get_provider_token_stats
pattern in the same file, instead of the deprecated
get_base_stats/get_grouped_base_stats/get_total_message_count.

- Windowed rows are fetched once with an explicit ORDER BY timestamp
  (the old get_base_stats relied on insertion order)
- Per-platform sums and hourly time-series buckets are aggregated in
  Python; total message count uses func.coalesce(func.sum(...), 0)
- Response shape is unchanged: platform entries keep the
  {name, count, timestamp} keys, now built as plain dicts so no
  deprecated po.Platform/Stats classes are instantiated
- Verified semantically identical against the old methods with an A/B
  comparison over a seeded database (time series, per-platform sums,
  total count, and empty-window case all match)
The existing test_get_stat route test only asserts the HTTP status and
the presence of the platform key, so an aggregation regression would
pass unnoticed. Add focused unit tests that seed PlatformStat rows and
assert the windowed per-platform sums, the global message total, the
hourly time-series bucket shape, the response key set, and the
empty-window behavior.
@dosubot dosubot Bot added size:M This PR changes 30-99 lines, ignoring generated files. area:webui The bug / feature is about webui(dashboard) of astrbot. labels Aug 13, 2026

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 1 issue

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location path="tests/unit/test_stat_service.py" line_range="19-28" />
<code_context>
+    }
+
+
+@pytest.mark.asyncio
+async def test_get_stat_empty_window(temp_db):
+    """A window with no rows yields empty platform stats but keeps the total."""
+    old_ts = datetime.now() - timedelta(hours=2)
</code_context>
<issue_to_address>
**suggestion (testing):** Add a test for a completely empty database window to cover the `total_messages == 0` path.

`test_get_stat_empty_window` only covers a window with no in-range rows while still having an out-of-window row. We’re missing coverage for the case where `PlatformStat` has no rows at all, to exercise `func.coalesce(sum(...), 0)` and verify `message_count` is `0` with an all-zero series. Please add a small test with an entirely empty DB (no inserts) to confirm this default behavior.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment on lines +19 to +28
@pytest.mark.asyncio
async def test_get_stat_aggregates_platform_stats(temp_db):
"""Seeded rows must aggregate into windowed platform sums and a global total."""
now = datetime.now()
seed = [
("aiocqhttp", 3, now - timedelta(hours=1)),
("aiocqhttp", 5, now - timedelta(hours=1, minutes=30)),
("qqofficial", 2, now - timedelta(hours=2)),
("webchat", 7, now - timedelta(minutes=10)),
# Outside the 24h window: counted in the total but not in window stats.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (testing): Add a test for a completely empty database window to cover the total_messages == 0 path.

test_get_stat_empty_window only covers a window with no in-range rows while still having an out-of-window row. We’re missing coverage for the case where PlatformStat has no rows at all, to exercise func.coalesce(sum(...), 0) and verify message_count is 0 with an all-zero series. Please add a small test with an entirely empty DB (no inserts) to confirm this default behavior.

@RC-CHN
RC-CHN merged commit 604392d into AstrBotDevs:master Aug 13, 2026
21 checks passed
@RC-CHN
RC-CHN deleted the refactor/stat-service-deprecated-stats branch August 13, 2026 07:10
BegoniaHe pushed a commit to Xero-Team/AstrBot that referenced this pull request Aug 14, 2026
Upstream-Commit: 604392d
Upstream-Author: Ruochen Pan <badbatch0x01@gmail.com>
Upstream-PR: AstrBotDevs#9658
Sync-Disposition: adapt
Fork-Adaptation: Preserve the fork StatisticsStore service boundary while querying PlatformStat totals directly for the all-history message count.
Tested: uv run pytest tests/unit/test_stat_service.py -q
LIghtJUNction added a commit that referenced this pull request Aug 14, 2026
* chore: update readme

* feat: support PowerShell 7 for Windows local shell (#9622)

* feat(config): add Windows PowerShell version option

* feat(computer): honor Windows PowerShell version in local runtime

* fix(computer): correct stale shell comment for configurable PowerShell

* refactor(computer): inline windows shell resolution per AGENTS.md

* test(computer): assert windows_shell in exec_managed call

* test: make shell tests cross-platform

Co-authored-by: Donoym <prober13c14@gmail.com>

* refactor(computer): auto-detect Windows shell instead of config

* fix(computer): drop stale cmd.exe references after shell auto-detect

* style: apply ruff format and import order

* Update astrbot/core/astr_main_agent.py

Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>

---------

Co-authored-by: Donoym <prober13c14@gmail.com>
Co-authored-by: Soulter <37870767+Soulter@users.noreply.github.com>
Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>

* feat: add download-count sorting to plugin marketplace (#9570)

* feat: 插件市场支持按下载量排序

为插件市场现有的前端本地排序补充下载量选项,复用已规范化的 download_count,不改变默认推荐顺序、后端接口和 OpenAPI。

新增稳定且不修改输入的下载量排序工具:支持升降序、未知值双向置底、非法值兜底及相同值原始顺序保留;接入市场排序控件并补齐中、英、俄三语文案。

新增 9 项专项单元测试,覆盖正常排序、零值、缺失与非法值、负数、数字字符串、小数、稳定性和输入不可变。验证通过 45 项 Dashboard Node 测试、额外性质检查、三语 JSON 校验、Vue 类型检查和生产构建。

* Delete dashboard/tests/marketPluginSort.test.mjs

* refactor: 内联插件市场下载量排序

删除独立的市场下载量排序工具,将下载量比较逻辑直接放在现有市场排序分支。

缺失下载量使用默认值 0,保持前端本地排序与现有排序行为一致。

验证:vue-tsc --noEmit;pnpm run build;node --test dashboard/tests/*.test.mjs;git diff --check。

---------

Co-authored-by: C₂₂H₂₅NO₆ <Sisyphbaous-DT-Project@users.noreply.github.com>
Co-authored-by: Soulter <37870767+Soulter@users.noreply.github.com>

* fix: improve dark theme text contrast (#9643)

* fix: propagate QQ media upload failures (#9644)

* feat(qqofficial): add chunked file uploads (#9646)

Add a dedicated chunked uploader for large local QQ Official media. Keep C2C and group endpoints explicit, support server-provided part index bases, and retry transient upload operations.

Co-authored-by: Fuyan Yuan <33221728+TheRainstorm@users.noreply.github.com>

* fix(kb): support UUID fallback in get_kb_by_name and warn on missing KBs (#9636)

Fixes #9529.

When kb_names contains UUIDs instead of names, get_kb_by_name() would
return None and check_all_kb() would silently skip retrieval with only
a DEBUG-level log.

Modifications:
- get_kb_by_name() now falls back to UUID lookup when name match fails
- check_all_kb() distinguishes None (not found) from empty KBs and logs
  a WARNING with the count of missing KBs
- Add regression tests covering UUID lookup, name preference, and logging

* fix: prevent SharedPreferences deadlocks (#9649)

* fix: avoid blocking shared preference access

* docs: clarify shared preference cache roles

* docs: explain shared preference cache purpose

* docs: link cache rationale to pull request

* chore: bump version to 4.27.3 (#9650)

* chore: bump version to 4.27.3

* Update changelog for version 4.27.3

Updated changelog for version 4.27.3 with new features, maintenance updates, and bug fixes.

* Refactor: stat service deprecated stats (#9658)

* refactor(dashboard): migrate get_stat off deprecated stats methods

Rewrite StatService.get_stat to query PlatformStat directly via
db_helper.get_db(), following the existing get_provider_token_stats
pattern in the same file, instead of the deprecated
get_base_stats/get_grouped_base_stats/get_total_message_count.

- Windowed rows are fetched once with an explicit ORDER BY timestamp
  (the old get_base_stats relied on insertion order)
- Per-platform sums and hourly time-series buckets are aggregated in
  Python; total message count uses func.coalesce(func.sum(...), 0)
- Response shape is unchanged: platform entries keep the
  {name, count, timestamp} keys, now built as plain dicts so no
  deprecated po.Platform/Stats classes are instantiated
- Verified semantically identical against the old methods with an A/B
  comparison over a seeded database (time series, per-platform sums,
  total count, and empty-window case all match)

* test(dashboard): cover StatService.get_stat aggregation semantics

The existing test_get_stat route test only asserts the HTTP status and
the presence of the platform key, so an aggregation regression would
pass unnoticed. Add focused unit tests that seed PlatformStat rows and
assert the windowed per-platform sums, the global message total, the
hourly time-series bucket shape, the response key set, and the
empty-window behavior.

* feat(provider): add SSYCloud chat completion provider (#9659)

* fix: include JSON cards in group context (#9655)

* fix: include JSON cards in group context

* fix: allow JSON cards to trigger active replies

* docs: add ShengSuanYun provider guide

* fix: detect audio format from file content (#9612)

* feat: log effective Windows local runtime shell (#9648)

* feat: log effective Windows local runtime shell

* chore: remove Windows shell logging tests

---------

Co-authored-by: Soulter <905617992@qq.com>

* refactor(misskey): migrate off deprecated visibility resolver alias (#9674)

---------

Co-authored-by: Soulter <905617992@qq.com>
Co-authored-by: Wei Chengqian <wcqqq1214@gmail.com>
Co-authored-by: Donoym <prober13c14@gmail.com>
Co-authored-by: Soulter <37870767+Soulter@users.noreply.github.com>
Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>
Co-authored-by: C₂₂H₂₅NO₆ <96930391+Sisyphbaous-DT-Project@users.noreply.github.com>
Co-authored-by: C₂₂H₂₅NO₆ <Sisyphbaous-DT-Project@users.noreply.github.com>
Co-authored-by: Fuyan Yuan <33221728+TheRainstorm@users.noreply.github.com>
Co-authored-by: lxfight <1686540385@qq.com>
Co-authored-by: Ruochen Pan <badbatch0x01@gmail.com>
Co-authored-by: xxshu26 <15197757832@163.com>
Co-authored-by: PeiPei233 <49641967+PeiPei233@users.noreply.github.com>
Co-authored-by: xiaoxuan010 <2592053474@qq.com>
Co-authored-by: C10H14N2O5 <100066858+C10H14N2O5@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:webui The bug / feature is about webui(dashboard) of astrbot. size:M This PR changes 30-99 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant