Skip to content

Commit d1d8101

Browse files
Harden export state parsing and listing cache fast path
1 parent 196f2b6 commit d1d8101

3 files changed

Lines changed: 27 additions & 6 deletions

File tree

scripts/export.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,8 @@ def _read_last_export_ms(state_path: str, since: Literal["all", "last"]) -> int:
174174
try:
175175
with open(state_path, "r", encoding="utf-8") as f:
176176
st = json.load(f)
177+
if not isinstance(st, dict):
178+
return 0
177179
ts = st.get("lastExportTime")
178180
if ts:
179181
return to_epoch_ms(ts)

services/export_engine.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ def _collect_ide_export_entries(
216216
composer_id = row["key"].split(":")[1]
217217
try:
218218
cd = json.loads(row["value"])
219-
except (json.JSONDecodeError, ValueError) as parse_err:
219+
except (json.JSONDecodeError, TypeError, ValueError) as parse_err:
220220
_logger.debug(
221221
"Skipping corrupt composerData row %s: %s",
222222
composer_id,
@@ -370,7 +370,8 @@ def _collect_cli_export_entries(
370370
for session in cp["sessions"]:
371371
meta = session.get("meta", {})
372372
session_id = session["session_id"]
373-
created_ms: int = meta.get("createdAt") or int(
373+
created_raw = meta.get("createdAt")
374+
created_ms = to_epoch_ms(created_raw) if created_raw else int(
374375
datetime.now().timestamp() * 1000,
375376
)
376377
session_name = meta.get("name") or f"Session {session_id[:8]}"

services/workspace_listing.py

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,15 @@
2121
from models import Bubble, ParseWarningCollector
2222
from services.export_engine import WorkspaceOrchestration, prepare_workspace_orchestration
2323
from services.summary_cache import (
24+
fingerprint_workspace_storage,
2425
get_cached_projects,
2526
nocache_enabled,
2627
set_cached_projects,
2728
)
2829
from services.workspace_db import (
2930
COMPOSER_ROWS_WITH_HEADERS_SQL,
31+
collect_workspace_entries,
32+
global_storage_db_path,
3033
load_project_layouts_for_composer,
3134
load_project_layouts_map,
3235
open_global_db,
@@ -91,14 +94,29 @@ def list_workspace_projects(
9194
:meth:`models.ParseWarningCollector.to_api_list`; empty when no skips.
9295
"""
9396
effective_nocache = nocache_enabled(request_nocache=nocache)
94-
orch = prepare_workspace_orchestration(
95-
workspace_path, rules, nocache=effective_nocache,
96-
)
97+
workspace_entries: list[dict[str, Any]] | None = None
9798
if not effective_nocache:
98-
cached = get_cached_projects(orch.fingerprint)
99+
workspace_entries = collect_workspace_entries(workspace_path)
100+
gdb = global_storage_db_path(workspace_path)
101+
cli_path = get_cli_chats_path()
102+
fingerprint = fingerprint_workspace_storage(
103+
workspace_path,
104+
workspace_entries,
105+
global_db_path=gdb if os.path.isfile(gdb) else None,
106+
rules=rules,
107+
cli_chats_path=cli_path if os.path.isdir(cli_path) else None,
108+
)
109+
cached = get_cached_projects(fingerprint)
99110
if cached is not None:
100111
return cached
101112

113+
orch = prepare_workspace_orchestration(
114+
workspace_path,
115+
rules,
116+
nocache=effective_nocache,
117+
workspace_entries=workspace_entries,
118+
)
119+
102120
projects, warnings = _build_workspace_projects_uncached(
103121
workspace_path, rules, orch,
104122
)

0 commit comments

Comments
 (0)