SilverStreamingApplication 1.2__tar.gz → 1.4__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 (26) hide show
  1. silverstreamingapplication-1.4/PKG-INFO +7 -0
  2. {SilverStreamingApplication-1.2 → silverstreamingapplication-1.4}/com/phida/main/SilverMerge.py +95 -11
  3. {SilverStreamingApplication-1.2 → silverstreamingapplication-1.4}/com/phida/main/WorkflowBuilder.py +26 -4
  4. {SilverStreamingApplication-1.2 → silverstreamingapplication-1.4}/setup.py +2 -2
  5. silverstreamingapplication-1.4/silverstreamingapplication.egg-info/PKG-INFO +7 -0
  6. {SilverStreamingApplication-1.2/SilverStreamingApplication.egg-info → silverstreamingapplication-1.4/silverstreamingapplication.egg-info}/SOURCES.txt +5 -7
  7. SilverStreamingApplication-1.2/PKG-INFO +0 -12
  8. SilverStreamingApplication-1.2/SilverStreamingApplication.egg-info/PKG-INFO +0 -12
  9. SilverStreamingApplication-1.2/com/phida/main/__init__.py +0 -0
  10. SilverStreamingApplication-1.2/com/phida/tests/__init__.py +0 -0
  11. {SilverStreamingApplication-1.2 → silverstreamingapplication-1.4}/com/phida/main/Maintenance.py +0 -0
  12. {SilverStreamingApplication-1.2 → silverstreamingapplication-1.4}/com/phida/main/Operations.py +0 -0
  13. {SilverStreamingApplication-1.2 → silverstreamingapplication-1.4}/com/phida/main/PartitionAnalyzer.py +0 -0
  14. {SilverStreamingApplication-1.2 → silverstreamingapplication-1.4}/com/phida/main/PerfAnalyzer.py +0 -0
  15. {SilverStreamingApplication-1.2/com → silverstreamingapplication-1.4/com/phida/main}/__init__.py +0 -0
  16. {SilverStreamingApplication-1.2 → silverstreamingapplication-1.4}/com/phida/main/logging.py +0 -0
  17. {SilverStreamingApplication-1.2 → silverstreamingapplication-1.4}/com/phida/main/sparksession.py +0 -0
  18. {SilverStreamingApplication-1.2 → silverstreamingapplication-1.4}/com/phida/main/utils.py +0 -0
  19. {SilverStreamingApplication-1.2 → silverstreamingapplication-1.4}/com/phida/main/utilsDatabricksAPI.py +0 -0
  20. {SilverStreamingApplication-1.2 → silverstreamingapplication-1.4}/com/phida/tests/OperationsTest.py +0 -0
  21. {SilverStreamingApplication-1.2/com/phida → silverstreamingapplication-1.4/com/phida/tests}/__init__.py +0 -0
  22. {SilverStreamingApplication-1.2 → silverstreamingapplication-1.4}/com/phida/tests/main_test.py +0 -0
  23. {SilverStreamingApplication-1.2 → silverstreamingapplication-1.4}/com/phida/tests/utils_test.py +0 -0
  24. {SilverStreamingApplication-1.2 → silverstreamingapplication-1.4}/setup.cfg +0 -0
  25. {SilverStreamingApplication-1.2/SilverStreamingApplication.egg-info → silverstreamingapplication-1.4/silverstreamingapplication.egg-info}/dependency_links.txt +0 -0
  26. {SilverStreamingApplication-1.2/SilverStreamingApplication.egg-info → silverstreamingapplication-1.4/silverstreamingapplication.egg-info}/top_level.txt +0 -0
@@ -0,0 +1,7 @@
1
+ Metadata-Version: 2.1
2
+ Name: silverstreamingapplication
3
+ Version: 1.4
4
+ Summary: initial version
5
+ Home-page:
6
+ Author:
7
+ Author-email:
@@ -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, max as spark_max
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,9 @@ 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
28
+ enable_delete_filter: String - Flag to enable/disable filtering of deleted records (default: 'N')
29
+ use_auto_loader: String - Flag to enable/disable use of autoloader for reading source table (default: 'N')
27
30
 
28
31
  methods:
29
32
  silverCleansing
@@ -35,12 +38,12 @@ class SilverMerge:
35
38
  from com.phida.SilverMerge import SilverMerge
36
39
  silverMergeObj = SilverMerge(srcDatabaseName, srcTableName, tgtDatabaseName, tgtTableName,
37
40
  tgtCheckpoint, tgtTablePath, tgtPartitionColumns, derivedColExpr,
38
- triggerOnce, dropColumnStr, pruneColumn)
41
+ triggerOnce, dropColumnStr, pruneColumn, cluster_table_path, enable_delete_filter, use_auto_loader)
39
42
 
40
43
  """
41
44
  def __init__(self, srcDatabaseName, srcTableName, tgtDatabaseName, tgtTableName,
42
45
  tgtCheckpoint, tgtTablePath, tgtPartitionColumns, derivedColExpr,
43
- triggerOnce, dropColumnStr, pruneColumn):
46
+ triggerOnce, dropColumnStr, pruneColumn, cluster_table_path, enable_delete_filter, use_auto_loader):
44
47
  """
45
48
  desc:
46
49
  Initialize the required class variables
@@ -57,7 +60,9 @@ class SilverMerge:
57
60
  triggerOnce: String - Whether continuous streaming or just once
58
61
  dropColumnStr: String - Columns to be dropped from source table df
59
62
  pruneColumn: String - Column to use for dynamic file pruning (future feature)
60
-
63
+ cluster_table_path: String - Path to the cluster table
64
+ enable_delete_filter: String - Flag to enable/disable filtering of deleted records (default: 'N')
65
+ use_auto_loader: String - Flag to enable/disable use of autoloader for reading source table (default: 'N')
61
66
  """
62
67
 
63
68
  logger.info("phida_log: Initialising class variables")
@@ -73,6 +78,9 @@ class SilverMerge:
73
78
  self.triggerOnce = triggerOnce
74
79
  self.dropColumnStr = dropColumnStr
75
80
  self.pruneColumn = pruneColumn
81
+ self.cluster_table_path = cluster_table_path
82
+ self.enable_delete_filter = enable_delete_filter.strip().upper() if enable_delete_filter else 'N'
83
+ self.use_auto_loader = use_auto_loader.strip().upper() if use_auto_loader and use_auto_loader.strip().upper() == 'Y' else 'N'
76
84
 
77
85
  logger.info(f"phida_log: Check if source table {self.srcDatabaseName}.{self.srcTableName} exists")
78
86
 
@@ -82,7 +90,11 @@ class SilverMerge:
82
90
 
83
91
  logger.info(f"phida_log: initialising derived class variables")
84
92
 
85
- self.srcDF = spark.readStream.table(self.srcDatabaseName + "." + self.srcTableName)
93
+ if self.use_auto_loader == 'N':
94
+ self.srcDF = spark.readStream.table(self.srcDatabaseName + "." + self.srcTableName)
95
+ elif self.use_auto_loader == 'Y':
96
+ src_table_path = spark.sql(f"DESCRIBE DETAIL {self.srcDatabaseName}.{self.srcTableName}").collect()[0]['location']
97
+ self.srcDF = spark.readStream.format("cloudFiles").option("cloudFiles.format", "parquet").option("cloudFiles.schemaLocation", src_table_path + "/_cloudfiles/_schemas").load(src_table_path)
86
98
 
87
99
  self.keyCols = getKeyCols(self.srcDatabaseName, self.srcTableName)
88
100
 
@@ -203,6 +215,64 @@ class SilverMerge:
203
215
  else:
204
216
  logger.info(f"phida_log: There is no change in schema in silver")
205
217
 
218
+ def filter_deleted_records(self, microBatchOutputDF):
219
+ """
220
+ Filters out records from microBatchOutputDF that have been marked as deleted in the Bronze table
221
+ within the last 4 hours based on hvr_integ_key.
222
+ """
223
+
224
+ if microBatchOutputDF.isEmpty():
225
+ return microBatchOutputDF
226
+
227
+ filtered_table_name = f"{self.srcDatabaseName}.{self.srcTableName}_filtered"
228
+
229
+ if not tableExists(self.srcDatabaseName, f"{self.srcTableName}_filtered"):
230
+ return microBatchOutputDF
231
+
232
+ delete_records = spark.read.table(filtered_table_name).filter(col("source_operation") == 0)
233
+
234
+ if delete_records.isEmpty():
235
+ return microBatchOutputDF
236
+
237
+ delete_keys_df = (delete_records.groupBy(self.keyColsList).agg(spark_max(col("hvr_integ_key")).alias("delete_hvr_integ_key")))
238
+
239
+ joined_df = microBatchOutputDF.join(broadcast(delete_keys_df), on=self.keyColsList, how="left")
240
+
241
+ filtered_df = (joined_df.filter(
242
+ (col("delete_hvr_integ_key").isNull()) |
243
+ (col("hvr_integ_key") > col("delete_hvr_integ_key"))
244
+ )
245
+ .drop("delete_hvr_integ_key"))
246
+
247
+ return filtered_df
248
+
249
+ def preprocess_dataframe(self, df: DataFrame, parent_keys: list) -> DataFrame:
250
+
251
+ """Removes rows where all or any 'source_operation' values for a group are 8."""
252
+
253
+ grouped_df = df.groupBy(parent_keys).agg(
254
+ expr("bool_and(source_operation = 8)").alias("all_8"),
255
+ expr("bool_or(source_operation = 8)").alias("any_8")
256
+ )
257
+
258
+ return df.join(grouped_df, on=parent_keys, how="left").filter("NOT (all_8 OR any_8)")
259
+
260
+
261
+ def get_parent_keys(self, df: DataFrame, kernel_value: str, unpack_table_value: str) -> list:
262
+
263
+ """Get the parent keys for the given kernel and unpack_table values"""
264
+
265
+ filtered_df = df.filter(
266
+ (col("kernel") == kernel_value) & (col("unpack_table") == unpack_table_value)
267
+ )
268
+ row = filtered_df.select("key_columns_for_pack_table", "key_columns_for_unpack_table").first()
269
+ pack_keys = set(row["key_columns_for_pack_table"].split(',')) if row["key_columns_for_pack_table"] else set()
270
+ unpack_keys = set(row["key_columns_for_unpack_table"].split(',')) if row["key_columns_for_unpack_table"] else set()
271
+ parent_keys = list(pack_keys & unpack_keys)
272
+ return parent_keys
273
+
274
+
275
+
206
276
  def upsertToDelta(self, microBatchOutputDF, batchId):
207
277
  """
208
278
  desc:
@@ -221,16 +291,30 @@ class SilverMerge:
221
291
  tip:
222
292
  N/A
223
293
  """
224
-
294
+ op_8_df = microBatchOutputDF.filter("source_operation = 8")
225
295
  microBatchOutputDF = microBatchOutputDF.filter("source_operation in (0,1,2,3)")
226
-
227
- windowSpec = Window.partitionBy(self.keyColsList).orderBy(col("src_commit_time").desc(),
228
- col("hvr_integ_key").desc())
296
+ microBatchOutputDF_8 = microBatchOutputDF.filter("source_operation in (0,1,2,3,8)")
297
+ tgtDeltaTable = DeltaTable.forName(spark, self.tgtDatabaseName + "." + self.tgtTableName)
298
+
299
+ if self.cluster_table_path:
300
+ if not op_8_df.isEmpty():
301
+ table_details = DeltaTable.forName(spark, self.cluster_table_path)
302
+ table_details_df = table_details.toDF()
303
+ parent_keys = self.get_parent_keys(table_details_df, self.srcDatabaseName, self.srcTableName)
304
+ parent_key_conditions = " AND ".join([f"t.{col} = s.{col}" for col in parent_keys])
305
+ if not tgtDeltaTable.toDF().isEmpty():
306
+ tgtDeltaTable.alias("t").merge(microBatchOutputDF_8.alias("s"), parent_key_conditions) \
307
+ .whenMatchedDelete() \
308
+ .execute()
309
+ microBatchOutputDF = self.preprocess_dataframe(microBatchOutputDF_8, parent_keys)
310
+
311
+ windowSpec = Window.partitionBy(self.keyColsList).orderBy(col("hvr_integ_key").desc())
229
312
 
230
313
  microBatchOutputDF = microBatchOutputDF.withColumn("latest_record", row_number().over(windowSpec)).filter(
231
314
  "latest_record == 1").drop("latest_record")
232
315
 
233
- tgtDeltaTable = DeltaTable.forName(spark, self.tgtDatabaseName + "." + self.tgtTableName)
316
+ if self.enable_delete_filter == 'Y':
317
+ microBatchOutputDF = self.filter_deleted_records(microBatchOutputDF)
234
318
 
235
319
  tgtDeltaTable.alias("t").merge(microBatchOutputDF.alias("s"), self.condition) \
236
320
  .whenMatchedDelete("s.source_operation in (0,3)") \
@@ -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, enable_delete_filter, enable_autoloader, library):
76
76
  """
77
77
  desc:
78
78
  A method for creating the dict/json for a single task
@@ -93,6 +93,10 @@ 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
+ enable_delete_filter: String - Flag to enable/disable filtering of deleted records (default: 'N')
98
+ enable_autoloader: String - Flag to enable/disable autoloader (default: 'N')
99
+ pythonWhlPath: String - Path of the python wheel file
96
100
  library: String - Library to be installed for the job (with version number)
97
101
 
98
102
  return:
@@ -130,7 +134,10 @@ class WorkflowBuilder:
130
134
  "derived_col_expr": derivedColExpr,
131
135
  "trigger_once": triggerOnce,
132
136
  "prune_column": pruneColumn,
133
- "drop_column_list": dropColumnStr
137
+ "drop_column_list": dropColumnStr,
138
+ "cluster_table_path": cluster_table_path,
139
+ "enable_delete_filter": str(enable_delete_filter),
140
+ "enable_autoloader": enable_autoloader
134
141
  }
135
142
  },
136
143
  "timeout_seconds": timeout_seconds,
@@ -311,7 +318,7 @@ class WorkflowBuilder:
311
318
  tgtTablePath = task['tgt_table_path']
312
319
  triggerOnce = task['trigger_once']
313
320
  dropColumnStr = task['drop_column_list']
314
-
321
+
315
322
  try:
316
323
  tgtPartitionColumns = task['tgt_partition_columns']
317
324
  except:
@@ -326,11 +333,26 @@ class WorkflowBuilder:
326
333
  pruneColumn = task['prune_column']
327
334
  except:
328
335
  pruneColumn = ""
336
+
337
+ try:
338
+ cluster_table_path = task['cluster_table_path']
339
+ except:
340
+ cluster_table_path = ""
341
+
342
+ try:
343
+ enable_delete_filter = task['enable_delete_filter']
344
+ except:
345
+ enable_delete_filter = ""
346
+
347
+ try:
348
+ enable_autoloader = task['enable_autoloader']
349
+ except:
350
+ enable_autoloader = ""
329
351
 
330
352
  taskTemp = self.createTask(taskKey, jobClusterKey, notebookPath, srcDatabaseName, srcTableName,
331
353
  tgtDatabaseName, tgtTableName, tgtCheckpoint, tgtTablePath,
332
354
  tgtPartitionColumns, derivedColExpr, triggerOnce, dropColumnStr,
333
- pruneColumn, "", self.library)
355
+ pruneColumn, cluster_table_path, enable_delete_filter, enable_autoloader, self.library)
334
356
 
335
357
  tasks.append(taskTemp)
336
358
  if jobId is None:
@@ -1,8 +1,8 @@
1
1
  from setuptools import setup
2
2
 
3
3
  setup(
4
- name='SilverStreamingApplication',
5
- version='1.2',
4
+ name='silverstreamingapplication',
5
+ version='1.4',
6
6
  packages=['com.phida.main', 'com.phida.tests'],
7
7
  url='',
8
8
  license='',
@@ -0,0 +1,7 @@
1
+ Metadata-Version: 2.1
2
+ Name: silverstreamingapplication
3
+ Version: 1.4
4
+ Summary: initial version
5
+ Home-page:
6
+ Author:
7
+ Author-email:
@@ -1,10 +1,4 @@
1
1
  setup.py
2
- SilverStreamingApplication.egg-info/PKG-INFO
3
- SilverStreamingApplication.egg-info/SOURCES.txt
4
- SilverStreamingApplication.egg-info/dependency_links.txt
5
- SilverStreamingApplication.egg-info/top_level.txt
6
- com/__init__.py
7
- com/phida/__init__.py
8
2
  com/phida/main/Maintenance.py
9
3
  com/phida/main/Operations.py
10
4
  com/phida/main/PartitionAnalyzer.py
@@ -19,4 +13,8 @@ com/phida/main/utilsDatabricksAPI.py
19
13
  com/phida/tests/OperationsTest.py
20
14
  com/phida/tests/__init__.py
21
15
  com/phida/tests/main_test.py
22
- com/phida/tests/utils_test.py
16
+ com/phida/tests/utils_test.py
17
+ silverstreamingapplication.egg-info/PKG-INFO
18
+ silverstreamingapplication.egg-info/SOURCES.txt
19
+ silverstreamingapplication.egg-info/dependency_links.txt
20
+ silverstreamingapplication.egg-info/top_level.txt
@@ -1,12 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: SilverStreamingApplication
3
- Version: 1.2
4
- Summary: initial version
5
- Home-page: UNKNOWN
6
- Author:
7
- Author-email:
8
- License: UNKNOWN
9
- Platform: UNKNOWN
10
-
11
- UNKNOWN
12
-
@@ -1,12 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: SilverStreamingApplication
3
- Version: 1.2
4
- Summary: initial version
5
- Home-page: UNKNOWN
6
- Author:
7
- Author-email:
8
- License: UNKNOWN
9
- Platform: UNKNOWN
10
-
11
- UNKNOWN
12
-
File without changes