MCPcopy Create free account
hub / github.com/dbcli/mycli / SchemaPrefetcher

Class SchemaPrefetcher

mycli/schema_prefetcher.py:51–236  ·  view source on GitHub ↗

Run schema prefetch work on a dedicated background thread.

Source from the content-addressed store, hash-verified

49
50
51class SchemaPrefetcher:
52 """Run schema prefetch work on a dedicated background thread."""
53
54 def __init__(self, mycli: 'MyCli') -> None:
55 self.mycli = mycli
56 self._thread: threading.Thread | None = None
57 self._cancel = threading.Event()
58 self._loaded: set[str] = set()
59
60 def is_prefetching(self) -> bool:
61 return bool(self._thread and self._thread.is_alive())
62
63 def clear_loaded(self) -> None:
64 """Forget which schemas have been prefetched (used on reset)."""
65 self._loaded.clear()
66
67 def stop(self, timeout: float = 2.0) -> None:
68 """Signal the background thread to stop and wait briefly for it."""
69 if self._thread and self._thread.is_alive():
70 self._cancel.set()
71 self._thread.join(timeout=timeout)
72 self._cancel = threading.Event()
73 self._thread = None
74
75 def start_configured(self) -> None:
76 """Start prefetching based on the user's prefetch settings."""
77 mode = getattr(self.mycli, 'prefetch_schemas_mode', PrefetchMode.ALWAYS.value)
78 schema_list = getattr(self.mycli, 'prefetch_schemas_list', [])
79 parsed = parse_prefetch_config(mode, schema_list)
80 if parsed is not None and not parsed:
81 # ``never`` or ``listed`` with an empty list — nothing to do.
82 return
83 self._start(parsed)
84
85 def prefetch_schema_now(self, schema: str) -> None:
86 """Fetch *schema* immediately on a background thread.
87
88 Used when a user manually switches to a schema. The method
89 returns quickly; the actual work happens in the new thread.
90 """
91 if not schema:
92 return
93 # Avoid double-fetching while a full-prefetch pass is running.
94 self.stop()
95 self._start([schema])
96
97 def _start(self, schemas: Iterable[str] | None) -> None:
98 """Spawn the background worker.
99
100 ``schemas=None`` defers resolution to the worker, which lists
101 every database via its own dedicated connection — the main
102 thread's ``sqlexecute`` must not be used here since the worker
103 would race with the REPL.
104 """
105 self.stop()
106 queue: list[str] | None = None if schemas is None else list(schemas)
107 self._cancel = threading.Event()
108 self._thread = threading.Thread(

Calls

no outgoing calls