-
Notifications
You must be signed in to change notification settings - Fork 17.4k
Add deferrable mode for S3KeySensor #31018
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 9 commits
Commits
Show all changes
37 commits
Select commit
Hold shift + click to select a range
3ded5c9
Make S3KeySensor deferrable
sunank200 3d1c188
Remove aiobotocore from dependency
sunank200 85e6edb
Add the S3 trigger path
sunank200 95e74c6
Add the tests
sunank200 f613dd0
Merge branch 'main' into s3keysensor
sunank200 602d9d6
remove unnecessary tests
sunank200 ae83da3
Fix the docs
sunank200 6e1f0a0
update docs and example DAG
sunank200 11ce1b8
Merge branch 'apache:main' into s3keysensor
sunank200 41b0c22
Merge branch 'apache:main' into s3keysensor
sunank200 e5f515f
Merge branch 'main' into s3keysensor
sunank200 571ffa6
Remove S3HookAsync and use S3Hook with async_conn
sunank200 0785452
Add tests for hooks and triggers
sunank200 38583a7
remove aiohttp
sunank200 c4be0da
remove test for Python 3.7 in Airflow
sunank200 e1bbaec
Add more test to system tests
sunank200 debf4a7
Merge branch 'main' into s3keysensor
sunank200 3701f61
Merge branch 'apache:main' into s3keysensor
sunank200 b75c3b9
Merge branch 'main' into s3keysensor
sunank200 d7b3188
Merge branch 'apache:main' into s3keysensor
sunank200 d36487d
add check_fn fix
sunank200 c3e8d8e
Merge branch 'main' into s3keysensor
sunank200 6be1156
Add tests for chech_fn
sunank200 fa49d9c
Remove s3 key unchanged code
sunank200 08ee769
Add the should_check_fn in serializer
sunank200 df55976
Update triggers integration-name in providers.yaml
sunank200 3ac1de4
Refactor integration name from Amazon S3 to Amazon Simple Storage Ser…
sunank200 545a26b
add type checking
sunank200 8d18db9
Add . for static checksin doc-strings
sunank200 9f62328
Merge remote-tracking branch 'upstream/main' into s3keysensor
sunank200 f598da1
Merge branch 'main' into s3keysensor
sunank200 01f64fe
Merge branch 's3keysensor' of https://github.com/sunank200/airflow in…
sunank200 66732fd
Merge branch 'main' into s3keysensor
sunank200 110a8f9
change doc string
sunank200 83c3bed
Merge branch 's3keysensor' of https://github.com/sunank200/airflow in…
sunank200 66e7e4e
Merge branch 'main' into s3keysensor
sunank200 1b315a1
Merge branch 'main' into s3keysensor
sunank200 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
Large diffs are not rendered by default.
Oops, something went wrong.
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,97 @@ | ||
| # Licensed to the Apache Software Foundation (ASF) under one | ||
| # or more contributor license agreements. See the NOTICE file | ||
| # distributed with this work for additional information | ||
| # regarding copyright ownership. The ASF licenses this file | ||
| # to you under the Apache License, Version 2.0 (the | ||
| # "License"); you may not use this file except in compliance | ||
| # with the License. You may obtain a copy of the License at | ||
| # | ||
| # http://www.apache.org/licenses/LICENSE-2.0 | ||
| # | ||
| # Unless required by applicable law or agreed to in writing, | ||
| # software distributed under the License is distributed on an | ||
| # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
| # KIND, either express or implied. See the License for the | ||
| # specific language governing permissions and limitations | ||
| # under the License. | ||
| from __future__ import annotations | ||
|
|
||
| import asyncio | ||
| from typing import Any, AsyncIterator, Callable | ||
|
|
||
| from airflow.providers.amazon.aws.hooks.s3 import S3AsyncHook | ||
| from airflow.triggers.base import BaseTrigger, TriggerEvent | ||
|
|
||
|
|
||
| class S3KeyTrigger(BaseTrigger): | ||
| """ | ||
| S3KeyTrigger is fired as deferred class with params to run the task in trigger worker | ||
|
|
||
| :param bucket_name: Name of the S3 bucket. Only needed when ``bucket_key`` | ||
| is not provided as a full s3:// url. | ||
| :param bucket_key: The key being waited on. Supports full s3:// style url | ||
| or relative path from root level. When it's specified as a full s3:// | ||
| url, please leave bucket_name as `None`. | ||
| :param wildcard_match: whether the bucket_key should be interpreted as a | ||
| Unix wildcard pattern | ||
| :param aws_conn_id: reference to the s3 connection | ||
| :param hook_params: params for hook its optional | ||
| :param check_fn: Function that receives the list of the S3 objects, | ||
| and returns a boolean | ||
| """ | ||
|
|
||
| def __init__( | ||
| self, | ||
| bucket_name: str, | ||
| bucket_key: str | list[str], | ||
| wildcard_match: bool = False, | ||
| check_fn: Callable[..., bool] | None = None, | ||
| aws_conn_id: str = "aws_default", | ||
| poke_interval: float = 5.0, | ||
| **hook_params: Any, | ||
| ): | ||
| super().__init__() | ||
| self.bucket_name = bucket_name | ||
| self.bucket_key = bucket_key | ||
| self.wildcard_match = wildcard_match | ||
| self.check_fn = check_fn | ||
| self.aws_conn_id = aws_conn_id | ||
| self.hook_params = hook_params | ||
| self.poke_interval = poke_interval | ||
|
|
||
| def serialize(self) -> tuple[str, dict[str, Any]]: | ||
| """Serialize S3KeyTrigger arguments and classpath.""" | ||
| return ( | ||
| "airflow.providers.amazon.aws.triggers.s3.S3KeyTrigger", | ||
| { | ||
| "bucket_name": self.bucket_name, | ||
| "bucket_key": self.bucket_key, | ||
| "wildcard_match": self.wildcard_match, | ||
| "check_fn": self.check_fn, | ||
| "aws_conn_id": self.aws_conn_id, | ||
| "hook_params": self.hook_params, | ||
| "poke_interval": self.poke_interval, | ||
| }, | ||
| ) | ||
|
|
||
| async def run(self) -> AsyncIterator[TriggerEvent]: | ||
| """Make an asynchronous connection using S3HookAsync.""" | ||
| try: | ||
| hook = self._get_async_hook() | ||
| async with await hook.get_client_async() as client: | ||
| while True: | ||
| if await hook.check_key(client, self.bucket_name, self.bucket_key, self.wildcard_match): | ||
| if self.check_fn is None: | ||
|
sunank200 marked this conversation as resolved.
Outdated
|
||
| yield TriggerEvent({"status": "success"}) | ||
| else: | ||
| s3_objects = await hook.get_files( | ||
| client, self.bucket_name, self.bucket_key, self.wildcard_match | ||
| ) | ||
| yield TriggerEvent({"status": "success", "s3_objects": s3_objects}) | ||
| await asyncio.sleep(self.poke_interval) | ||
|
|
||
| except Exception as e: | ||
| yield TriggerEvent({"status": "error", "message": str(e)}) | ||
|
|
||
| def _get_async_hook(self) -> S3AsyncHook: | ||
| return S3AsyncHook(aws_conn_id=self.aws_conn_id, verify=self.hook_params.get("verify")) | ||
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| # Licensed to the Apache Software Foundation (ASF) under one | ||
|
sunank200 marked this conversation as resolved.
|
||
| # or more contributor license agreements. See the NOTICE file | ||
| # distributed with this work for additional information | ||
| # regarding copyright ownership. The ASF licenses this file | ||
| # to you under the Apache License, Version 2.0 (the | ||
| # "License"); you may not use this file except in compliance | ||
| # with the License. You may obtain a copy of the License at | ||
| # | ||
| # http://www.apache.org/licenses/LICENSE-2.0 | ||
| # | ||
| # Unless required by applicable law or agreed to in writing, | ||
| # software distributed under the License is distributed on an | ||
| # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
| # KIND, either express or implied. See the License for the | ||
| # specific language governing permissions and limitations | ||
| # under the License. | ||
|
|
||
| from __future__ import annotations | ||
|
|
||
| __all__ = ["async_mock", "AsyncMock"] | ||
|
|
||
| import sys | ||
|
|
||
| if sys.version_info < (3, 8): | ||
|
sunank200 marked this conversation as resolved.
Outdated
|
||
| # For compatibility with Python 3.7 | ||
| from asynctest import mock as async_mock | ||
|
|
||
| # ``asynctest.mock.CoroutineMock`` which provide compatibility not working well with autospec=True | ||
| # as result "TypeError: object MagicMock can't be used in 'await' expression" could be raised. | ||
| # Best solution in this case provide as spec actual awaitable object | ||
| # >>> from tests.providers.apache.livy.compat import AsyncMock | ||
| # >>> from foo.bar import SpamEgg | ||
| # >>> mock_something = AsyncMock(SpamEgg) | ||
| from asynctest.mock import CoroutineMock as AsyncMock | ||
| else: | ||
| from unittest import mock as async_mock | ||
| from unittest.mock import AsyncMock | ||
Oops, something went wrong.
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.