Spaces:
Running
Running
docs: build-time deep dive notes (root cause, verified results, next bottleneck)
Browse filesCaptures the 2026-08-10 research: scoped-connection root cause + evidence,
what shipped and where (hf-test + MCP Space df44611, rollback 3d735c7),
verified timings (e2e 655s, MCP 9.2min), API research findings, and the
model-semantics phase (~5 min of sequential LLM batches) as the documented
next bottleneck with optimization options β deferred, no code changes.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- docs/build_time_deep_dive_2026_08_10.md +124 -0
- sprint_2026_04.md +3 -1
docs/build_time_deep_dive_2026_08_10.md
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Build-time deep dive β 2026-08-10
|
| 2 |
+
|
| 3 |
+
Research notes from the investigation into "why does the model take so long to
|
| 4 |
+
create." Companion to `docs/sre_slow_tml_import.md` (now RESOLVED) and
|
| 5 |
+
`docs/async_tml_import_handoff.md` (superseded as a fix, kept as the 504
|
| 6 |
+
safety net). Probe script: `tests/ts_table_create_deepdive.py`.
|
| 7 |
+
|
| 8 |
+
---
|
| 9 |
+
|
| 10 |
+
## 1. Root cause of the ~250s table imports
|
| 11 |
+
|
| 12 |
+
ThoughtSpot's logical-table TML import **scans all external-warehouse metadata
|
| 13 |
+
visible to the connection**. This is documented behavior for the v2 connection
|
| 14 |
+
APIs: when the database scope is omitted, *"all databases in the data warehouse
|
| 15 |
+
are accessible for metadata operations."* Our connection TML had no `database`
|
| 16 |
+
property, and the Snowflake role (`SE_ROLE`) can see **~507 databases** β so
|
| 17 |
+
every table create/join import paid a full metadata scan.
|
| 18 |
+
|
| 19 |
+
Measured 2026-08-10, same instance, same trivial 2-column table:
|
| 20 |
+
|
| 21 |
+
| Connection | Table import time |
|
| 22 |
+
|---|---:|
|
| 23 |
+
| Unscoped (app behavior before the fix) | **246β251s** |
|
| 24 |
+
| Scoped to `DEMOBUILD` (1,003 schemas / 6,084 tables of accumulated demo debris) | **33s** |
|
| 25 |
+
| Scoped to a fresh, tiny database | **0.7s** |
|
| 26 |
+
|
| 27 |
+
Key evidence that killed the earlier theories:
|
| 28 |
+
|
| 29 |
+
- **Prod (secloud) measured identical ~250s unscoped** β never sebe-specific,
|
| 30 |
+
never "instance load."
|
| 31 |
+
- Duplicate-name create errors return in 0.17s; model TML imports are
|
| 32 |
+
near-instant β parsing/validation/auth were never the cost.
|
| 33 |
+
- Flat ~250s per call regardless of payload (1 trivial table vs 4-table batch)
|
| 34 |
+
β a scan proportional to *visible metadata*, not to the payload.
|
| 35 |
+
- July's conclusion ("server-side, not reducible, raise with SRE") was wrong;
|
| 36 |
+
the async-import work from July remains useful only as the 504 safety net.
|
| 37 |
+
|
| 38 |
+
## 2. The fix that shipped (commit `21ee86d` + follow-ups)
|
| 39 |
+
|
| 40 |
+
1. **Scoped connections** β every demo connection now carries a
|
| 41 |
+
`database` property in its TML (`create_connection_tml` /
|
| 42 |
+
`create_connection_with_reconcile` require it; fail loudly without).
|
| 43 |
+
2. **Monthly-rotating demo database** β demos write to
|
| 44 |
+
`<SNOWFLAKE_DATABASE>_<YYYY_MM>` (e.g. `DEMOBUILD_2026_08`). Single source:
|
| 45 |
+
`get_demo_database()` in `snowflake_auth.py`, consumed by the session
|
| 46 |
+
params, `cdw_connector`, env injection, and the deploy path.
|
| 47 |
+
`ensure_demo_database()` creates it on connect. The admin setting
|
| 48 |
+
`SNOWFLAKE_DATABASE` stays the base name.
|
| 49 |
+
3. **Test harnesses** (`e2e_quality.py`, `settings_test.py`) resolve the
|
| 50 |
+
database from the model TML / `get_demo_database()` β no hardcoded
|
| 51 |
+
`DEMOBUILD` anywhere.
|
| 52 |
+
|
| 53 |
+
Operational notes:
|
| 54 |
+
|
| 55 |
+
- `get_demo_database()` is **memoized per process** β a long-running Space
|
| 56 |
+
crosses a month boundary only on restart/redeploy. Harmless (old DB keeps
|
| 57 |
+
working), just means rotation isn't mid-process.
|
| 58 |
+
- **Old-demo redeploys**: data written before 2026-08-10 lives in old
|
| 59 |
+
`DEMOBUILD`; re-running ThoughtSpot deployment for such a schema will fail
|
| 60 |
+
"schema not found" (deploy looks in the rotated DB). Already-deployed old
|
| 61 |
+
demos are untouched. If old-schema redeploys become a need, thread the
|
| 62 |
+
original database through instead.
|
| 63 |
+
- Old monthly DBs can be dropped as their demos expire β that, not cleanup
|
| 64 |
+
jobs, is the bloat story now.
|
| 65 |
+
|
| 66 |
+
## 3. Verified results (same day)
|
| 67 |
+
|
| 68 |
+
| Path | Before | After |
|
| 69 |
+
|---|---|---|
|
| 70 |
+
| App e2e, per test (Aug 7β10 pre-fix record) | 1,084β2,711s, 12/24 timeouts | **655s, Grade B, 0 timeouts** (TreeHouse) |
|
| 71 |
+
| MCP solo build (6 rehearsals on old deploy) | 16β20 min | **9.2 min, PASS, zero errors** (Tixr, owner=jack) |
|
| 72 |
+
|
| 73 |
+
Both paths verified writing to `DEMOBUILD_2026_08` with scoped connections.
|
| 74 |
+
MCP Space `thoughtspot-demoprep/mcp` deployed at `df44611`; rollback point is
|
| 75 |
+
`3d735c7` (`git push hf-mcp 3d735c7:main --force`).
|
| 76 |
+
|
| 77 |
+
## 4. Related API research (documented, for future reference)
|
| 78 |
+
|
| 79 |
+
- The v2 connection APIs also accept a **`databases` list** in
|
| 80 |
+
`data_warehouse_config` (persisted scope across multiple DBs) β an
|
| 81 |
+
alternative to the single `database` property if we ever need >1 DB visible.
|
| 82 |
+
- The UI's "edit connection β select tables" path is
|
| 83 |
+
`POST /api/rest/2.0/connections/{id}/update` with an `externalDatabases`
|
| 84 |
+
hierarchy β a table-registration path that skips TML entirely. Not needed
|
| 85 |
+
now (scoped TML import is <1s) but a known fallback.
|
| 86 |
+
- **No join/relationship API exists in REST v2.0** β TML is the only public
|
| 87 |
+
way to define joins; our two-phase create+joins stays.
|
| 88 |
+
- `skip_diff_check: true` (10.6.0.cl+) is an undocumented-beyond-one-line
|
| 89 |
+
import knob; untested, might shave validation time. Not needed at current
|
| 90 |
+
speeds.
|
| 91 |
+
- Search indexing on table add is a background process (docs) and was ruled
|
| 92 |
+
out as the latency source.
|
| 93 |
+
|
| 94 |
+
## 5. The NEXT bottleneck: model semantics (~5 min, LLM-bound)
|
| 95 |
+
|
| 96 |
+
Current solo MCP build profile (Tixr, 9.2 min total):
|
| 97 |
+
|
| 98 |
+
| Phase | Time | Bound by |
|
| 99 |
+
|---|---:|---|
|
| 100 |
+
| Dataset + DDL authoring | ~2.5 min | LLM |
|
| 101 |
+
| Snowflake load + TS tables + joins | **~30s** | (was ~8β10 min) |
|
| 102 |
+
| **Model create + semantic enrichment** | **~5 min** | **LLM, sequential** |
|
| 103 |
+
| Liveboard create + enhance | ~2 min | MCP + LLM titles |
|
| 104 |
+
|
| 105 |
+
The model phase is NOT ThoughtSpot: model TML import is near-instant. The time
|
| 106 |
+
is `model_semantic_updater.py` β per-column description + 3β5 synonyms +
|
| 107 |
+
Spotter `ai_context` for every model column, generated in **sequential batches
|
| 108 |
+
of 25 columns per LLM call** (a 60β110 column model = 3β5 back-to-back calls),
|
| 109 |
+
plus one model-description call.
|
| 110 |
+
|
| 111 |
+
Optimization options (deliberately NOT implemented β decision 2026-08-10 was
|
| 112 |
+
to hold code changes):
|
| 113 |
+
|
| 114 |
+
1. **Parallelize the batches** β the batch calls are independent; running them
|
| 115 |
+
concurrently collapses ~4β5 min to roughly the latency of one call (~1 min).
|
| 116 |
+
Contained change in `model_semantic_updater.generate_column_semantics`.
|
| 117 |
+
Biggest win, lowest risk.
|
| 118 |
+
2. **Overlap phases** β column set is known from the blueprint before Snowflake
|
| 119 |
+
loads; semantics could generate during the data-load wait and be applied
|
| 120 |
+
after model creation. Bigger restructuring, saves the same wall-clock.
|
| 121 |
+
3. **Cheaper model** β descriptions/synonyms are formulaic; a Haiku-class model
|
| 122 |
+
would cut latency and cost. Quality check needed on `ai_context` hints.
|
| 123 |
+
|
| 124 |
+
With option 1 alone, a solo build lands ~5β6 min end to end.
|
sprint_2026_04.md
CHANGED
|
@@ -257,6 +257,8 @@ should tell. KPI targets, growth trends, and anomaly patterns live in the matrix
|
|
| 257 |
### Sprint 4 (this sprint)
|
| 258 |
|
| 259 |
- [x] **Table-create latency root cause + fix (Aug 10)** β ~250s/import was the unscoped TS connection scanning all ~507 Snowflake DBs visible to SE_ROLE (measured identical on sebe AND secloud; NOT instance load, July SRE docs corrected). Fix: (1) connection TML now scoped via required `database` property (`create_connection_tml`), (2) demos write to monthly-rotating DB `<SNOWFLAKE_DATABASE>_<YYYY_MM>` (`get_demo_database()`/`ensure_demo_database()` in `snowflake_auth.py`) since bloated DEMOBUILD (1,003 schemas) still cost 33s vs 0.7s fresh. Probe: `tests/ts_table_create_deepdive.py` β
|
|
|
|
|
|
|
| 260 |
|
| 261 |
- [x] **Branching / Release Strategy** β `main`/`develop`/hotfix workflow documented in CLAUDE.md; `develop` branch confirmed; `v1.0.0` tagged on `main`; `hf-test` remote wired β
|
| 262 |
- [x] **Settings Redesign β accordion** β Right panel: TS Environment + AI Model always visible; collapsible `βοΈ Settings` accordion with Liveboard Name, Data Size, Geo Scope, Tag Name, Column Naming Style, Object Naming Prefix, Share With β
|
|
@@ -289,4 +291,4 @@ should tell. KPI targets, growth trends, and anomaly patterns live in the matrix
|
|
| 289 |
|
| 290 |
---
|
| 291 |
|
| 292 |
-
*Last updated:
|
|
|
|
| 257 |
### Sprint 4 (this sprint)
|
| 258 |
|
| 259 |
- [x] **Table-create latency root cause + fix (Aug 10)** β ~250s/import was the unscoped TS connection scanning all ~507 Snowflake DBs visible to SE_ROLE (measured identical on sebe AND secloud; NOT instance load, July SRE docs corrected). Fix: (1) connection TML now scoped via required `database` property (`create_connection_tml`), (2) demos write to monthly-rotating DB `<SNOWFLAKE_DATABASE>_<YYYY_MM>` (`get_demo_database()`/`ensure_demo_database()` in `snowflake_auth.py`) since bloated DEMOBUILD (1,003 schemas) still cost 33s vs 0.7s fresh. Probe: `tests/ts_table_create_deepdive.py` β
|
| 260 |
+
- [x] **Perf fix verified + deployed (Aug 10)** β app e2e: 655s Grade B, 0 timeouts (pre-fix record: 1,084β2,711s, 12/24 timeouts). Deployed to `hf-test` AND MCP Space `thoughtspot-demoprep/mcp` (`df44611`, rollback `3d735c7`); MCP Tixr rehearsal on new code: PASS, 9.2 min vs 16β20 min. Full research notes: `docs/build_time_deep_dive_2026_08_10.md` β
|
| 261 |
+
- [ ] **Next bottleneck: model semantics ~5 min** β `model_semantic_updater.generate_column_semantics()` runs sequential LLM batches (25 cols/call); parallelizing collapses it to ~1 min β ~5β6 min total builds. Deliberately deferred (no code changes during demo window); see deep-dive doc Β§5
|
| 262 |
|
| 263 |
- [x] **Branching / Release Strategy** β `main`/`develop`/hotfix workflow documented in CLAUDE.md; `develop` branch confirmed; `v1.0.0` tagged on `main`; `hf-test` remote wired β
|
| 264 |
- [x] **Settings Redesign β accordion** β Right panel: TS Environment + AI Model always visible; collapsible `βοΈ Settings` accordion with Liveboard Name, Data Size, Geo Scope, Tag Name, Column Naming Style, Object Naming Prefix, Share With β
|
|
|
|
| 291 |
|
| 292 |
---
|
| 293 |
|
| 294 |
+
*Last updated: August 10, 2026 β table-create perf fix verified + deployed (test + MCP); build-time deep dive documented*
|