Skip to content

Commit 50f29cd

Browse files
authored
Fix leaking dynamodb tables in integration tests (#2104)
1 parent 99f1851 commit 50f29cd

3 files changed

Lines changed: 37 additions & 5 deletions

File tree

.github/workflows/pr_integration_tests.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ jobs:
146146
- name: Install dependencies
147147
run: make install-python-ci-dependencies
148148
- name: Test python
149+
if: ${{ always() }} # this will guarantee that step won't be canceled and resources won't leak
149150
env:
150151
FEAST_SERVER_DOCKER_IMAGE_TAG: ${{ needs.build-docker-image.outputs.DOCKER_IMAGE_TAG }}
151152
FEAST_USAGE: "False"

sdk/python/feast/infra/online_stores/dynamodb.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
14+
import logging
1415
from datetime import datetime
1516
from typing import Any, Callable, Dict, List, Optional, Sequence, Tuple, Union
1617

@@ -34,6 +35,9 @@
3435
raise FeastExtrasDependencyImportError("aws", str(e))
3536

3637

38+
logger = logging.getLogger(__name__)
39+
40+
3741
class DynamoDBOnlineStoreConfig(FeastConfigBaseModel):
3842
"""Online store config for DynamoDB store"""
3943

@@ -179,9 +183,17 @@ def _delete_tables_idempotent(
179183
f"{config.project}.{table_instance.name}"
180184
)
181185
table.delete()
186+
logger.info(
187+
f"Dynamo table {config.project}.{table_instance.name} was deleted"
188+
)
182189
except ClientError as ce:
183190
# If the table deletion fails with ResourceNotFoundException,
184191
# it means the table has already been deleted.
185192
# Otherwise, re-raise the exception
186193
if ce.response["Error"]["Code"] != "ResourceNotFoundException":
187194
raise
195+
else:
196+
logger.warning(
197+
f"Trying to delete table that doesn't exist:"
198+
f" {config.project}.{table_instance.name}"
199+
)

sdk/python/tests/integration/registration/test_universal_types.py

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import logging
12
from dataclasses import dataclass
23
from datetime import datetime, timedelta
34
from typing import List
@@ -18,6 +19,8 @@
1819
from tests.integration.feature_repos.universal.entities import driver
1920
from tests.integration.feature_repos.universal.feature_views import driver_feature_view
2021

22+
logger = logging.getLogger(__name__)
23+
2124

2225
def populate_test_configs(offline: bool):
2326
entity_type_feature_dtypes = [
@@ -106,14 +109,19 @@ def get_fixtures(request):
106109
field_mapping={"ts_1": "ts"},
107110
)
108111
fv = create_feature_view(
112+
request.fixturename,
109113
config.feature_dtype,
110114
config.feature_is_list,
111115
config.has_empty_list,
112116
data_source,
113117
)
114118

115119
def cleanup():
116-
type_test_environment.data_source_creator.teardown()
120+
try:
121+
type_test_environment.data_source_creator.teardown()
122+
except Exception: # noqa
123+
logger.exception("DataSourceCreator teardown has failed")
124+
117125
type_test_environment.feature_store.teardown()
118126

119127
request.addfinalizer(cleanup)
@@ -151,7 +159,11 @@ def test_feature_get_historical_features_types_match(offline_types_test_fixtures
151159
environment, config, data_source, fv = offline_types_test_fixtures
152160
fs = environment.feature_store
153161
fv = create_feature_view(
154-
config.feature_dtype, config.feature_is_list, config.has_empty_list, data_source
162+
"get_historical_features_types_match",
163+
config.feature_dtype,
164+
config.feature_is_list,
165+
config.has_empty_list,
166+
data_source,
155167
)
156168
entity = driver()
157169
fs.apply([fv, entity])
@@ -197,7 +209,11 @@ def test_feature_get_historical_features_types_match(offline_types_test_fixtures
197209
def test_feature_get_online_features_types_match(online_types_test_fixtures):
198210
environment, config, data_source, fv = online_types_test_fixtures
199211
fv = create_feature_view(
200-
config.feature_dtype, config.feature_is_list, config.has_empty_list, data_source
212+
"get_online_features_types_match",
213+
config.feature_dtype,
214+
config.feature_is_list,
215+
config.has_empty_list,
216+
data_source,
201217
)
202218
fs = environment.feature_store
203219
features = [fv.name + ":value"]
@@ -230,7 +246,9 @@ def test_feature_get_online_features_types_match(online_types_test_fixtures):
230246
assert isinstance(feature, expected_dtype)
231247

232248

233-
def create_feature_view(feature_dtype, feature_is_list, has_empty_list, data_source):
249+
def create_feature_view(
250+
name, feature_dtype, feature_is_list, has_empty_list, data_source
251+
):
234252
if feature_is_list is True:
235253
if feature_dtype == "int32":
236254
value_type = ValueType.INT32_LIST
@@ -249,7 +267,8 @@ def create_feature_view(feature_dtype, feature_is_list, has_empty_list, data_sou
249267
value_type = ValueType.FLOAT
250268
elif feature_dtype == "bool":
251269
value_type = ValueType.BOOL
252-
return driver_feature_view(data_source, value_type=value_type,)
270+
271+
return driver_feature_view(data_source, name=name, value_type=value_type,)
253272

254273

255274
def assert_expected_historical_feature_types(

0 commit comments

Comments
 (0)