|
100 | 100 | } |
101 | 101 | } |
102 | 102 |
|
| 103 | +SLOW_VIEW_NAME = f"view_{DAG_ID}_{ENV_ID}_slow".replace("-", "_") |
| 104 | + |
| 105 | +# The JavaScript UDF spins for a fixed number of iterations per row, which keeps a query over the view |
| 106 | +# RUNNING for tens of seconds, i.e. across several poll intervals of the deferrable check operators |
| 107 | +# (#73981). `CURRENT_TIMESTAMP()` makes the view non-deterministic, so BigQuery never serves a repeated |
| 108 | +# check from the query cache. Nothing here scans more than the two-row table, so the jobs are billed at |
| 109 | +# the 10 MB minimum. |
| 110 | +CREATE_SLOW_VIEW_QUERY = f""" |
| 111 | +CREATE OR REPLACE FUNCTION `{DATASET_NAME}.slow_ds`(ds STRING) RETURNS STRING LANGUAGE js AS r''' |
| 112 | + let acc = 0; |
| 113 | + for (let i = 0; i < 500000000; i++) {{ |
| 114 | + acc = (acc * 31 + i) % 1000003; |
| 115 | + }} |
| 116 | + return acc >= 0 ? ds : null; |
| 117 | +'''; |
| 118 | +CREATE OR REPLACE VIEW `{DATASET_NAME}.{SLOW_VIEW_NAME}` AS |
| 119 | + SELECT value, name, `{DATASET_NAME}.slow_ds`(ds) AS ds |
| 120 | + FROM `{DATASET_NAME}.{TABLE_NAME_1}` |
| 121 | + WHERE CURRENT_TIMESTAMP() IS NOT NULL; |
| 122 | +""" |
103 | 123 |
|
104 | 124 | default_args = { |
105 | 125 | "execution_timeout": timedelta(hours=6), |
|
262 | 282 | deferrable=True, |
263 | 283 | ) |
264 | 284 |
|
| 285 | + create_slow_view = BigQueryInsertJobOperator( |
| 286 | + task_id="create_slow_view", |
| 287 | + configuration={"query": {"query": CREATE_SLOW_VIEW_QUERY, "useLegacySql": False}}, |
| 288 | + location=LOCATION, |
| 289 | + ) |
| 290 | + |
| 291 | + check_value_long_running = BigQueryValueCheckOperator( |
| 292 | + task_id="check_value_long_running", |
| 293 | + sql=f"SELECT COUNT(*) FROM {DATASET_NAME}.{SLOW_VIEW_NAME} WHERE ds IS NOT NULL", |
| 294 | + pass_value=2, |
| 295 | + use_legacy_sql=False, |
| 296 | + location=LOCATION, |
| 297 | + deferrable=True, |
| 298 | + ) |
| 299 | + |
| 300 | + check_interval_long_running = BigQueryIntervalCheckOperator( |
| 301 | + task_id="check_interval_long_running", |
| 302 | + table=f"{DATASET_NAME}.{SLOW_VIEW_NAME}", |
| 303 | + days_back=1, |
| 304 | + metrics_thresholds={"COUNT(*)": 1.5}, |
| 305 | + use_legacy_sql=False, |
| 306 | + location=LOCATION, |
| 307 | + deferrable=True, |
| 308 | + ) |
| 309 | + |
265 | 310 | check_openlineage_events = OpenLineageTestOperator( |
266 | 311 | task_id="check_openlineage_events", |
267 | 312 | file_path=str(Path(__file__).parent / "resources" / "openlineage" / "bigquery_queries_async.json"), |
|
272 | 317 | insert_query_job >> get_data >> get_data_result |
273 | 318 | insert_query_job >> execute_query_save >> bigquery_execute_multi_query |
274 | 319 | insert_query_job >> execute_long_running_query >> check_value >> check_interval |
275 | | - [check_count, check_interval, bigquery_execute_multi_query, get_data_result] >> delete_dataset |
| 320 | + insert_query_job >> create_slow_view >> check_value_long_running >> check_interval_long_running |
| 321 | + [ |
| 322 | + check_count, |
| 323 | + check_interval, |
| 324 | + check_interval_long_running, |
| 325 | + bigquery_execute_multi_query, |
| 326 | + get_data_result, |
| 327 | + ] >> delete_dataset |
276 | 328 | delete_dataset >> check_openlineage_events |
277 | 329 |
|
278 | 330 | from tests_common.test_utils.watcher import watcher |
|
0 commit comments