| 1127 | |
| 1128 | |
| 1129 | def _get_features( |
| 1130 | registry, |
| 1131 | project, |
| 1132 | features: Union[List[str], "FeatureService"], |
| 1133 | allow_cache: bool = False, |
| 1134 | ) -> List[str]: |
| 1135 | from feast.feature_service import FeatureService |
| 1136 | |
| 1137 | _features = features |
| 1138 | |
| 1139 | if not _features: |
| 1140 | raise ValueError("No features specified for retrieval") |
| 1141 | |
| 1142 | _feature_refs = [] |
| 1143 | if isinstance(_features, FeatureService): |
| 1144 | # Create cache key for feature service resolution |
| 1145 | cache_key = f"{_features.name}:{project}:{hash(tuple(str(fv) for fv in _features.feature_view_projections))}" |
| 1146 | |
| 1147 | # Check cache first if caching is enabled and available |
| 1148 | if allow_cache and hasattr(registry, "_feature_service_cache"): |
| 1149 | if cache_key in registry._feature_service_cache: |
| 1150 | return registry._feature_service_cache[cache_key] |
| 1151 | |
| 1152 | # Resolve feature service from registry |
| 1153 | feature_service_from_registry = registry.get_feature_service( |
| 1154 | _features.name, project, allow_cache |
| 1155 | ) |
| 1156 | if feature_service_from_registry != _features: |
| 1157 | warnings.warn( |
| 1158 | "The FeatureService object that has been passed in as an argument is " |
| 1159 | "inconsistent with the version from the registry. Potentially a newer version " |
| 1160 | "of the FeatureService has been applied to the registry." |
| 1161 | ) |
| 1162 | |
| 1163 | # Build feature reference list |
| 1164 | for projection in feature_service_from_registry.feature_view_projections: |
| 1165 | _feature_refs.extend( |
| 1166 | [f"{projection.name_to_use()}:{f.name}" for f in projection.features] |
| 1167 | ) |
| 1168 | |
| 1169 | # Cache the result if caching is enabled and available |
| 1170 | if allow_cache and hasattr(registry, "_feature_service_cache"): |
| 1171 | registry._feature_service_cache[cache_key] = _feature_refs |
| 1172 | else: |
| 1173 | assert isinstance(_features, list) |
| 1174 | _feature_refs = _features |
| 1175 | return _feature_refs |
| 1176 | |
| 1177 | |
| 1178 | def _list_feature_views( |