Skip to content

Commit 874068d

Browse files
committed
fix(code-bundle): rebuild after source changes
Remove argument-only async LRU caching from code bundle builders so each invocation re-hashes the current source files. Keep persistent cache reuse for unchanged bundles and add regression test Signed-off-by: Jeff Chung <sh1001309@gmail.com>
1 parent d6dcbf9 commit 874068d

4 files changed

Lines changed: 39 additions & 34 deletions

File tree

examples/integration_tests.py

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,18 +26,12 @@
2626
import pytest
2727

2828
import flyte
29-
from flyte._code_bundle import build_code_bundle
3029

3130
# =============================================================================
3231
# FIXTURES
3332
# =============================================================================
3433

3534

36-
@pytest.fixture(autouse=True)
37-
def clear_lru_caches():
38-
build_code_bundle.cache_clear()
39-
40-
4135
@pytest.fixture(scope="session")
4236
def flyte_client():
4337
"""

src/flyte/_code_bundle/bundle.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,6 @@
2020
except ImportError: # pragma: no cover - Windows local dev; task containers are POSIX
2121
fcntl = None # type: ignore[assignment] # ty: ignore[invalid-assignment]
2222

23-
from async_lru import alru_cache
24-
2523
from flyte._logging import log, logger
2624
from flyte._status import status
2725
from flyte._utils import AsyncLRUCache
@@ -184,7 +182,6 @@ async def build_pkl_bundle(
184182
return CodeBundle(pkl=str(dest), computed_version=str_digest)
185183

186184

187-
@alru_cache
188185
async def build_code_bundle(
189186
from_dir: Path,
190187
*ignore: Type[Ignore],
@@ -292,7 +289,6 @@ async def build_code_bundle(
292289
return CodeBundle(tgz=remote_path, destination=extract_dir, computed_version=hash_digest, files=files)
293290

294291

295-
@alru_cache
296292
async def build_code_bundle_from_relative_paths(
297293
relative_paths: tuple[str, ...],
298294
from_dir: Path,

tests/flyte/app/test_app_code_bundling.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ async def test_code_bundle_consistency_with_include_files(temp_app_directory):
5050
from_dir=temp_app_directory,
5151
dryrun=True,
5252
)
53-
build_code_bundle_from_relative_paths.cache_clear()
53+
5454
bundle2 = await build_code_bundle_from_relative_paths(
5555
relative_paths=include_files,
5656
from_dir=temp_app_directory,
@@ -70,7 +70,7 @@ async def test_code_bundle_consistency_with_subdirectory_files(temp_app_director
7070
from_dir=temp_app_directory,
7171
dryrun=True,
7272
)
73-
build_code_bundle_from_relative_paths.cache_clear()
73+
7474
bundle2 = await build_code_bundle_from_relative_paths(
7575
relative_paths=include_files,
7676
from_dir=temp_app_directory,
@@ -89,7 +89,7 @@ async def test_code_bundle_different_files_produce_different_versions(temp_app_d
8989
from_dir=temp_app_directory,
9090
dryrun=True,
9191
)
92-
build_code_bundle_from_relative_paths.cache_clear()
92+
9393
bundle2 = await build_code_bundle_from_relative_paths(
9494
relative_paths=("app.py", "utils.py"),
9595
from_dir=temp_app_directory,
@@ -106,7 +106,7 @@ async def test_code_bundle_file_content_changes_version(temp_app_directory):
106106
from_dir=temp_app_directory,
107107
dryrun=True,
108108
)
109-
build_code_bundle_from_relative_paths.cache_clear()
109+
110110
(temp_app_directory / "app.py").write_text("print('Modified content!')")
111111
bundle2 = await build_code_bundle_from_relative_paths(
112112
relative_paths=("app.py",),

tests/flyte/code_bundle/test_build_code_bundle.py

Lines changed: 35 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,7 @@
2424

2525
import pytest
2626

27-
from flyte._code_bundle.bundle import (
28-
build_code_bundle,
29-
build_code_bundle_from_relative_paths,
30-
)
27+
from flyte._code_bundle.bundle import build_code_bundle
3128

3229
TESTDATA_ROOT = Path(__file__).parent / "testdata"
3330

@@ -103,20 +100,6 @@ def _load(path: Path, name: str) -> ModuleType:
103100
sys.modules.pop(name, None)
104101

105102

106-
@pytest.fixture(autouse=True)
107-
def _clear_bundle_cache() -> Iterator[None]:
108-
"""
109-
``build_code_bundle`` is wrapped in ``alru_cache`` at module level. Clear
110-
it before and after each test so cached results from one layout never leak
111-
into another — and so determinism tests can re-run the same inputs.
112-
"""
113-
build_code_bundle.cache_clear()
114-
build_code_bundle_from_relative_paths.cache_clear()
115-
yield
116-
build_code_bundle.cache_clear()
117-
build_code_bundle_from_relative_paths.cache_clear()
118-
119-
120103
# ---------------------------------------------------------------------------
121104
# Single-file layouts
122105
# ---------------------------------------------------------------------------
@@ -359,6 +342,40 @@ async def test_build_code_bundle_multi_file_loaded_modules_with_include(importer
359342
# ---------------------------------------------------------------------------
360343

361344

345+
@pytest.mark.asyncio
346+
async def test_build_code_bundle_refreshes_after_source_file_changes():
347+
with tempfile.TemporaryDirectory() as tmp:
348+
tmp_dir = Path(tmp)
349+
layout = _copy_layout("single_file", tmp_dir)
350+
bundle_out = _bundle_out(tmp_dir)
351+
352+
bundle_before = await build_code_bundle(
353+
from_dir=layout,
354+
dryrun=True,
355+
copy_style="all",
356+
copy_bundle_to=bundle_out,
357+
)
358+
359+
updated_source = """\
360+
def fn(x: int) -> int:
361+
return x + 1
362+
"""
363+
(layout / "hello.py").write_text(updated_source)
364+
365+
bundle_after = await build_code_bundle(
366+
from_dir=layout,
367+
dryrun=True,
368+
copy_style="all",
369+
copy_bundle_to=bundle_out,
370+
)
371+
372+
with tarfile.open(Path(bundle_after.tgz), "r:gz") as tar:
373+
bundled_file = tar.extractfile("hello.py")
374+
assert bundled_file is not None
375+
assert bundled_file.read().decode("utf-8") == updated_source
376+
assert bundle_after.computed_version != bundle_before.computed_version
377+
378+
362379
@pytest.mark.asyncio
363380
async def test_build_code_bundle_digest_is_content_addressed():
364381
"""
@@ -399,8 +416,6 @@ async def test_build_code_bundle_include_changes_digest():
399416
copy_style="all",
400417
copy_bundle_to=_bundle_out(tmp_dir, "out_1"),
401418
)
402-
# Clear so the second call doesn't return the cached result.
403-
build_code_bundle.cache_clear()
404419

405420
bundle_with_extra = await build_code_bundle(
406421
from_dir=layout,

0 commit comments

Comments
 (0)