-
Notifications
You must be signed in to change notification settings - Fork 128
Demo for Spark Structured Streaming #518
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 3 commits
Commits
Show all changes
18 commits
Select commit
Hold shift + click to select a range
86f79c3
Issue#489 - Feature - DQX Spark Structured Streaming Demo
dinbab1984 cb21e46
Issue#489 - Feature - DQX Spark Structured Streaming Demo
dinbab1984 2ca7150
Issue#489 - Feature - DQX Spark Structured Streaming Demo
dinbab1984 33de3be
Merge branch 'main' into feature/streaming_demo
mwojtyczka bfce864
Update docs/dqx/docs/demos.mdx
mwojtyczka c05b22d
Merge branch 'main' into feature/streaming_demo
mwojtyczka 9cfcbb8
Issue#489 - Feature - DQX Spark Structured Streaming Demo
dinbab1984 5439a2a
Update demos/dqx_streaming_demo_native.py
mwojtyczka 284f8ab
Update demos/dqx_streaming_demo_native.py
mwojtyczka 5a4096e
Update demos/dqx_streaming_demo_native.py
mwojtyczka b69dc60
Update demos/dqx_streaming_demo_native.py
mwojtyczka 5289244
Update demos/dqx_streaming_demo_native.py
mwojtyczka 20dc407
Update demos/dqx_streaming_demo_diy.py
mwojtyczka 4235d25
Update docs/dqx/docs/demos.mdx
mwojtyczka 4283282
Update docs/dqx/docs/demos.mdx
mwojtyczka c8c073e
updated docs
mwojtyczka e6bad71
test
mwojtyczka 1551e34
test
mwojtyczka File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,214 @@ | ||
| # Databricks notebook source | ||
| # MAGIC | ||
| # MAGIC %md | ||
| # MAGIC ### Environment Setup for DQX with Structured Streaming | ||
| # MAGIC | ||
| # MAGIC #### 1\. Library Installation | ||
| # MAGIC | ||
| # MAGIC **Option A — Notebook-scoped installation** | ||
| # MAGIC | ||
| # MAGIC - Use notebook-scoped pip installs, which take effect only for the current interactive notebook session. | ||
| # MAGIC | ||
| # MAGIC ```py | ||
| # MAGIC # Install DQX library in the current notebook session | ||
| # MAGIC # Run this cell before any imports from databricks-labs-dqx | ||
| # MAGIC | ||
| # MAGIC %pip install databricks-labs-dqx | ||
| # MAGIC ``` | ||
| # MAGIC | ||
| # MAGIC - If you are using a cluster that was running prior to this install, you may need to restart the Python process for the changes to take full effect: | ||
| # MAGIC | ||
| # MAGIC ```py | ||
| # MAGIC # Optional: Force restart of the Python process if required by your environment | ||
| # MAGIC dbutils.library.restartPython() | ||
| # MAGIC ``` | ||
| # MAGIC | ||
| # MAGIC **Option B — Cluster-scoped installation (recommended for production streaming jobs)** | ||
| # MAGIC | ||
| # MAGIC - Install the DQX library to your cluster via the Databricks Libraries UI or by specifying it as a PyPI library dependency during cluster creation. | ||
| # MAGIC - This ensures the package is available for all jobs or notebooks attached to the cluster, including those running streaming workloads. | ||
| # MAGIC - The syntax for specifying the package is: | ||
| # MAGIC - Library Source: PyPI | ||
| # MAGIC - Package: `databricks-labs-dqx` | ||
| # MAGIC | ||
|
|
||
| # COMMAND ---------- | ||
|
|
||
| # MAGIC %md | ||
| # MAGIC ### Install DQX as Library <br> | ||
| # MAGIC For this demo, we will install DQX as library | ||
| # MAGIC | ||
|
|
||
| # COMMAND ---------- | ||
|
|
||
| dbutils.widgets.text("test_library_ref", "", "Test Library Ref") | ||
|
|
||
| if dbutils.widgets.get("test_library_ref") != "": | ||
| %pip install '{dbutils.widgets.get("test_library_ref")}' | ||
| else: | ||
| %pip install databricks-labs-dqx | ||
|
|
||
| %restart_python | ||
|
|
||
| # COMMAND ---------- | ||
|
|
||
| # MAGIC %md | ||
| # MAGIC ### Bronze Stream | ||
| # MAGIC | ||
| # MAGIC This cell reads the NYC Taxi 2019 dataset from a Delta table as a streaming DataFrame, which will be used as the input for downstream data quality checks and transformations. | ||
|
|
||
| # COMMAND ---------- | ||
|
|
||
| bronze_stream = ( | ||
| spark.readStream | ||
| .format("delta") | ||
| .load("/databricks-datasets/delta-sharing/samples/nyctaxi_2019") | ||
| ) | ||
|
|
||
| # COMMAND ---------- | ||
|
|
||
| # MAGIC %md | ||
| # MAGIC ### Define Data Quality Checks | ||
| # MAGIC | ||
| # MAGIC This cell defines a set of data quality checks using YAML syntax. The checks are designed to validate key columns in the NYC Taxi dataset, such as `vendor_id`, `pickup_datetime`, `dropoff_datetime`, `passenger_count`, and `trip_distance`. Each check specifies a function, its arguments, a name, and a criticality level (error or warn). These checks will be used by the DQEngine to enforce data quality rules on the streaming data. | ||
|
|
||
| # COMMAND ---------- | ||
|
|
||
| # Define Data Quality checks | ||
| import yaml | ||
|
|
||
|
|
||
| checks = yaml.safe_load(""" | ||
| - check: | ||
| function: is_not_null | ||
| arguments: | ||
| column: vendor_id | ||
| name: vendor_id_is_null | ||
| criticality: error | ||
| - check: | ||
| function: is_not_null_and_not_empty | ||
| arguments: | ||
| column: vendor_id | ||
| trim_strings: true | ||
| name: vendor_id_is_null_or_empty | ||
| criticality: error | ||
|
|
||
| - check: | ||
| function: is_not_null | ||
| arguments: | ||
| column: pickup_datetime | ||
| name: pickup_datetime_is_null | ||
| criticality: error | ||
| - check: | ||
| function: is_not_in_future | ||
| arguments: | ||
| column: pickup_datetime | ||
| name: pickup_datetime_isnt_in_range | ||
| criticality: warn | ||
|
|
||
| - check: | ||
| function: is_not_in_future | ||
| arguments: | ||
| column: pickup_datetime | ||
|
mwojtyczka marked this conversation as resolved.
|
||
| name: pickup_datetime_not_in_future | ||
| criticality: warn | ||
| - check: | ||
| function: is_not_in_future | ||
| arguments: | ||
| column: dropoff_datetime | ||
| name: dropoff_datetime_not_in_future | ||
| criticality: warn | ||
| - check: | ||
| function: is_not_null | ||
| arguments: | ||
| column: passenger_count | ||
| name: passenger_count_is_null | ||
| criticality: error | ||
| - check: | ||
| function: is_in_range | ||
| arguments: | ||
| column: passenger_count | ||
| min_limit: 0 | ||
| max_limit: 6 | ||
| name: passenger_incorrect_count | ||
| criticality: warn | ||
| - check: | ||
| function: is_not_null | ||
| arguments: | ||
| column: trip_distance | ||
| name: trip_distance_is_null | ||
| criticality: error | ||
| """) | ||
|
|
||
| # COMMAND ---------- | ||
|
|
||
| # MAGIC %md | ||
| # MAGIC ### Inputs | ||
| # MAGIC - Checkpoint and table locations are set via widgets | ||
|
|
||
| # COMMAND ---------- | ||
|
|
||
| dbutils.widgets.text("silver_checkpoint", "/tmp/dq/structured/bronze_to_silver_checkpoint") | ||
| dbutils.widgets.text("quarantine_checkpoint", "/tmp/dq/structured/bronze_to_quarantine_checkpoint") | ||
| dbutils.widgets.text("silver_table", "/tmp/dq/structured/silver_table") | ||
|
mwojtyczka marked this conversation as resolved.
|
||
| dbutils.widgets.text("quarantine_table", "/tmp/dq/structured/quarantine_table") | ||
|
mwojtyczka marked this conversation as resolved.
|
||
|
|
||
| # COMMAND ---------- | ||
|
|
||
| silver_checkpoint = dbutils.widgets.get("silver_checkpoint") | ||
| quarantine_checkpoint = dbutils.widgets.get("quarantine_checkpoint") | ||
| silver_table = dbutils.widgets.get("silver_table") | ||
| quarantine_table = dbutils.widgets.get("quarantine_table") | ||
|
|
||
| # COMMAND ---------- | ||
|
|
||
| # MAGIC %md | ||
| # MAGIC ### Apply data quality checks and split the bronze stream into silver and quarantine DataFrames | ||
|
|
||
| # COMMAND ---------- | ||
|
|
||
| from databricks.labs.dqx.engine import DQEngine | ||
| from databricks.sdk import WorkspaceClient | ||
| from pyspark.sql import DataFrame | ||
|
|
||
| dq_engine = DQEngine(WorkspaceClient()) | ||
|
|
||
| def apply_data_quality_and_split(df: DataFrame): | ||
| return dq_engine.apply_checks_by_metadata_and_split(df, checks) | ||
|
|
||
| silver_df, quarantine_df = apply_data_quality_and_split(bronze_stream) | ||
|
mwojtyczka marked this conversation as resolved.
Outdated
|
||
|
|
||
| # COMMAND ---------- | ||
|
|
||
| # MAGIC %md | ||
| # MAGIC ### Write streaming DataFrames to Delta tables with checkpointing | ||
|
|
||
| # COMMAND ---------- | ||
|
|
||
| PATH_PREFIXES = ("/", "dbfs:/", "s3://", "abfss://", "gs://") | ||
|
|
||
| def write_stream(df, checkpoint_location, target): | ||
| writer = ( | ||
| df.writeStream | ||
| .format("delta") | ||
| .outputMode("append") | ||
| .option("checkpointLocation", checkpoint_location) | ||
| .trigger(availableNow=True) | ||
| ) | ||
| if target.startswith(PATH_PREFIXES): | ||
| return writer.start(target) | ||
| else: | ||
| return writer.toTable(target) | ||
|
|
||
| silver_query = write_stream(silver_df, silver_checkpoint, silver_table) | ||
| quarantine_query = write_stream(quarantine_df, quarantine_checkpoint, quarantine_table) | ||
|
mwojtyczka marked this conversation as resolved.
|
||
|
|
||
| # COMMAND ---------- | ||
|
|
||
| # MAGIC %md | ||
| # MAGIC ### Wait for the streams to finish or keep them running for interactive sessions if required | ||
|
|
||
| # COMMAND ---------- | ||
|
|
||
| silver_query.awaitTermination() | ||
| quarantine_query.awaitTermination() | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.