Skip to content

Commit 55c4531

Browse files
Fix review follow-ups for search window order and shared tab parsing
1 parent bc5e6ea commit 55c4531

5 files changed

Lines changed: 17 additions & 48 deletions

File tree

services/search.py

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -502,6 +502,8 @@ def _search_global_storage_via_index(
502502
if since_ms is not None and not composers_in_window:
503503
return results
504504

505+
search_pool = composers_in_window
506+
505507
window_ids = set(composers_in_window.keys()) if since_ms is not None else None
506508
bubble_texts_by_composer = query_composer_bubble_hits(
507509
query_lower,
@@ -513,19 +515,13 @@ def _search_global_storage_via_index(
513515
for row in query_composer_title_hits(query_lower, since_ms=since_ms):
514516
candidate_ids.add(row["composer_id"])
515517

516-
search_pool = composers_in_window if since_ms is not None else query_composer_rows_in_window(None)
517518
for composer_id, row in search_pool.items():
518519
raw_lower = (row["raw_json"] or "").lower()
519520
if query_lower in raw_lower:
520521
candidate_ids.add(composer_id)
521522

522523
for composer_id in candidate_ids:
523-
composer_row: sqlite3.Row | None = (
524-
composers_in_window.get(composer_id) if since_ms is not None
525-
else search_pool.get(composer_id)
526-
)
527-
if composer_row is None:
528-
composer_row = query_composer_rows_in_window(None).get(composer_id)
524+
composer_row = search_pool.get(composer_id)
529525
if composer_row is None:
530526
continue
531527

@@ -888,6 +884,10 @@ def search_legacy_workspaces(
888884
ct = tab.get("chatTitle") or ""
889885
tab_id = str(tab.get("tabId") or "")
890886

887+
tab_ts = to_epoch_ms(tab.get("lastSendTime")) or _UNKNOWN_SEARCH_TIMESTAMP
888+
if not _timestamp_in_search_window(tab_ts, since_ms):
889+
continue
890+
891891
tab_model_names: list[str] | None = None
892892
tab_meta = tab.get("metadata")
893893
if isinstance(tab_meta, dict):
@@ -921,10 +921,6 @@ def search_legacy_workspaces(
921921
if not has_match:
922922
continue
923923

924-
tab_ts = to_epoch_ms(tab.get("lastSendTime")) or _UNKNOWN_SEARCH_TIMESTAMP
925-
if not _timestamp_in_search_window(tab_ts, since_ms):
926-
continue
927-
928924
results.append({
929925
"workspaceId": name,
930926
"workspaceFolder": workspace_name,

services/search_index.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343

4444
__all__ = [
4545
"SEARCH_INDEX_FILE",
46+
"SEARCH_INDEX_POINTER_FILE",
4647
"ensure_search_index",
4748
"index_is_usable",
4849
"index_search_enabled",

services/workspace_composer_scan.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,13 @@ def parse_composer_data_row(
2929
Returns ``None`` for null/placeholder payloads (e.g. ``empty-state-draft``)
3030
without emitting decode warnings. Logs and records skips for malformed JSON.
3131
"""
32+
if not row_key.startswith("composerData:"):
33+
return None
3234
if raw_value is None:
3335
return None
3436
if not isinstance(raw_value, (str, bytes, bytearray)):
3537
parse_warnings.record_composer_skipped()
3638
return None
37-
if not row_key.startswith("composerData:"):
38-
return None
3939
composer_id = row_key.split(":", 1)[1]
4040
if not composer_id:
4141
parse_warnings.record_composer_skipped()

services/workspace_tabs.py

Lines changed: 6 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -741,13 +741,7 @@ def assemble_workspace_tabs(
741741
project_layouts_map[chat_id].append(layout["rootPath"])
742742

743743
# Get composer data entries with conversations
744-
composer_rows = safe_fetchall(
745-
global_db,
746-
"SELECT key, value FROM cursorDiskKV WHERE key LIKE 'composerData:%'"
747-
" AND value IS NOT NULL"
748-
" AND value LIKE '%fullConversationHeadersOnly%'"
749-
" AND value NOT LIKE '%fullConversationHeadersOnly\":[]%'",
750-
)
744+
composer_rows = safe_fetchall(global_db, COMPOSER_ROWS_WITH_HEADERS_SQL)
751745

752746
invalid_workspace_aliases = infer_invalid_workspace_aliases(
753747
composer_rows=composer_rows,
@@ -761,34 +755,12 @@ def assemble_workspace_tabs(
761755
)
762756

763757
for row in composer_rows:
764-
composer_id = row["key"].split(":")[1]
765-
try:
766-
parsed = json.loads(row["value"])
767-
except (json.JSONDecodeError, TypeError, ValueError) as e:
768-
payload_len, payload_fp = _kv_payload_log_meta(row["value"])
769-
_logger.warning(
770-
"Failed to decode Composer from composerData:%s: %s (key=%s, payload_len=%d, payload_sha256=%s)",
771-
composer_id,
772-
e,
773-
row["key"],
774-
payload_len,
775-
payload_fp,
776-
)
777-
parse_warnings.record_composer_skipped()
778-
continue
779-
try:
780-
composer = Composer.from_dict(parsed, composer_id=composer_id)
781-
except SchemaError as e:
782-
# Drift skipped + logged so the two primary conversation
783-
# paths (list_workspaces + get_workspace_tabs) agree on what
784-
# counts as a valid composer.
785-
_logger.warning(
786-
"Failed to parse Composer from composerData:%s: %s",
787-
composer_id,
788-
e,
789-
)
790-
parse_warnings.record_composer_skipped()
758+
composer = parse_composer_data_row(
759+
row["key"], row["value"], parse_warnings=parse_warnings,
760+
)
761+
if composer is None:
791762
continue
763+
composer_id = composer.composer_id
792764
try:
793765
# Determine project
794766
pid = determine_project_for_conversation(

tests/test_parse_failure_logging.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ def test_workspace_tabs_logs_composer_json_decode_failure(self) -> None:
156156
("composerData:cmp-json", bad_composer_value),
157157
)
158158
conn.commit()
159-
with self.assertLogs("services.workspace_tabs", level="WARNING") as cm:
159+
with self.assertLogs("services.workspace_composer_scan", level="WARNING") as cm:
160160
with app.test_request_context("/api/workspaces/global/tabs"):
161161
_payload, _status = assemble_workspace_tabs("global", ws_root, rules=[])
162162

0 commit comments

Comments
 (0)