Skip to content

Commit 02cca86

Browse files
Job state (lifecycle management) (#77)
1 parent 1334cd4 commit 02cca86

File tree

7 files changed

+51
-15
lines changed

7 files changed

+51
-15
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
## [Unreleased]
44

5+
- Handling job_state (running, suspended)
6+
57
## [1.3.10] - 2024-03-06
68

79
- Handling flink job upgrade_mode (savepoint, stateless)

dbt/adapters/flink/handler.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
QueryHints,
1010
QueryHintsParser,
1111
QueryMode,
12+
UpgradeMode,
13+
JobState,
1214
)
1315

1416
from flink.sqlgateway.client import FlinkSqlGatewayClient
@@ -103,25 +105,24 @@ def execute(self, sql: str, bindings: Optional[Sequence[Any]] = None) -> None:
103105
sql = sql.format(*[self._convert_binding(binding) for binding in bindings])
104106
self.last_query_hints: QueryHints = QueryHintsParser.parse(sql)
105107
execution_config = self.last_query_hints.execution_config
106-
start_from_savepoint = False
107108
if execution_config:
108109
if not self.last_query_hints.test_query:
109-
with_savepoint = self.last_query_hints.upgrade_mode == "savepoint"
110+
with_savepoint = self.last_query_hints.upgrade_mode == UpgradeMode.SAVEPOINT
110111
savepoint_path = FlinkJobManager(self.session).stop_job(
111112
execution_config, with_savepoint
112113
)
113114
if savepoint_path:
114115
logger.debug("Savepoint path {}", savepoint_path)
115116
execution_config[ExecutionConfig.SAVEPOINT_PATH] = savepoint_path
116-
start_from_savepoint = True
117-
if not start_from_savepoint:
118-
logger.debug("Job starting without savepoint")
119-
execution_config.pop(ExecutionConfig.SAVEPOINT_PATH, None)
120117

121118
if self.last_query_hints.drop_statement:
122119
logger.debug("Executing drop statement: {}", self.last_query_hints.drop_statement)
123120
FlinkCursor(self.session).execute(self.last_query_hints.drop_statement)
124121

122+
if JobState.SUSPENDED == self.last_query_hints.job_state:
123+
logger.info("Job suspended")
124+
return
125+
125126
self._set_query_mode()
126127
logger.info("Executing statement:\n{}\nExecution config:\n{}", sql, execution_config)
127128
operation_handle = FlinkSqlGatewayClient.execute_statement(

dbt/adapters/flink/query_hints_parser.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,16 @@ class QueryMode(Enum):
88
STREAMING = "streaming"
99

1010

11+
class UpgradeMode(Enum):
12+
SAVEPOINT = "savepoint"
13+
STATELESS = "stateless"
14+
15+
16+
class JobState(Enum):
17+
RUNNING = "running"
18+
SUSPENDED = "suspended"
19+
20+
1121
class QueryHints:
1222
fetch_max: Optional[int] = None
1323
fetch_timeout_ms: Optional[int] = None
@@ -36,8 +46,10 @@ def __init__(self, hints=None):
3646
self.execution_config[key_val[0]] = key_val[1]
3747
if "drop_statement" in hints:
3848
self.drop_statement = hints["drop_statement"]
39-
if "upgrade_mode" in hints:
40-
self.upgrade_mode = hints["upgrade_mode"]
49+
self.upgrade_mode = UpgradeMode(
50+
hints.get("upgrade_mode", UpgradeMode.STATELESS.value).lower()
51+
)
52+
self.job_state = JobState(hints.get("job_state", JobState.RUNNING.value).lower())
4153

4254

4355
class QueryHintsParser:

dbt/include/flink/macros/materializations/models/create_table_as.sql

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,12 @@
2626
{% set execution_config = config.get('default_execution_config', {}) %}
2727
{% set _dummy = execution_config.update(config.get('execution_config', {})) %}
2828
{% set upgrade_mode = config.get('upgrade_mode', 'stateless') %}
29+
{% set job_state = config.get('job_state', 'running') %}
2930

3031
{{ sql_header if sql_header is not none }}
31-
/** upgrade_mode('{{upgrade_mode}}') */
32+
/** upgrade_mode('{{upgrade_mode}}') */ /** job_state('{{job_state}}') */
3233
{% if execution_config %}/** execution_config('{% for cfg_name in execution_config %}{{cfg_name}}={{execution_config[cfg_name]}}{% if not loop.last %};{% endif %}{% endfor %}') */{% endif %}
33-
/** drop_statement('drop {% if temporary: -%}temporary {%- endif %}table if exists {{ this.render() }}') */
34+
/** drop_statement('drop {% if temporary: -%}temporary {%- endif %}table if exists `{{ this.render() }}`') */
3435
create {% if temporary: -%}temporary {%- endif %}table
3536
{{ this.render() }}
3637
{% if type %}/** mode('{{type}}')*/{% endif %}

dbt/include/flink/macros/materializations/models/create_view_as.sql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
{%- set sql_header = config.get('sql_header', none) -%}
1818

1919
{{ sql_header if sql_header is not none }}
20-
/** drop_statement('drop view if exists {{ this.render() }}') */
20+
/** drop_statement('drop view if exists `{{ this.render() }}`') */
2121
create view /*TODO {{ relation }}*/ {{ this.render() }} {% if type %}/** mode('{{type}}')*/{% endif %} as (
2222
{{ sql }}
2323
);

dbt/include/flink/macros/materializations/sources/source.sql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
{% set watermark_properties = node.config.get('watermark') %}
88
{% set type = node.config.get('type', None) %}
99
{% set table_column_ids = node.columns.keys() %}
10-
/** drop_statement('DROP TABLE IF EXISTS {{ node.identifier }}') */
10+
/** drop_statement('DROP TABLE IF EXISTS `{{ node.identifier }}`') */
1111
CREATE TABLE {{ node.identifier }} {% if type %}/** mode('{{type}}')*/{% endif %} (
1212
{% for column_id in table_column_ids %}
1313
{%- if node.columns[column_id]["column_type"] == 'metadata' %} `{{ node.columns[column_id]["name"] }}` {{ node.columns[column_id]["data_type"] }} METADATA {% if node.columns[column_id]["expression"] %} FROM '{{node.columns[column_id]["expression"]}}' {% endif %}

tests/adapters/flink/test_query_hints_parser.py

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
1-
from dbt.adapters.flink.query_hints_parser import QueryHintsParser, QueryMode
1+
from dbt.adapters.flink.query_hints_parser import (
2+
QueryHintsParser,
3+
QueryMode,
4+
JobState,
5+
UpgradeMode,
6+
)
27

38

49
class TestQueryHintsParser:
@@ -39,11 +44,26 @@ def test_drop_statement(self):
3944
sql = "/** drop_statement('DROP TABLE IF EXISTS TABLE_A') */ CREATE TABLE TABLE_A (id STRING)"
4045
hints = QueryHintsParser.parse(sql)
4146
assert hints.drop_statement == "DROP TABLE IF EXISTS TABLE_A"
42-
47+
4348
def test_upgrade_mode(self):
4449
sql = "/** upgrade_mode('savepoint') */ CREATE TABLE TABLE_X (id String) AS SELECT * FROM Y"
4550
hints = QueryHintsParser.parse(sql)
46-
assert hints.upgrade_mode == "savepoint"
51+
assert hints.upgrade_mode == UpgradeMode.SAVEPOINT
52+
53+
def test_default_upgrade_mode(self):
54+
sql = "CREATE TABLE TABLE_X (id String) AS SELECT * FROM Y"
55+
hints = QueryHintsParser.parse(sql)
56+
assert hints.upgrade_mode == UpgradeMode.STATELESS
57+
58+
def test_job_state(self):
59+
sql = "/** job_state('suspended') */ CREATE TABLE TABLE_X (id String) AS SELECT * FROM Y"
60+
hints = QueryHintsParser.parse(sql)
61+
assert hints.job_state == JobState.SUSPENDED
62+
63+
def test_default_job_state(self):
64+
sql = "CREATE TABLE TABLE_X (id String) AS SELECT * FROM Y"
65+
hints = QueryHintsParser.parse(sql)
66+
assert hints.job_state == JobState.RUNNING
4767

4868
def test_multiple_hints_in_single_comment(self):
4969
sql = "select /** fetch_max(10) fetch_timeout_ms(1000) */ from input"

0 commit comments

Comments
 (0)