-
Notifications
You must be signed in to change notification settings - Fork 339
Auto Backfill workflow #1420
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
Auto Backfill workflow #1420
Changes from all commits
5b35033
61cfc69
b6084f2
0330cbb
312b573
227d28a
9d94be4
c2bf932
8885cf5
78b3fd4
60ff6ee
87806e6
21dea01
370c036
77deff7
f36f157
e932af0
f77b27a
ddb88b7
255c4c4
7046ddb
b0b4abf
6f979e0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,178 @@ | ||
| import typing | ||
| from datetime import datetime, timedelta | ||
|
|
||
| import click | ||
|
|
||
| from flytekit.clis.sdk_in_container.helpers import get_and_save_remote_with_click_context | ||
| from flytekit.clis.sdk_in_container.run import DateTimeType, DurationParamType | ||
|
|
||
| _backfill_help = """ | ||
| The backfill command generates and registers a new workflow based on the input launchplan to run an | ||
| automated backfill. The workflow can be managed using the Flyte UI and can be canceled, relaunched, and recovered. | ||
|
|
||
| - launchplan refers to the name of the launchplan | ||
| - launchplan_version is optional and should be a valid version for a launchplan version. | ||
| """ | ||
|
|
||
|
|
||
| def resolve_backfill_window( | ||
| from_date: datetime = None, | ||
| to_date: datetime = None, | ||
| backfill_window: timedelta = None, | ||
| ) -> typing.Tuple[datetime, datetime]: | ||
| """ | ||
| Resolves the from_date -> to_date | ||
| """ | ||
| if from_date and to_date and backfill_window: | ||
| raise click.BadParameter("Setting from-date, to-date and backfill_window at the same time is not allowed.") | ||
| if not (from_date or to_date): | ||
| raise click.BadParameter( | ||
| "One of following pairs are required -> (from-date, to-date) | (from-date, backfill_window) |" | ||
| " (to-date, backfill_window)" | ||
| ) | ||
| if from_date and to_date: | ||
| pass | ||
| elif not backfill_window: | ||
| raise click.BadParameter("One of start-date and end-date are needed with duration") | ||
| elif from_date: | ||
| to_date = from_date + backfill_window | ||
| else: | ||
| from_date = to_date - backfill_window | ||
| return from_date, to_date | ||
|
|
||
|
|
||
| @click.command("backfill", help=_backfill_help) | ||
| @click.option( | ||
| "-p", | ||
| "--project", | ||
| required=False, | ||
| type=str, | ||
| default="flytesnacks", | ||
| help="Project to register and run this workflow in", | ||
| ) | ||
| @click.option( | ||
| "-d", | ||
| "--domain", | ||
| required=False, | ||
| type=str, | ||
| default="development", | ||
| help="Domain to register and run this workflow in", | ||
| ) | ||
| @click.option( | ||
| "-v", | ||
| "--version", | ||
| required=False, | ||
| type=str, | ||
| default=None, | ||
| help="Version for the registered workflow. If not specified it is auto-derived using the start and end date", | ||
| ) | ||
| @click.option( | ||
| "-n", | ||
| "--execution-name", | ||
| required=False, | ||
| type=str, | ||
| default=None, | ||
| help="Create a named execution for the backfill. This can prevent launching multiple executions.", | ||
| ) | ||
| @click.option( | ||
| "--dry-run", | ||
| required=False, | ||
| type=bool, | ||
| is_flag=True, | ||
| default=False, | ||
| show_default=True, | ||
| help="Just generate the workflow - do not register or execute", | ||
| ) | ||
| @click.option( | ||
| "--parallel/--serial", | ||
| required=False, | ||
| type=bool, | ||
| is_flag=True, | ||
| default=False, | ||
| show_default=True, | ||
| help="All backfill steps can be run in parallel (limited by max-parallelism), if using --parallel." | ||
| " Else all steps will be run sequentially [--serial].", | ||
| ) | ||
| @click.option( | ||
| "--execute/--do-not-execute", | ||
| required=False, | ||
| type=bool, | ||
| is_flag=True, | ||
| default=True, | ||
| show_default=True, | ||
| help="Generate the workflow and register, do not execute", | ||
| ) | ||
| @click.option( | ||
| "--from-date", | ||
| required=False, | ||
| type=DateTimeType(), | ||
| default=None, | ||
| help="Date from which the backfill should begin. Start date is inclusive.", | ||
| ) | ||
| @click.option( | ||
| "--to-date", | ||
| required=False, | ||
| type=DateTimeType(), | ||
| default=None, | ||
| help="Date to which the backfill should run_until. End date is inclusive", | ||
| ) | ||
| @click.option( | ||
| "--backfill-window", | ||
| required=False, | ||
| type=DurationParamType(), | ||
| default=None, | ||
| help="Timedelta for number of days, minutes hours after the from-date or before the to-date to compute the " | ||
| "backfills between. This is needed with from-date / to-date. Optional if both from-date and to-date are " | ||
| "provided", | ||
| ) | ||
| @click.argument( | ||
| "launchplan", | ||
| required=True, | ||
| type=str, | ||
| ) | ||
| @click.argument( | ||
| "launchplan-version", | ||
| required=False, | ||
| type=str, | ||
| default=None, | ||
| ) | ||
| @click.pass_context | ||
| def backfill( | ||
| ctx: click.Context, | ||
| project: str, | ||
| domain: str, | ||
| from_date: datetime, | ||
| to_date: datetime, | ||
| backfill_window: timedelta, | ||
| launchplan: str, | ||
| launchplan_version: str, | ||
| dry_run: bool, | ||
| execute: bool, | ||
| parallel: bool, | ||
| execution_name: str, | ||
| version: str, | ||
| ): | ||
| from_date, to_date = resolve_backfill_window(from_date, to_date, backfill_window) | ||
| remote = get_and_save_remote_with_click_context(ctx, project, domain) | ||
| try: | ||
| entity = remote.launch_backfill( | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is it possible that this call does not return an entity? Should we inform the user in that case?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. it is not, but i cleaned up the comment
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. in that case, Just to make the code more readable, can you remove the if clause in line 171?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. hmm the if block is just to improve the output for the user right?
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I was just thinking of the case |
||
| project=project, | ||
| domain=domain, | ||
| from_date=from_date, | ||
| to_date=to_date, | ||
| launchplan=launchplan, | ||
| launchplan_version=launchplan_version, | ||
| execution_name=execution_name, | ||
| version=version, | ||
| dry_run=dry_run, | ||
| execute=execute, | ||
| parallel=parallel, | ||
| ) | ||
| if entity: | ||
| console_url = remote.generate_console_url(entity) | ||
| if execute: | ||
| click.secho(f"\n Execution launched {console_url} to see execution in the console.", fg="green") | ||
| return | ||
| click.secho(f"\n Workflow registered at {console_url}", fg="green") | ||
| except StopIteration as e: | ||
| click.secho(f"{e.value}", fg="red") | ||
Uh oh!
There was an error while loading. Please reload this page.