Skip to content

Commit 523705d

Browse files
committed
fix: ensure references arent auto gced in server and reparse on deferral state injection
1 parent dba6653 commit 523705d

File tree

4 files changed

+23
-15
lines changed

4 files changed

+23
-15
lines changed

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "dbt-core-interface"
3-
version = "1.1.0"
3+
version = "1.1.1"
44
dynamic = []
55
description = "Dbt Core Interface"
66
authors = [

src/dbt_core_interface/client.py

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -135,12 +135,14 @@ def _request(
135135
)
136136

137137
if resp.status_code >= 400:
138+
d = resp.json()
139+
logger.error(d)
138140
try:
139-
err = ServerErrorContainer.model_validate(resp.json())
141+
err = ServerErrorContainer.model_validate(d)
140142
raise ServerErrorException(err.error)
141-
except ValueError as e:
142-
logger.error("Failed to parse error response: %s", e)
143-
resp.raise_for_status()
143+
except ValueError:
144+
pass
145+
resp.raise_for_status()
144146

145147
return resp
146148

@@ -307,17 +309,13 @@ def inject_state(self, directory: Path | str) -> dict[str, t.Any]:
307309
resp = self._request(
308310
"GET",
309311
"/api/v1/state",
310-
json_payload={"directory": str(directory)},
312+
params={"directory": str(directory)},
311313
)
312-
if resp.ok:
313-
return {}
314314
return resp.json()
315315

316316
def clear_state(self) -> dict[str, t.Any]:
317317
"""Clear the deferral manifest state on the server."""
318318
resp = self._request("DELETE", "/api/v1/state")
319-
if resp.ok:
320-
return {}
321319
return resp.json()
322320

323321
def status(self) -> dict[str, t.Any]:

src/dbt_core_interface/server.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -180,15 +180,17 @@ def _save_state(runners: DbtProjectContainer) -> None:
180180
@asynccontextmanager
181181
async def lifespan(app: FastAPI) -> AsyncGenerator[None, t.Any]:
182182
"""Lifespan context manager for FastAPI app."""
183-
_ = app
184183
_load_saved_state(container := _get_container())
184+
app.state._p_references = {}
185185
for project in container:
186186
_ = DbtProjectWatcher(project, start=True)
187+
app.state._p_references[project] = True
187188
try:
188189
yield
189190
finally:
190191
_save_state(container)
191192
_ = DbtProjectWatcher.stop_all()
193+
app.state._p_references.clear()
192194

193195

194196
app = FastAPI(
@@ -350,6 +352,7 @@ def compile_sql(
350352
@app.get("/api/v1/register")
351353
def register_project(
352354
response: Response,
355+
request: Request,
353356
project_dir: str = Query(...),
354357
profiles_dir: str | None = Query(None),
355358
target: str | None = Query(None),
@@ -370,6 +373,7 @@ def register_project(
370373
_save_state(runners)
371374
watcher = DbtProjectWatcher(dbt_project)
372375
watcher.start()
376+
request.app.state._p_references[dbt_project] = True
373377
except Exception as e:
374378
response.status_code = 400
375379
return ServerErrorContainer(
@@ -387,6 +391,7 @@ def register_project(
387391
@app.delete("/api/v1/register")
388392
def unregister_project(
389393
response: Response,
394+
request: Request,
390395
project_dir: str = Query(..., description="Project directory to unregister."),
391396
runners: DbtProjectContainer = Depends(_get_container),
392397
) -> ServerUnregisterResult | ServerErrorContainer:
@@ -408,6 +413,7 @@ def unregister_project(
408413
_save_state(runners)
409414
if dbt_project:
410415
DbtProjectWatcher.stop_path(dbt_project.project_root)
416+
_ = request.app.state._p_references.pop(dbt_project, None)
411417
return ServerUnregisterResult(
412418
removed=project_path.name, projects=list(map(str, runners.registered_projects()))
413419
)
@@ -650,10 +656,12 @@ def list_projects(runners: DbtProjectContainer = Depends(_get_container)) -> dic
650656
def inject_state(
651657
runner: DbtProject = Depends(_get_runner),
652658
directory: str = Query(..., description="Directory containing the deferral state files."),
653-
) -> ServerErrorContainer | None:
659+
) -> dict[str, t.Any] | ServerErrorContainer:
654660
"""Enable dbt deferral by injecting the deferral state into the runner."""
655661
try:
656662
runner.inject_deferred_state(directory)
663+
runner.parse_project(write_manifest=True)
664+
return {"success": True}
657665
except Exception as e:
658666
raise HTTPException(
659667
status_code=500,
@@ -668,10 +676,12 @@ def inject_state(
668676

669677

670678
@app.delete("/api/v1/state")
671-
def clear_state(runner: DbtProject = Depends(_get_runner)) -> None:
679+
def clear_state(runner: DbtProject = Depends(_get_runner)) -> dict[str, t.Any]:
672680
"""Clear the deferral state in the runner."""
673681
try:
674682
runner.clear_deferred_state()
683+
runner.parse_project(write_manifest=True)
684+
return {"success": True}
675685
except Exception as e:
676686
raise HTTPException(
677687
status_code=500,

uv.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)