Give both summaries a modified time, and the dashboard list a footprint
Home's "recently modified" order was a proxy — drafts first, then the version counter, then the name. Both summaries now carry `updated_at`, read as the mtime of the working copy: every write in the store commits immediately, so a file's mtime is its commit time, and `git log -1 -- <path>` costs ~990ms across this instance's 15 documents (it walks the history back to the last commit touching each one, so it is slowest for the stalest) against ~1.8ms for the stats. No cache needed. `DashboardSummary` also carries `footprint`: each widget as its type plus the placement a panel resolves, which is the whole of what the mosaic draws. That drops the document fetch per tile and with it the cap of eight, past which tiles showed a name and nothing else. Verified against this instance's 8 dashboards: the blocks are identical to what the old client-side derivation produced. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CL9zvnnvcp1mvA8o7impxk
This commit is contained in:
@@ -19,6 +19,8 @@ import logging
|
||||
import shutil
|
||||
import subprocess
|
||||
import threading
|
||||
from collections.abc import Iterable
|
||||
from datetime import UTC, datetime
|
||||
from pathlib import Path
|
||||
|
||||
from fluksio.flow.schemas import FlowDef
|
||||
@@ -84,6 +86,20 @@ class StaleVersion(ValueError):
|
||||
return f"Flow '{self.name}' has changed since you loaded it"
|
||||
|
||||
|
||||
def _updated_at(paths: Iterable[Path]) -> datetime | None:
|
||||
"""When the newest of these files was written, or ``None`` if none exist.
|
||||
|
||||
A file's mtime, not the commit that recorded it: every write here commits
|
||||
immediately, so the two are the same instant, and `git log -1 -- <path>`
|
||||
would walk the history back to the last commit touching that path — 130ms
|
||||
for a document nobody has edited in a week, against a `stat` for all of
|
||||
them. Slowest for exactly the stalest documents is the wrong shape for a
|
||||
list endpoint.
|
||||
"""
|
||||
stamps = [path.stat().st_mtime for path in paths if path.exists()]
|
||||
return datetime.fromtimestamp(max(stamps), UTC) if stamps else None
|
||||
|
||||
|
||||
def _same_content(left: FlowDef, right: FlowDef) -> bool:
|
||||
"""Equal but for the version counter, which the server owns."""
|
||||
return left.model_copy(update={"version": 0}) == right.model_copy(
|
||||
@@ -386,6 +402,18 @@ class FlowStore:
|
||||
drafts = self._draft_nodes_dir(name)
|
||||
return drafts.exists() and any(drafts.glob("*.py"))
|
||||
|
||||
def updated_at(self, name: str) -> datetime | None:
|
||||
"""When this flow was last written — its document or any node's source.
|
||||
|
||||
Node code is saved without touching the flow document, so a flow whose
|
||||
last change was to a node body would otherwise look untouched.
|
||||
"""
|
||||
return _updated_at(
|
||||
[self._flow_file(name), self._draft_file(name)]
|
||||
+ list((self._flow_dir(name) / "nodes").glob("*.py"))
|
||||
+ list(self._draft_nodes_dir(name).glob("*.py"))
|
||||
)
|
||||
|
||||
def read_flow(self, name: str, draft: bool = False) -> FlowDef:
|
||||
"""The published flow, or with ``draft`` the working copy."""
|
||||
if draft:
|
||||
|
||||
Reference in New Issue
Block a user