prophecy-libs 2.0.0.dev1__tar.gz → 2.0.0.dev2__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 (137) hide show
  1. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/PKG-INFO +1 -1
  2. prophecy-libs-2.0.0.dev2/prophecy/executionmetrics/componentruns/component_run_service.py +307 -0
  3. prophecy-libs-2.0.0.dev2/prophecy/executionmetrics/componentruns/component_runs_dao.py +835 -0
  4. prophecy-libs-2.0.0.dev2/prophecy/executionmetrics/evolutions/__init__.py +0 -0
  5. prophecy-libs-2.0.0.dev2/prophecy/executionmetrics/evolutions/delta_metrics_storage_initializer.py +366 -0
  6. prophecy-libs-2.0.0.dev2/prophecy/executionmetrics/evolutions/hive_parquet_storage_initializer.py +279 -0
  7. prophecy-libs-2.0.0.dev2/prophecy/executionmetrics/evolutions/metrics_storage_initializer.py +286 -0
  8. prophecy-libs-2.0.0.dev2/prophecy/executionmetrics/evolutions/models.py +115 -0
  9. prophecy-libs-2.0.0.dev2/prophecy/executionmetrics/evolutions/package.py +302 -0
  10. prophecy-libs-2.0.0.dev2/prophecy/executionmetrics/execution_metrics_handler.py +393 -0
  11. prophecy-libs-2.0.0.dev2/prophecy/executionmetrics/in_memory_store.py +955 -0
  12. prophecy-libs-2.0.0.dev2/prophecy/executionmetrics/interims/__init__.py +0 -0
  13. prophecy-libs-2.0.0.dev2/prophecy/executionmetrics/interims/delta_interims.py +249 -0
  14. prophecy-libs-2.0.0.dev2/prophecy/executionmetrics/interims/hive_parquet_interims.py +224 -0
  15. prophecy-libs-2.0.0.dev2/prophecy/executionmetrics/interims/interims_table.py +239 -0
  16. prophecy-libs-2.0.0.dev2/prophecy/executionmetrics/logging_spark_session.py +162 -0
  17. prophecy-libs-2.0.0.dev2/prophecy/executionmetrics/models.py +28 -0
  18. prophecy-libs-2.0.0.dev2/prophecy/executionmetrics/package.py +1140 -0
  19. prophecy-libs-2.0.0.dev2/prophecy/executionmetrics/pipelineruns/__init__.py +0 -0
  20. prophecy-libs-2.0.0.dev2/prophecy/executionmetrics/pipelineruns/pipeline_run_service.py +782 -0
  21. prophecy-libs-2.0.0.dev2/prophecy/executionmetrics/pipelineruns/pipeline_runs_dao.py +433 -0
  22. prophecy-libs-2.0.0.dev2/prophecy/executionmetrics/schemas/__init__.py +0 -0
  23. prophecy-libs-2.0.0.dev2/prophecy/executionmetrics/schemas/em.py +260 -0
  24. prophecy-libs-2.0.0.dev2/prophecy/executionmetrics/schemas/external.py +119 -0
  25. prophecy-libs-2.0.0.dev2/prophecy/executionmetrics/utils/__init__.py +0 -0
  26. prophecy-libs-2.0.0.dev2/prophecy/executionmetrics/utils/common.py +82 -0
  27. prophecy-libs-2.0.0.dev2/prophecy/executionmetrics/utils/constants.py +62 -0
  28. prophecy-libs-2.0.0.dev2/prophecy/executionmetrics/utils/external.py +394 -0
  29. prophecy-libs-2.0.0.dev2/prophecy/executionmetrics/utils/interim_store.py +316 -0
  30. prophecy-libs-2.0.0.dev2/prophecy/executionmetrics/zip_file.py +162 -0
  31. prophecy-libs-2.0.0.dev2/prophecy/jsonrpc/__init__.py +0 -0
  32. prophecy-libs-2.0.0.dev2/prophecy/jsonrpc/models.py +809 -0
  33. prophecy-libs-2.0.0.dev2/prophecy/streaming/__init__.py +0 -0
  34. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/utils/__init__.py +3 -2
  35. prophecy-libs-2.0.0.dev2/prophecy/utils/constants.py +42 -0
  36. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/utils/datasampleloader.py +4 -10
  37. prophecy-libs-2.0.0.dev2/prophecy/utils/faker/utils/__init__.py +0 -0
  38. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/utils/initial_python_code.py +13 -1
  39. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/utils/json_rpc_layer.py +23 -57
  40. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/utils/pipeline_monitoring.py +155 -120
  41. prophecy-libs-2.0.0.dev2/prophecy/utils/request_processor.py +121 -0
  42. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/utils/secrets.py +194 -146
  43. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/utils/utils.py +1124 -224
  44. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy_libs.egg-info/PKG-INFO +1 -1
  45. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy_libs.egg-info/SOURCES.txt +34 -0
  46. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy_libs.egg-info/requires.txt +2 -0
  47. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/setup.py +8 -2
  48. prophecy-libs-2.0.0.dev1/prophecy/utils/request_processor.py +0 -74
  49. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/README.md +0 -0
  50. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/__init__.py +0 -0
  51. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/config/__init__.py +0 -0
  52. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/config/config_base.py +0 -0
  53. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/config/config_base_test.py +0 -0
  54. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/config/utils.py +0 -0
  55. {prophecy-libs-2.0.0.dev1/prophecy/streaming → prophecy-libs-2.0.0.dev2/prophecy/executionmetrics}/__init__.py +0 -0
  56. {prophecy-libs-2.0.0.dev1/prophecy/utils/faker/utils → prophecy-libs-2.0.0.dev2/prophecy/executionmetrics/componentruns}/__init__.py +0 -0
  57. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/libs/__init__.py +0 -0
  58. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/libs/uc_shared_utils.py +0 -0
  59. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/libs/utils.py +0 -0
  60. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/lookups/LookupsBase.py +0 -0
  61. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/lookups/LookupsNative.py +0 -0
  62. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/lookups/__init__.py +0 -0
  63. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/random_data_creator.py +0 -0
  64. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/streaming/delta_lake_utils.py +0 -0
  65. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/test/__init__.py +0 -0
  66. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/test/base_test_case.py +0 -0
  67. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/test/utils.py +0 -0
  68. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/udfs/__init__.py +0 -0
  69. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/udfs/rest_api_udf.py +0 -0
  70. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/udfs/sample_udf.py +0 -0
  71. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/udfs/scala_udf_wrapper.py +0 -0
  72. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/utils/data_profiler.py +0 -0
  73. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/utils/diff.py +0 -0
  74. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/utils/dill/__diff.py +0 -0
  75. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/utils/dill/__init__.py +0 -0
  76. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/utils/dill/_dill.py +0 -0
  77. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/utils/dill/_objects.py +0 -0
  78. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/utils/dill/_shims.py +0 -0
  79. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/utils/dill/detect.py +0 -0
  80. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/utils/dill/logger.py +0 -0
  81. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/utils/dill/objtypes.py +0 -0
  82. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/utils/dill/pointers.py +0 -0
  83. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/utils/dill/session.py +0 -0
  84. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/utils/dill/settings.py +0 -0
  85. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/utils/dill/source.py +0 -0
  86. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/utils/dill/temp.py +0 -0
  87. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/utils/faker/__init__.py +0 -0
  88. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/utils/faker/__main__.py +0 -0
  89. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/utils/faker/cli.py +0 -0
  90. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/utils/faker/config.py +0 -0
  91. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/utils/faker/custom_typing.py +0 -0
  92. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/utils/faker/decode/__init__.py +0 -0
  93. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/utils/faker/decode/codes.py +0 -0
  94. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/utils/faker/documentor.py +0 -0
  95. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/utils/faker/exceptions.py +0 -0
  96. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/utils/faker/factory.py +0 -0
  97. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/utils/faker/generator.py +0 -0
  98. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/utils/faker/providers/__init__.py +0 -0
  99. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/utils/faker/providers/address/__init__.py +0 -0
  100. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/utils/faker/providers/address/en/__init__.py +0 -0
  101. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/utils/faker/providers/address/en_US/__init__.py +0 -0
  102. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/utils/faker/providers/date_time/__init__.py +0 -0
  103. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/utils/faker/providers/date_time/en_US/__init__.py +0 -0
  104. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/utils/faker/providers/internet/__init__.py +0 -0
  105. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/utils/faker/providers/internet/en_US/__init__.py +0 -0
  106. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/utils/faker/providers/misc/__init__.py +0 -0
  107. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/utils/faker/providers/misc/en_US/__init__.py +0 -0
  108. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/utils/faker/providers/person/__init__.py +0 -0
  109. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/utils/faker/providers/person/en_US/__init__.py +0 -0
  110. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/utils/faker/providers/phone_number/__init__.py +0 -0
  111. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/utils/faker/providers/phone_number/en_US/__init__.py +0 -0
  112. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/utils/faker/providers/python/__init__.py +0 -0
  113. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/utils/faker/providers/python/en_US/__init__.py +0 -0
  114. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/utils/faker/proxy.py +0 -0
  115. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/utils/faker/utils/checksums.py +0 -0
  116. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/utils/faker/utils/datasets.py +0 -0
  117. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/utils/faker/utils/decorators.py +0 -0
  118. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/utils/faker/utils/distribution.py +0 -0
  119. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/utils/faker/utils/loading.py +0 -0
  120. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/utils/faker/utils/text.py +0 -0
  121. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/utils/functions.py +0 -0
  122. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/utils/gems_utils.py +0 -0
  123. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/utils/httpclient.py +0 -0
  124. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/utils/metagem_utils.py +0 -0
  125. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/utils/monitoring_utils.py +0 -0
  126. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/utils/synthetic_data_generator.py +0 -0
  127. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/utils/transpiler/__init__.py +0 -0
  128. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/utils/transpiler/abi_base.py +0 -0
  129. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/utils/transpiler/abi_core_fcns.py +0 -0
  130. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/utils/transpiler/abi_fcn_wrapper.py +0 -0
  131. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/utils/transpiler/dataframe_fcns.py +0 -0
  132. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/utils/transpiler/dml_schema.py +0 -0
  133. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy/utils/transpiler/fixed_file_schema.py +0 -0
  134. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy_libs.egg-info/dependency_links.txt +0 -0
  135. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy_libs.egg-info/not-zip-safe +0 -0
  136. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/prophecy_libs.egg-info/top_level.txt +0 -0
  137. {prophecy-libs-2.0.0.dev1 → prophecy-libs-2.0.0.dev2}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 1.0
2
2
  Name: prophecy-libs
3
- Version: 2.0.0.dev1
3
+ Version: 2.0.0.dev2
4
4
  Summary: Helper library for prophecy generated code
5
5
  Home-page: https://github.com/SimpleDataLabsInc/prophecy-python-libs
6
6
  Author: UNKNOWN
@@ -0,0 +1,307 @@
1
+ """
2
+ Component Run Service for execution metrics.
3
+
4
+ This module provides business logic layer for component run operations,
5
+ coordinating between DAOs and handling interim data management.
6
+ """
7
+
8
+ import logging
9
+ import json
10
+ from typing import List, Dict, Optional, Tuple
11
+
12
+ from pyspark.sql import SparkSession, DataFrame
13
+
14
+ from prophecy.executionmetrics.componentruns.component_runs_dao import (
15
+ ComponentRunsDAO,
16
+ ComponentRuns,
17
+ ComponentRunsWithStatus,
18
+ ComponentRunsWithRunDates,
19
+ Filters,
20
+ )
21
+ from prophecy.executionmetrics.package import InterimResponse, PipelineRuns
22
+ from prophecy.executionmetrics.evolutions.metrics_storage_initializer import (
23
+ StorageMetadata,
24
+ )
25
+ from prophecy.executionmetrics.interims.interims_table import (
26
+ create_interims_table,
27
+ )
28
+ from prophecy.executionmetrics.schemas.external import (
29
+ ComponentRunIdAndInterims,
30
+ LInterimContent,
31
+ )
32
+ from prophecy.executionmetrics.utils.common import now_utc
33
+
34
+ logger = logging.getLogger(__name__)
35
+
36
+
37
+ def to_json_string(obj: any) -> str:
38
+ """Convert object to JSON string."""
39
+ if hasattr(obj, "__dict__"):
40
+ return json.dumps(obj.__dict__, default=str)
41
+ return json.dumps(obj, default=str)
42
+
43
+
44
+ def component_iterators_and_interims(
45
+ interims: List[LInterimContent], port_to_run_id_map: Dict[str, List[str]]
46
+ ) -> List[ComponentRunIdAndInterims]:
47
+ """
48
+ Convert interim content to component run ID and interims.
49
+
50
+ Args:
51
+ interims: List of interim content
52
+ port_to_run_id_map: Mapping from port to run IDs
53
+
54
+ Returns:
55
+ List of ComponentRunIdAndInterims
56
+ """
57
+ result = []
58
+
59
+ for interim in interims:
60
+ # Get run IDs for this port
61
+ run_ids = port_to_run_id_map.get(interim.port, [])
62
+
63
+ # Create entry for each run ID
64
+ for run_id in run_ids:
65
+ # Convert interim to JSON string
66
+ interim_json = to_json_string(interim)
67
+
68
+ result.append(
69
+ ComponentRunIdAndInterims(
70
+ uid=run_id, run_id=run_id, interims=interim_json
71
+ )
72
+ )
73
+
74
+ return result
75
+
76
+
77
+ class ComponentRunService:
78
+ """
79
+ Service layer for component run operations.
80
+
81
+ This class provides business logic for managing component runs,
82
+ including querying, adding, and managing interim data.
83
+ """
84
+
85
+ def __init__(
86
+ self,
87
+ dao: ComponentRunsDAO,
88
+ spark: SparkSession,
89
+ storage_metadata: StorageMetadata,
90
+ ):
91
+ """
92
+ Initialize the service.
93
+
94
+ Args:
95
+ dao: Component runs DAO
96
+ spark: SparkSession
97
+ storage_metadata: Storage configuration
98
+ """
99
+ self.dao = dao
100
+ self.spark = spark
101
+ self.storage_metadata = storage_metadata
102
+ self.logger = logger
103
+
104
+ @classmethod
105
+ def create(
106
+ cls, spark: SparkSession, storage_metadata: StorageMetadata
107
+ ) -> "ComponentRunService":
108
+ """
109
+ Factory method to create service without user context.
110
+
111
+ Args:
112
+ spark: SparkSession
113
+ storage_metadata: Storage configuration
114
+
115
+ Returns:
116
+ ComponentRunService instance
117
+ """
118
+ dao = ComponentRunsDAO(spark, storage_metadata, None)
119
+ return cls(dao, spark, storage_metadata)
120
+
121
+ # @classmethod
122
+ # def create_with_user(
123
+ # cls,
124
+ # spark: SparkSession,
125
+ # storage_metadata: StorageMetadata,
126
+ # user_id: str,
127
+ # ) -> "ComponentRunService":
128
+ # """
129
+ # Factory method to create service with user context.
130
+
131
+ # Args:
132
+ # spark: SparkSession
133
+ # storage_metadata: Storage configuration
134
+ # user_id: User ID for interims table
135
+
136
+ # Returns:
137
+ # ComponentRunService instance
138
+ # """
139
+ # interims_table = create_interims_table(spark, user_id, storage_metadata)
140
+ # dao = ComponentRunsDAO(spark, storage_metadata, interims_table)
141
+ # return cls(dao, spark, storage_metadata)
142
+
143
+ # Query methods - delegate to DAO
144
+
145
+ def get_by_id(
146
+ self, uid: str, filters: Filters, expired_runs: bool = False
147
+ ) -> ComponentRuns:
148
+ """Get component run by ID."""
149
+ return self.dao.get_by_id(uid, filters, expired_runs)
150
+
151
+ def get_dataset_runs_by_dataset_id(
152
+ self,
153
+ dataset_uri: str,
154
+ limit: int = 100,
155
+ offset_uid_optional: Optional[int] = None,
156
+ filters: Filters = None,
157
+ ) -> List[ComponentRuns]:
158
+ """Get dataset runs by dataset ID."""
159
+ return self.dao.get_dataset_runs_by_dataset_id(
160
+ dataset_uri, limit, offset_uid_optional, filters
161
+ )
162
+
163
+ def get_dataset_runs_by_dataset_and_fabric_id(
164
+ self, dataset_uri: str, limit: int = 100, filters: Filters = None
165
+ ) -> List[ComponentRuns]:
166
+ """Get dataset runs by dataset and fabric ID."""
167
+ return self.dao.get_dataset_runs_by_dataset_and_fabric_id(
168
+ dataset_uri, limit, filters
169
+ )
170
+
171
+ def get_by_pipeline_id(
172
+ self, pipeline_uri: str, limit: int = 100, filters: Filters = None
173
+ ) -> List[ComponentRuns]:
174
+ """Get component runs by pipeline ID."""
175
+ return self.dao.get_by_pipeline_id(pipeline_uri, limit, filters)
176
+
177
+ def get_dataset_runs_by_pipeline_id(
178
+ self, pipeline_uri: str, limit: int = 100, filters: Filters = None
179
+ ) -> List[ComponentRuns]:
180
+ """Get dataset runs by pipeline ID."""
181
+ return self.dao.get_dataset_runs_by_pipeline_id(pipeline_uri, limit, filters)
182
+
183
+ def get_by_pipeline_run_id(
184
+ self,
185
+ pipeline_run_id: str,
186
+ get_expired_runs: bool = False,
187
+ filters: Filters = None,
188
+ ) -> List[ComponentRuns]:
189
+ """Get component runs by pipeline run ID."""
190
+ return self.dao.get_by_pipeline_run_id(
191
+ pipeline_run_id, get_expired_runs, filters
192
+ )
193
+
194
+ def get_ids_by_pipeline_run_id(
195
+ self, pipeline_run_id: str, filters: Filters
196
+ ) -> List[str]:
197
+ """Get component run IDs by pipeline run ID."""
198
+ return self.dao.get_ids_by_pipeline_run_id(pipeline_run_id, filters)
199
+
200
+ def get_dataset_runs_by_pipeline_run_id(
201
+ self, pipeline_run_id: str, filters: Filters = None
202
+ ) -> List[ComponentRuns]:
203
+ """Get dataset runs by pipeline run ID."""
204
+ return self.dao.get_dataset_runs_by_pipeline_run_id(
205
+ pipeline_run_id, filters=filters
206
+ )
207
+
208
+ def add_values(
209
+ self, component_runs_entity_list: List[ComponentRuns]
210
+ ) -> List[ComponentRuns]:
211
+ """Add component runs."""
212
+ return self.dao.add_values(component_runs_entity_list)
213
+
214
+ def add_recursive(
215
+ self,
216
+ pipeline_run: PipelineRuns,
217
+ component_runs_entities: List[ComponentRuns],
218
+ interims: List[LInterimContent],
219
+ created_by: str,
220
+ ) -> Tuple[List[ComponentRuns], List[str]]:
221
+ """
222
+ Add component runs and interims recursively.
223
+
224
+ This method handles the complex process of:
225
+ 1. Creating interims table for the user
226
+ 2. Building port to run ID mapping
227
+ 3. Adding component runs to storage
228
+ 4. Adding interim data with proper associations
229
+
230
+ Args:
231
+ pipeline_run: Pipeline run entity
232
+ component_runs_entities: List of component runs to add
233
+ interims: List of interim content
234
+ created_by: User who created the runs
235
+
236
+ Returns:
237
+ Tuple of (added component runs, interim IDs)
238
+ """
239
+ # Create interims table for user
240
+ interims_table = create_interims_table(
241
+ spark_session=self.spark,
242
+ user=created_by,
243
+ storage_metadata=self.storage_metadata,
244
+ )
245
+
246
+ # Build port to run ID mapping
247
+ port_to_run_id_map = {}
248
+ for run in component_runs_entities:
249
+ port = run.interim_out_port
250
+ if port not in port_to_run_id_map:
251
+ port_to_run_id_map[port] = []
252
+ port_to_run_id_map[port].append(run.uid)
253
+
254
+ # Add component runs to storage
255
+ component_runs = self.dao.add_values(component_runs_entities)
256
+
257
+ # Convert interims to component run ID and interims format
258
+ component_run_id_and_interims = component_iterators_and_interims(
259
+ interims, port_to_run_id_map
260
+ )
261
+
262
+ # Add interims to storage
263
+ interims_data = interims_table.add_multi(
264
+ component_run_id_and_interims,
265
+ created_by,
266
+ pipeline_run.fabric_uid,
267
+ pipeline_run.created_at or now_utc(),
268
+ )
269
+
270
+ return component_runs, interims_data
271
+
272
+ def get_interims_for_pipeline_run_id(
273
+ self, pipeline_run_id: str, updated_by: str, filters: Filters
274
+ ) -> List[InterimResponse]:
275
+ """Get interims for pipeline run ID."""
276
+ return self.dao.get_interims_for_pipeline_run_id(
277
+ pipeline_run_id, updated_by, filters
278
+ )
279
+
280
+ def get_dataset_runs_with_status(
281
+ self, dataset_uri: str, limit: int = 100, filters: Filters = None
282
+ ) -> List[ComponentRunsWithStatus]:
283
+ """Get dataset runs with pipeline status."""
284
+ return self.dao.get_dataset_run_with_run_status(dataset_uri, limit, filters)
285
+
286
+ def expire(self, uid: str, filters: Filters) -> DataFrame:
287
+ """Expire a component run."""
288
+ return self.dao.expire(uid, filters)
289
+
290
+ def get_detailed_dataset(
291
+ self, dataset_run_id: str, updated_by: str, filters: Filters
292
+ ) -> ComponentRunsWithRunDates:
293
+ """Get detailed dataset information including interims and run dates."""
294
+ return self.dao.get_detailed_dataset_runs(
295
+ run_id=dataset_run_id, updated_by=updated_by, filters=filters
296
+ )
297
+
298
+ def get_interims_for_pipeline_run_id_detailed(
299
+ self, run_id: str, filters: Filters
300
+ ) -> ComponentRunsWithRunDates:
301
+ """Get detailed interims for pipeline run ID."""
302
+ # Empty updated_by since it's not needed for this query
303
+ return self.dao.get_detailed_dataset_runs(run_id, "", filters)
304
+
305
+ def refresh(self):
306
+ """Refresh underlying tables."""
307
+ self.dao.refresh()