dlt-utils-lib 1.2.6__tar.gz → 1.2.7__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (20) hide show
  1. {dlt_utils_lib-1.2.6 → dlt_utils_lib-1.2.7}/PKG-INFO +1 -1
  2. {dlt_utils_lib-1.2.6 → dlt_utils_lib-1.2.7}/dlt_utils/dlt_autoloader_recovery_configuration.py +14 -1
  3. {dlt_utils_lib-1.2.6 → dlt_utils_lib-1.2.7}/dlt_utils_lib.egg-info/PKG-INFO +1 -1
  4. {dlt_utils_lib-1.2.6 → dlt_utils_lib-1.2.7}/dlt_utils_lib.egg-info/SOURCES.txt +1 -0
  5. dlt_utils_lib-1.2.7/tests/test_autoloader_recovery_configuration.py +68 -0
  6. {dlt_utils_lib-1.2.6 → dlt_utils_lib-1.2.7}/dlt_utils/__init__.py +0 -0
  7. {dlt_utils_lib-1.2.6 → dlt_utils_lib-1.2.7}/dlt_utils/dlt_metadata_receiver.py +0 -0
  8. {dlt_utils_lib-1.2.6 → dlt_utils_lib-1.2.7}/dlt_utils/dlt_transformations.py +0 -0
  9. {dlt_utils_lib-1.2.6 → dlt_utils_lib-1.2.7}/dlt_utils/main_cdc_utils.py +0 -0
  10. {dlt_utils_lib-1.2.6 → dlt_utils_lib-1.2.7}/dlt_utils/main_json_utils.py +0 -0
  11. {dlt_utils_lib-1.2.6 → dlt_utils_lib-1.2.7}/dlt_utils_lib.egg-info/dependency_links.txt +0 -0
  12. {dlt_utils_lib-1.2.6 → dlt_utils_lib-1.2.7}/dlt_utils_lib.egg-info/requires.txt +0 -0
  13. {dlt_utils_lib-1.2.6 → dlt_utils_lib-1.2.7}/dlt_utils_lib.egg-info/top_level.txt +0 -0
  14. {dlt_utils_lib-1.2.6 → dlt_utils_lib-1.2.7}/setup.cfg +0 -0
  15. {dlt_utils_lib-1.2.6 → dlt_utils_lib-1.2.7}/setup.py +0 -0
  16. {dlt_utils_lib-1.2.6 → dlt_utils_lib-1.2.7}/tests/__init__.py +0 -0
  17. {dlt_utils_lib-1.2.6 → dlt_utils_lib-1.2.7}/tests/conftest.py +0 -0
  18. {dlt_utils_lib-1.2.6 → dlt_utils_lib-1.2.7}/tests/test_main_cdc_utils.py +0 -0
  19. {dlt_utils_lib-1.2.6 → dlt_utils_lib-1.2.7}/tests/test_main_json_utils.py +0 -0
  20. {dlt_utils_lib-1.2.6 → dlt_utils_lib-1.2.7}/tests/test_transformation_module.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dlt_utils_lib
3
- Version: 1.2.6
3
+ Version: 1.2.7
4
4
  Summary: UNKNOWN
5
5
  Home-page: UNKNOWN
6
6
  License: UNKNOWN
@@ -2,6 +2,8 @@ import logging
2
2
 
3
3
  from databricks.sdk import WorkspaceClient
4
4
 
5
+ _RECOVERY_DECISION = None
6
+
5
7
 
6
8
  def _needs_autoloader_recovery(pipeline_id: str) -> bool:
7
9
  event = next(iter(WorkspaceClient().pipelines.list_pipeline_events(
@@ -18,9 +20,20 @@ def _needs_autoloader_recovery(pipeline_id: str) -> bool:
18
20
 
19
21
 
20
22
  def resolve_autoloader_recovery(spark) -> bool:
23
+ # Cached for the lifetime of the driver process: the decision belongs to the
24
+ # update as a whole, but callers ask once per table while the pipeline graph
25
+ # is built. Uncached, a 94-table pipeline makes 94 Pipelines API calls,
26
+ # serialized on the driver, before a single stream starts.
27
+ global _RECOVERY_DECISION
28
+ if _RECOVERY_DECISION is None:
29
+ _RECOVERY_DECISION = _resolve_autoloader_recovery(spark)
30
+ return _RECOVERY_DECISION
31
+
32
+
33
+ def _resolve_autoloader_recovery(spark) -> bool:
21
34
  method = spark.conf.get("autoloader_recovery_method", "AUTO").upper()
22
35
  if method == "ON":
23
36
  return True
24
37
  if method == "AUTO":
25
38
  return _needs_autoloader_recovery(spark.conf.get("pipelines.id"))
26
- return False
39
+ return False
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dlt-utils-lib
3
- Version: 1.2.6
3
+ Version: 1.2.7
4
4
  Summary: UNKNOWN
5
5
  Home-page: UNKNOWN
6
6
  License: UNKNOWN
@@ -12,6 +12,7 @@ dlt_utils_lib.egg-info/requires.txt
12
12
  dlt_utils_lib.egg-info/top_level.txt
13
13
  tests/__init__.py
14
14
  tests/conftest.py
15
+ tests/test_autoloader_recovery_configuration.py
15
16
  tests/test_main_cdc_utils.py
16
17
  tests/test_main_json_utils.py
17
18
  tests/test_transformation_module.py
@@ -0,0 +1,68 @@
1
+ import pytest
2
+
3
+ import dlt_utils.dlt_autoloader_recovery_configuration as recovery
4
+
5
+
6
+ class _SparkConfStub:
7
+ def __init__(self, values):
8
+ self._values = values
9
+
10
+ def get(self, key, default=None):
11
+ return self._values.get(key, default)
12
+
13
+
14
+ class _SparkStub:
15
+ def __init__(self, **values):
16
+ self.conf = _SparkConfStub(values)
17
+
18
+
19
+ @pytest.fixture(autouse=True)
20
+ def reset_cached_decision():
21
+ recovery._RECOVERY_DECISION = None
22
+ yield
23
+ recovery._RECOVERY_DECISION = None
24
+
25
+
26
+ def test_method_on_forces_recovery_without_calling_the_api(monkeypatch):
27
+ monkeypatch.setattr(recovery, "_needs_autoloader_recovery", _unexpected_api_call)
28
+
29
+ assert recovery.resolve_autoloader_recovery(
30
+ _SparkStub(autoloader_recovery_method="ON")
31
+ ) is True
32
+
33
+
34
+ def test_method_off_skips_recovery_without_calling_the_api(monkeypatch):
35
+ monkeypatch.setattr(recovery, "_needs_autoloader_recovery", _unexpected_api_call)
36
+
37
+ assert recovery.resolve_autoloader_recovery(
38
+ _SparkStub(autoloader_recovery_method="OFF")
39
+ ) is False
40
+
41
+
42
+ def test_method_auto_asks_the_pipelines_api(monkeypatch):
43
+ seen = []
44
+ monkeypatch.setattr(recovery, "_needs_autoloader_recovery",
45
+ lambda pipeline_id: seen.append(pipeline_id) or True)
46
+
47
+ spark = _SparkStub(autoloader_recovery_method="AUTO", **{"pipelines.id": "pipeline-1"})
48
+
49
+ assert recovery.resolve_autoloader_recovery(spark) is True
50
+ assert seen == ["pipeline-1"]
51
+
52
+
53
+ def test_decision_is_resolved_once_per_process(monkeypatch):
54
+ calls = []
55
+ monkeypatch.setattr(recovery, "_needs_autoloader_recovery",
56
+ lambda pipeline_id: calls.append(pipeline_id) or True)
57
+
58
+ spark = _SparkStub(autoloader_recovery_method="AUTO", **{"pipelines.id": "pipeline-1"})
59
+
60
+ # One call per table while the DLT graph is built; only the first may hit the API.
61
+ for _ in range(10):
62
+ assert recovery.resolve_autoloader_recovery(spark) is True
63
+
64
+ assert calls == ["pipeline-1"]
65
+
66
+
67
+ def _unexpected_api_call(pipeline_id):
68
+ raise AssertionError(f"Pipelines API should not be called (pipeline_id={pipeline_id})")
File without changes
File without changes