SilverStreamingApplication 1.1__tar.gz → 1.3__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.
- {SilverStreamingApplication-1.1 → SilverStreamingApplication-1.3}/PKG-INFO +1 -1
- {SilverStreamingApplication-1.1 → SilverStreamingApplication-1.3}/SilverStreamingApplication.egg-info/PKG-INFO +1 -1
- {SilverStreamingApplication-1.1 → SilverStreamingApplication-1.3}/com/phida/main/SilverMerge.py +55 -10
- {SilverStreamingApplication-1.1 → SilverStreamingApplication-1.3}/com/phida/main/WorkflowBuilder.py +12 -4
- {SilverStreamingApplication-1.1 → SilverStreamingApplication-1.3}/setup.py +1 -1
- {SilverStreamingApplication-1.1 → SilverStreamingApplication-1.3}/SilverStreamingApplication.egg-info/SOURCES.txt +0 -0
- {SilverStreamingApplication-1.1 → SilverStreamingApplication-1.3}/SilverStreamingApplication.egg-info/dependency_links.txt +0 -0
- {SilverStreamingApplication-1.1 → SilverStreamingApplication-1.3}/SilverStreamingApplication.egg-info/top_level.txt +0 -0
- {SilverStreamingApplication-1.1 → SilverStreamingApplication-1.3}/com/__init__.py +0 -0
- {SilverStreamingApplication-1.1 → SilverStreamingApplication-1.3}/com/phida/__init__.py +0 -0
- {SilverStreamingApplication-1.1 → SilverStreamingApplication-1.3}/com/phida/main/Maintenance.py +0 -0
- {SilverStreamingApplication-1.1 → SilverStreamingApplication-1.3}/com/phida/main/Operations.py +0 -0
- {SilverStreamingApplication-1.1 → SilverStreamingApplication-1.3}/com/phida/main/PartitionAnalyzer.py +0 -0
- {SilverStreamingApplication-1.1 → SilverStreamingApplication-1.3}/com/phida/main/PerfAnalyzer.py +0 -0
- {SilverStreamingApplication-1.1 → SilverStreamingApplication-1.3}/com/phida/main/__init__.py +0 -0
- {SilverStreamingApplication-1.1 → SilverStreamingApplication-1.3}/com/phida/main/logging.py +0 -0
- {SilverStreamingApplication-1.1 → SilverStreamingApplication-1.3}/com/phida/main/sparksession.py +0 -0
- {SilverStreamingApplication-1.1 → SilverStreamingApplication-1.3}/com/phida/main/utils.py +0 -0
- {SilverStreamingApplication-1.1 → SilverStreamingApplication-1.3}/com/phida/main/utilsDatabricksAPI.py +0 -0
- {SilverStreamingApplication-1.1 → SilverStreamingApplication-1.3}/com/phida/tests/OperationsTest.py +0 -0
- {SilverStreamingApplication-1.1 → SilverStreamingApplication-1.3}/com/phida/tests/__init__.py +0 -0
- {SilverStreamingApplication-1.1 → SilverStreamingApplication-1.3}/com/phida/tests/main_test.py +0 -0
- {SilverStreamingApplication-1.1 → SilverStreamingApplication-1.3}/com/phida/tests/utils_test.py +0 -0
- {SilverStreamingApplication-1.1 → SilverStreamingApplication-1.3}/setup.cfg +0 -0
{SilverStreamingApplication-1.1 → SilverStreamingApplication-1.3}/com/phida/main/SilverMerge.py
RENAMED
|
@@ -2,10 +2,10 @@ from com.phida.main.sparksession import spark, logger
|
|
|
2
2
|
from com.phida.main.Operations import tableExists, addDerivedColumns, createDeltaTable, alterDeltaTable, \
|
|
3
3
|
dropColumns, getDerivedColumnsList, schemaDiff, getKeyCols, buildJoinCondition, buildColumnsDict, hiveDDL, schemaDataTypeDiff
|
|
4
4
|
from com.phida.main.utils import pathExists, convertStrToList
|
|
5
|
-
from pyspark.sql.functions import row_number, col, broadcast
|
|
5
|
+
from pyspark.sql.functions import row_number, col, broadcast,expr
|
|
6
6
|
from pyspark.sql.window import Window
|
|
7
7
|
from delta.tables import DeltaTable
|
|
8
|
-
|
|
8
|
+
from pyspark.sql import DataFrame
|
|
9
9
|
|
|
10
10
|
class SilverMerge:
|
|
11
11
|
"""
|
|
@@ -24,6 +24,7 @@ class SilverMerge:
|
|
|
24
24
|
dropColumnStr: String - Columns to be dropped from source table df
|
|
25
25
|
pruneColumn: String - Column for applying the prune filter in the merge ON condition clause \
|
|
26
26
|
(to improve performance of the merge)
|
|
27
|
+
cluster_table_path: String - Path to the cluster table
|
|
27
28
|
|
|
28
29
|
methods:
|
|
29
30
|
silverCleansing
|
|
@@ -35,12 +36,12 @@ class SilverMerge:
|
|
|
35
36
|
from com.phida.SilverMerge import SilverMerge
|
|
36
37
|
silverMergeObj = SilverMerge(srcDatabaseName, srcTableName, tgtDatabaseName, tgtTableName,
|
|
37
38
|
tgtCheckpoint, tgtTablePath, tgtPartitionColumns, derivedColExpr,
|
|
38
|
-
triggerOnce, dropColumnStr, pruneColumn)
|
|
39
|
+
triggerOnce, dropColumnStr, pruneColumn, cluster_table_path)
|
|
39
40
|
|
|
40
41
|
"""
|
|
41
42
|
def __init__(self, srcDatabaseName, srcTableName, tgtDatabaseName, tgtTableName,
|
|
42
43
|
tgtCheckpoint, tgtTablePath, tgtPartitionColumns, derivedColExpr,
|
|
43
|
-
triggerOnce, dropColumnStr, pruneColumn):
|
|
44
|
+
triggerOnce, dropColumnStr, pruneColumn, cluster_table_path):
|
|
44
45
|
"""
|
|
45
46
|
desc:
|
|
46
47
|
Initialize the required class variables
|
|
@@ -57,7 +58,7 @@ class SilverMerge:
|
|
|
57
58
|
triggerOnce: String - Whether continuous streaming or just once
|
|
58
59
|
dropColumnStr: String - Columns to be dropped from source table df
|
|
59
60
|
pruneColumn: String - Column to use for dynamic file pruning (future feature)
|
|
60
|
-
|
|
61
|
+
cluster_table_path: String - Path to the cluster table
|
|
61
62
|
"""
|
|
62
63
|
|
|
63
64
|
logger.info("phida_log: Initialising class variables")
|
|
@@ -73,6 +74,7 @@ class SilverMerge:
|
|
|
73
74
|
self.triggerOnce = triggerOnce
|
|
74
75
|
self.dropColumnStr = dropColumnStr
|
|
75
76
|
self.pruneColumn = pruneColumn
|
|
77
|
+
self.cluster_table_path = cluster_table_path
|
|
76
78
|
|
|
77
79
|
logger.info(f"phida_log: Check if source table {self.srcDatabaseName}.{self.srcTableName} exists")
|
|
78
80
|
|
|
@@ -202,6 +204,34 @@ class SilverMerge:
|
|
|
202
204
|
|
|
203
205
|
else:
|
|
204
206
|
logger.info(f"phida_log: There is no change in schema in silver")
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
def preprocess_dataframe(self, df: DataFrame, parent_keys: list) -> DataFrame:
|
|
210
|
+
|
|
211
|
+
"""Removes rows where all or any 'source_operation' values for a group are 8."""
|
|
212
|
+
|
|
213
|
+
grouped_df = df.groupBy(parent_keys).agg(
|
|
214
|
+
expr("bool_and(source_operation = 8)").alias("all_8"),
|
|
215
|
+
expr("bool_or(source_operation = 8)").alias("any_8")
|
|
216
|
+
)
|
|
217
|
+
|
|
218
|
+
return df.join(grouped_df, on=parent_keys, how="left").filter("NOT (all_8 OR any_8)")
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
def get_parent_keys(self, df: DataFrame, kernel_value: str, unpack_table_value: str) -> list:
|
|
222
|
+
|
|
223
|
+
"""Get the parent keys for the given kernel and unpack_table values"""
|
|
224
|
+
|
|
225
|
+
filtered_df = df.filter(
|
|
226
|
+
(col("kernel") == kernel_value) & (col("unpack_table") == unpack_table_value)
|
|
227
|
+
)
|
|
228
|
+
row = filtered_df.select("key_columns_for_pack_table", "key_columns_for_unpack_table").first()
|
|
229
|
+
pack_keys = set(row["key_columns_for_pack_table"].split(',')) if row["key_columns_for_pack_table"] else set()
|
|
230
|
+
unpack_keys = set(row["key_columns_for_unpack_table"].split(',')) if row["key_columns_for_unpack_table"] else set()
|
|
231
|
+
parent_keys = list(pack_keys & unpack_keys)
|
|
232
|
+
return parent_keys
|
|
233
|
+
|
|
234
|
+
|
|
205
235
|
|
|
206
236
|
def upsertToDelta(self, microBatchOutputDF, batchId):
|
|
207
237
|
"""
|
|
@@ -221,20 +251,35 @@ class SilverMerge:
|
|
|
221
251
|
tip:
|
|
222
252
|
N/A
|
|
223
253
|
"""
|
|
254
|
+
op_8_df = microBatchOutputDF.filter("source_operation = 8")
|
|
255
|
+
microBatchOutputDF = microBatchOutputDF.filter("source_operation in (0,1,2,3)")
|
|
256
|
+
microBatchOutputDF_8 = microBatchOutputDF.filter("source_operation in (0,1,2,3,8)")
|
|
257
|
+
tgtDeltaTable = DeltaTable.forName(spark, self.tgtDatabaseName + "." + self.tgtTableName)
|
|
258
|
+
|
|
259
|
+
if not op_8_df.isEmpty():
|
|
260
|
+
table_details = DeltaTable.forName(spark,self.cluster_table_path)
|
|
261
|
+
table_details_df = table_details.toDF()
|
|
262
|
+
parent_keys = self.get_parent_keys(table_details_df, self.srcDatabaseName, self.srcTableName)
|
|
263
|
+
parent_key_conditions = " AND ".join([f"t.{col} = s.{col}" for col in parent_keys])
|
|
264
|
+
if not tgtDeltaTable.toDF().isEmpty():
|
|
265
|
+
tgtDeltaTable.alias("t").merge(microBatchOutputDF_8.alias("s"), parent_key_conditions) \
|
|
266
|
+
.whenMatchedDelete() \
|
|
267
|
+
.execute()
|
|
268
|
+
microBatchOutputDF = self.preprocess_dataframe(microBatchOutputDF_8, parent_keys)
|
|
269
|
+
|
|
224
270
|
windowSpec = Window.partitionBy(self.keyColsList).orderBy(col("src_commit_time").desc(),
|
|
225
271
|
col("hvr_integ_key").desc())
|
|
226
272
|
|
|
227
273
|
microBatchOutputDF = microBatchOutputDF.withColumn("latest_record", row_number().over(windowSpec)).filter(
|
|
228
274
|
"latest_record == 1").drop("latest_record")
|
|
229
275
|
|
|
230
|
-
tgtDeltaTable = DeltaTable.forName(spark, self.tgtDatabaseName + "." + self.tgtTableName)
|
|
231
276
|
|
|
232
277
|
tgtDeltaTable.alias("t").merge(microBatchOutputDF.alias("s"), self.condition) \
|
|
233
|
-
.whenMatchedDelete("s.source_operation
|
|
234
|
-
.whenMatchedUpdate(condition="s.source_operation
|
|
235
|
-
.whenNotMatchedInsert(condition="s.source_operation
|
|
278
|
+
.whenMatchedDelete("s.source_operation in (0,3)") \
|
|
279
|
+
.whenMatchedUpdate(condition="s.source_operation not in (0,3)", set=self.columnsDict) \
|
|
280
|
+
.whenNotMatchedInsert(condition="s.source_operation not in (0,3)", values=self.columnsDict) \
|
|
236
281
|
.execute()
|
|
237
|
-
|
|
282
|
+
|
|
238
283
|
def streamIntoDeltaTarget(self):
|
|
239
284
|
"""
|
|
240
285
|
desc:
|
{SilverStreamingApplication-1.1 → SilverStreamingApplication-1.3}/com/phida/main/WorkflowBuilder.py
RENAMED
|
@@ -72,7 +72,7 @@ class WorkflowBuilder:
|
|
|
72
72
|
@staticmethod
|
|
73
73
|
def createTask(taskKey, jobClusterKey, notebookPath, srcDatabaseName, srcTableName, tgtDatabaseName, tgtTableName,
|
|
74
74
|
tgtCheckpoint, tgtTablePath, tgtPartitionColumns, derivedColExpr, triggerOnce, dropColumnStr,
|
|
75
|
-
pruneColumn, pythonWhlPath, library):
|
|
75
|
+
pruneColumn,cluster_table_path, pythonWhlPath, library):
|
|
76
76
|
"""
|
|
77
77
|
desc:
|
|
78
78
|
A method for creating the dict/json for a single task
|
|
@@ -93,6 +93,8 @@ class WorkflowBuilder:
|
|
|
93
93
|
dropColumnStr: String - Columns to be dropped from source table df
|
|
94
94
|
pruneColumn: String - Column for applying the prune filter in the merge ON condition clause \
|
|
95
95
|
(to improve performance of the merge)
|
|
96
|
+
cluster_table_path: String - The path of the table in the cluster
|
|
97
|
+
pythonWhlPath: String - Path of the python wheel file
|
|
96
98
|
library: String - Library to be installed for the job (with version number)
|
|
97
99
|
|
|
98
100
|
return:
|
|
@@ -130,7 +132,8 @@ class WorkflowBuilder:
|
|
|
130
132
|
"derived_col_expr": derivedColExpr,
|
|
131
133
|
"trigger_once": triggerOnce,
|
|
132
134
|
"prune_column": pruneColumn,
|
|
133
|
-
"drop_column_list": dropColumnStr
|
|
135
|
+
"drop_column_list": dropColumnStr,
|
|
136
|
+
"cluster_table_path": cluster_table_path
|
|
134
137
|
}
|
|
135
138
|
},
|
|
136
139
|
"timeout_seconds": timeout_seconds,
|
|
@@ -311,7 +314,7 @@ class WorkflowBuilder:
|
|
|
311
314
|
tgtTablePath = task['tgt_table_path']
|
|
312
315
|
triggerOnce = task['trigger_once']
|
|
313
316
|
dropColumnStr = task['drop_column_list']
|
|
314
|
-
|
|
317
|
+
|
|
315
318
|
try:
|
|
316
319
|
tgtPartitionColumns = task['tgt_partition_columns']
|
|
317
320
|
except:
|
|
@@ -326,11 +329,16 @@ class WorkflowBuilder:
|
|
|
326
329
|
pruneColumn = task['prune_column']
|
|
327
330
|
except:
|
|
328
331
|
pruneColumn = ""
|
|
332
|
+
|
|
333
|
+
try:
|
|
334
|
+
cluster_table_path = task['cluster_table_path']
|
|
335
|
+
except:
|
|
336
|
+
cluster_table_path = ""
|
|
329
337
|
|
|
330
338
|
taskTemp = self.createTask(taskKey, jobClusterKey, notebookPath, srcDatabaseName, srcTableName,
|
|
331
339
|
tgtDatabaseName, tgtTableName, tgtCheckpoint, tgtTablePath,
|
|
332
340
|
tgtPartitionColumns, derivedColExpr, triggerOnce, dropColumnStr,
|
|
333
|
-
pruneColumn, "", self.library)
|
|
341
|
+
pruneColumn,cluster_table_path, "", self.library)
|
|
334
342
|
|
|
335
343
|
tasks.append(taskTemp)
|
|
336
344
|
if jobId is None:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{SilverStreamingApplication-1.1 → SilverStreamingApplication-1.3}/com/phida/main/Maintenance.py
RENAMED
|
File without changes
|
{SilverStreamingApplication-1.1 → SilverStreamingApplication-1.3}/com/phida/main/Operations.py
RENAMED
|
File without changes
|
|
File without changes
|
{SilverStreamingApplication-1.1 → SilverStreamingApplication-1.3}/com/phida/main/PerfAnalyzer.py
RENAMED
|
File without changes
|
{SilverStreamingApplication-1.1 → SilverStreamingApplication-1.3}/com/phida/main/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{SilverStreamingApplication-1.1 → SilverStreamingApplication-1.3}/com/phida/main/sparksession.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{SilverStreamingApplication-1.1 → SilverStreamingApplication-1.3}/com/phida/tests/OperationsTest.py
RENAMED
|
File without changes
|
{SilverStreamingApplication-1.1 → SilverStreamingApplication-1.3}/com/phida/tests/__init__.py
RENAMED
|
File without changes
|
{SilverStreamingApplication-1.1 → SilverStreamingApplication-1.3}/com/phida/tests/main_test.py
RENAMED
|
File without changes
|
{SilverStreamingApplication-1.1 → SilverStreamingApplication-1.3}/com/phida/tests/utils_test.py
RENAMED
|
File without changes
|
|
File without changes
|