vomebook commited on
Commit
0e23101
·
verified ·
1 Parent(s): a265c3e

Upload app.py

Browse files
Files changed (1) hide show
  1. app.py +29 -52
app.py CHANGED
@@ -65,6 +65,8 @@ search_response_cache: dict[tuple, tuple[float, object]] = {}
65
  search_response_cache_lock = threading.Lock()
66
  preview_text_cache: dict[str, str] = {}
67
  preview_text_cache_lock = threading.Lock()
 
 
68
  ZIP_TOKEN_TTL_SECONDS = 600
69
  ZIP_TOKEN_MAX_ENTRIES = 32
70
  zip_download_tokens: dict[str, tuple[float, list[str]]] = {}
@@ -330,7 +332,10 @@ class FulltextDatabases:
330
  tokens = query_tokens(query) if version == TOKENIZER_VERSION else query_terms(query)
331
  if version == TOKENIZER_VERSION:
332
  tokens = [*tokens, *literal_query_tokens(query)]
333
- if not tokens:
 
 
 
334
  rows = connection.execute(
335
  "SELECT rowid FROM content_fts WHERE instr(content, ?) > 0", (normalized_query,)
336
  )
@@ -403,21 +408,6 @@ class FulltextDatabases:
403
  return set()
404
  return matched or set()
405
 
406
- def verify_exact_content(self, connection: sqlite3.Connection, candidates: set[int], query: str) -> set[int]:
407
- if not candidates:
408
- return set()
409
- matched: set[int] = set()
410
- ordered = sorted(candidates)
411
- for offset in range(0, len(ordered), 500):
412
- batch = ordered[offset:offset + 500]
413
- placeholders = ",".join("?" for _ in batch)
414
- rows = connection.execute(
415
- f"SELECT rowid FROM content_fts WHERE rowid IN ({placeholders}) AND instr(content, ?) > 0",
416
- [*batch, query],
417
- )
418
- matched.update(int(row[0]) for row in rows)
419
- return matched
420
-
421
  def verify_wildcard_content(
422
  self,
423
  connection: sqlite3.Connection,
@@ -455,15 +445,6 @@ class FulltextDatabases:
455
  matched.update(int(row[0]) for row in rows)
456
  return matched
457
 
458
- def can_trust_exact_content(self, source: str, query: str) -> bool:
459
- with self.lock:
460
- return (
461
- self.tokenizer_versions.get(source) == TOKENIZER_VERSION
462
- and self.has_content_fts.get(source, False)
463
- and "*" not in query
464
- and "?" not in query
465
- )
466
-
467
  def summaries(self, doc_ids: list[str]) -> dict[str, str]:
468
  grouped = {}
469
  for doc_id in doc_ids:
@@ -986,25 +967,6 @@ def metadata_matches(q: str, exact: bool, search_paths: bool) -> set[int]:
986
  if all(term in records[idx][field] for term in terms)
987
  }
988
 
989
- def file_matches_exact_query(idx: int, query: str) -> bool:
990
- file_path = get_doc_storage_path(records[idx])
991
- if not file_path.exists():
992
- return False
993
- payload = file_path.read_bytes()
994
- if "*" not in query and "?" not in query and query.encode("utf-8") in payload:
995
- return True
996
- return matches_exact_query(payload.decode("utf-8", errors="ignore"), query)
997
-
998
- def verify_fulltext_matches(indices: set[int], query: str) -> set[int]:
999
- return set(cached_verified_fulltext_matches(tuple(sorted(indices)), query))
1000
-
1001
- @lru_cache(maxsize=32)
1002
- def cached_verified_fulltext_matches(indices: tuple[int, ...], query: str) -> frozenset[int]:
1003
- return frozenset(
1004
- idx for idx in indices
1005
- if file_matches_exact_query(idx, query)
1006
- )
1007
-
1008
  def search(q="", sources_filter=None, folders=None, min_size=None, max_size=None, page=1, page_size=100, sort="relevance", exact=False, search_paths=True, timings=None):
1009
  started = time.perf_counter()
1010
  q = q.strip()
@@ -1161,14 +1123,29 @@ def _cached_payload(cache, lock, key: tuple, builder, ttl: int, max_entries: int
1161
  if timings is not None:
1162
  timings["cache"] = "miss"
1163
  timings["cache_lookup"] = (time.perf_counter() - cache_started) * 1000
1164
- value = builder()
1165
- inserted_at = time.monotonic()
1166
- with lock:
1167
- cache[key] = (inserted_at, value)
1168
- while len(cache) > max_entries:
1169
- oldest_key = min(cache, key=lambda item: cache[item][0])
1170
- cache.pop(oldest_key, None)
1171
- return value
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1172
 
1173
  def cached_payload(key: tuple, builder, timings=None):
1174
  return _cached_payload(
 
65
  search_response_cache_lock = threading.Lock()
66
  preview_text_cache: dict[str, str] = {}
67
  preview_text_cache_lock = threading.Lock()
68
+ cache_key_locks: dict[tuple, threading.Lock] = {}
69
+ cache_key_locks_guard = threading.Lock()
70
  ZIP_TOKEN_TTL_SECONDS = 600
71
  ZIP_TOKEN_MAX_ENTRIES = 32
72
  zip_download_tokens: dict[str, tuple[float, list[str]]] = {}
 
332
  tokens = query_tokens(query) if version == TOKENIZER_VERSION else query_terms(query)
333
  if version == TOKENIZER_VERSION:
334
  tokens = [*tokens, *literal_query_tokens(query)]
335
+ # Short non-CJK literals (Latin substrings or punctuation-separated
336
+ # characters) are not provable from whole-token/unigram postings, so
337
+ # verify them against the normalized FTS content directly.
338
+ if not tokens or not re.fullmatch(r"[\u4e00-\u9fff\u3400-\u4dbf]+", normalized_query):
339
  rows = connection.execute(
340
  "SELECT rowid FROM content_fts WHERE instr(content, ?) > 0", (normalized_query,)
341
  )
 
408
  return set()
409
  return matched or set()
410
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
411
  def verify_wildcard_content(
412
  self,
413
  connection: sqlite3.Connection,
 
445
  matched.update(int(row[0]) for row in rows)
446
  return matched
447
 
 
 
 
 
 
 
 
 
 
448
  def summaries(self, doc_ids: list[str]) -> dict[str, str]:
449
  grouped = {}
450
  for doc_id in doc_ids:
 
967
  if all(term in records[idx][field] for term in terms)
968
  }
969
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
970
  def search(q="", sources_filter=None, folders=None, min_size=None, max_size=None, page=1, page_size=100, sort="relevance", exact=False, search_paths=True, timings=None):
971
  started = time.perf_counter()
972
  q = q.strip()
 
1123
  if timings is not None:
1124
  timings["cache"] = "miss"
1125
  timings["cache_lookup"] = (time.perf_counter() - cache_started) * 1000
1126
+ # Serialize identical cold keys so concurrent requests compute once instead
1127
+ # of stampeding the builder. The per-key lock is removed once it is no longer
1128
+ # contended so the map stays bounded to the number of in-flight keys.
1129
+ with cache_key_locks_guard:
1130
+ key_lock = cache_key_locks.setdefault(key, threading.Lock())
1131
+ try:
1132
+ with key_lock:
1133
+ with lock:
1134
+ cached = cache.get(key)
1135
+ if cached and now - cached[0] < ttl:
1136
+ return cached[1]
1137
+ value = builder()
1138
+ inserted_at = time.monotonic()
1139
+ with lock:
1140
+ cache[key] = (inserted_at, value)
1141
+ while len(cache) > max_entries:
1142
+ oldest_key = min(cache, key=lambda item: cache[item][0])
1143
+ cache.pop(oldest_key, None)
1144
+ return value
1145
+ finally:
1146
+ with cache_key_locks_guard:
1147
+ if cache_key_locks.get(key) is key_lock:
1148
+ cache_key_locks.pop(key, None)
1149
 
1150
  def cached_payload(key: tuple, builder, timings=None):
1151
  return _cached_payload(