1717
1818package feast .core .service ;
1919
20+ import static feast .core .validators .Matchers .checkValidCharacters ;
21+ import static feast .core .validators .Matchers .checkValidFeatureSetFilterName ;
22+
2023import com .google .common .collect .Ordering ;
2124import com .google .protobuf .InvalidProtocolBufferException ;
2225import feast .core .CoreServiceProto .ApplyFeatureSetResponse ;
2326import feast .core .CoreServiceProto .ApplyFeatureSetResponse .Status ;
24- import feast .core .CoreServiceProto .GetFeatureSetsRequest ;
25- import feast .core .CoreServiceProto .GetFeatureSetsResponse ;
26- import feast .core .CoreServiceProto .GetStoresRequest ;
27- import feast .core .CoreServiceProto .GetStoresResponse ;
28- import feast .core .CoreServiceProto .GetStoresResponse .Builder ;
27+ import feast .core .CoreServiceProto .GetFeatureSetRequest ;
28+ import feast .core .CoreServiceProto .GetFeatureSetResponse ;
29+ import feast .core .CoreServiceProto .ListFeatureSetsRequest ;
30+ import feast .core .CoreServiceProto .ListFeatureSetsResponse ;
31+ import feast .core .CoreServiceProto .ListStoresRequest ;
32+ import feast .core .CoreServiceProto .ListStoresResponse ;
33+ import feast .core .CoreServiceProto .ListStoresResponse .Builder ;
2934import feast .core .CoreServiceProto .UpdateStoreRequest ;
3035import feast .core .CoreServiceProto .UpdateStoreResponse ;
3136import feast .core .FeatureSetProto .FeatureSetSpec ;
@@ -72,6 +77,61 @@ public SpecService(
7277 this .defaultSource = defaultSource ;
7378 }
7479
80+ /**
81+ * Get a feature set matching the feature name and version provided in the filter. The name
82+ * is required. If the version is provided then it will be used for the lookup. If the version
83+ * is omitted then the latest version will be returned.
84+ *
85+ * @param GetFeatureSetRequest containing the name and version of the feature set
86+ * @return GetFeatureSetResponse containing a single feature set
87+ */
88+ public GetFeatureSetResponse getFeatureSet (GetFeatureSetRequest request )
89+ throws InvalidProtocolBufferException {
90+
91+ // Validate input arguments
92+ checkValidCharacters (request .getName (), "featureSetName" );
93+ if (request .getName ().isEmpty ()) {
94+ throw io .grpc .Status .INVALID_ARGUMENT
95+ .withDescription ("No feature set name provided" )
96+ .asRuntimeException ();
97+ }
98+ if (request .getVersion () < 0 ){
99+ throw io .grpc .Status .INVALID_ARGUMENT
100+ .withDescription ("Version number cannot be less than 0" )
101+ .asRuntimeException ();
102+ }
103+
104+ // Find a list of feature sets with the requested name
105+ List <FeatureSet > featureSets = featureSetRepository .findByNameWithWildcard (request .getName ());
106+
107+ // Filter the list based on version
108+ if (request .getVersion () == 0 ){
109+ // Version is not set, filter list to latest version
110+ featureSets = Ordering .natural ().reverse ()
111+ .sortedCopy (featureSets ).subList (0 , featureSets .size () == 0 ? 0 : 1 );
112+ } else if (request .getVersion () > 0 ) {
113+ // Version is set, find specific version
114+ featureSets = featureSets .stream ()
115+ .filter (fs -> request .getVersion () == fs .getVersion ()).collect (Collectors .toList ());
116+ }
117+
118+ // Validate remaining items
119+ if (featureSets .size () == 0 ){
120+ throw io .grpc .Status .NOT_FOUND
121+ .withDescription ("Feature set could not be found" )
122+ .asRuntimeException ();
123+ }
124+ if (featureSets .size () > 1 ){
125+ throw io .grpc .Status .INTERNAL
126+ .withDescription (String .format ("Multiple feature sets found with the name %s and "
127+ + "version %s" , request .getName (), request .getVersion ()))
128+ .asRuntimeException ();
129+ }
130+
131+ // Only a single item in list, return successfully
132+ return GetFeatureSetResponse .newBuilder ().setFeatureSet (featureSets .get (0 ).toProto ()).build ();
133+ }
134+
75135 /**
76136 * Get featureSets matching the feature name and version provided in the filter. If the feature
77137 * name is not provided, the method will return all featureSets currently registered to Feast.
@@ -84,25 +144,21 @@ public SpecService(
84144 * comparator (<, <=, >, etc) and a version number, e.g. 10, <10, >=1
85145 *
86146 * @param filter filter containing the desired featureSet name and version filter
87- * @return GetFeatureSetsResponse with list of featureSets found matching the filter
147+ * @return ListFeatureSetsResponse with list of featureSets found matching the filter
88148 */
89- public GetFeatureSetsResponse getFeatureSets ( GetFeatureSetsRequest .Filter filter )
149+ public ListFeatureSetsResponse listFeatureSets ( ListFeatureSetsRequest .Filter filter )
90150 throws InvalidProtocolBufferException {
91151 String name = filter .getFeatureSetName ();
152+ checkValidFeatureSetFilterName (name , "featureSetName" );
92153 List <FeatureSet > featureSets ;
93154 if (name .equals ("" )) {
94155 featureSets = featureSetRepository .findAll ();
95156 } else {
96- featureSets = featureSetRepository .findByNameRegex (name );
97- if (filter .getFeatureSetVersion ().equals ("latest" )) {
98- featureSets = Ordering .natural ().reverse ()
99- .sortedCopy (featureSets ).subList (0 , featureSets .size () == 0 ? 0 : 1 );
100- } else {
101- featureSets = featureSets .stream ().filter (getVersionFilter (filter .getFeatureSetVersion ()))
102- .collect (Collectors .toList ());
103- }
157+ featureSets = featureSetRepository .findByNameWithWildcard (name .replace ('*' , '%' ));
158+ featureSets = featureSets .stream ().filter (getVersionFilter (filter .getFeatureSetVersion ()))
159+ .collect (Collectors .toList ());
104160 }
105- GetFeatureSetsResponse .Builder response = GetFeatureSetsResponse .newBuilder ();
161+ ListFeatureSetsResponse .Builder response = ListFeatureSetsResponse .newBuilder ();
106162 for (FeatureSet featureSet : featureSets ) {
107163 response .addFeatureSets (featureSet .toProto ());
108164 }
@@ -114,13 +170,13 @@ public GetFeatureSetsResponse getFeatureSets(GetFeatureSetsRequest.Filter filter
114170 * the method will return all stores currently registered to Feast.
115171 *
116172 * @param filter filter containing the desired store name
117- * @return GetStoresResponse containing list of stores found matching the filter
173+ * @return ListStoresResponse containing list of stores found matching the filter
118174 */
119- public GetStoresResponse getStores ( GetStoresRequest .Filter filter ) {
175+ public ListStoresResponse listStores ( ListStoresRequest .Filter filter ) {
120176 try {
121177 String name = filter .getName ();
122178 if (name .equals ("" )) {
123- Builder responseBuilder = GetStoresResponse .newBuilder ();
179+ Builder responseBuilder = ListStoresResponse .newBuilder ();
124180 for (Store store : storeRepository .findAll ()) {
125181 responseBuilder .addStore (store .toProto ());
126182 }
@@ -129,7 +185,7 @@ public GetStoresResponse getStores(GetStoresRequest.Filter filter) {
129185 Store store = storeRepository .findById (name )
130186 .orElseThrow (() -> new RetrievalException (String .format ("Store with name '%s' not found" ,
131187 name )));
132- return GetStoresResponse .newBuilder ()
188+ return ListStoresResponse .newBuilder ()
133189 .addStore (store .toProto ())
134190 .build ();
135191 } catch (InvalidProtocolBufferException e ) {
0 commit comments