Skip to content

Commit

Permalink
Add Common module (#801)
Browse files Browse the repository at this point in the history
* Add common module

* Refactor parts of codebase to use common module

* Add blacklist functionality and test

* Update common module pom

* Address PR comments

* Address PR comments

* Remove subscriptions blacklist changes

* Update param comment

Co-authored-by: Terence <terence.limxp@go-jek.com>
  • Loading branch information
terryyylim and Terence authored Jun 22, 2020
1 parent ec98916 commit fc53df1
Show file tree
Hide file tree
Showing 24 changed files with 479 additions and 116 deletions.
60 changes: 60 additions & 0 deletions common/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2018-2020 The Feast Authors
~
~ Licensed 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
~
~ https://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.
~
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<artifactId>feast-parent</artifactId>
<groupId>dev.feast</groupId>
<version>${revision}</version>
</parent>

<name>Feast Common</name>
<description>Feast common module with functionality that can be reused</description>
<artifactId>feast-common</artifactId>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M4</version>
<configuration>
<argLine>-Xms2048m -Xmx2048m -Djdk.net.URLClassPath.disableClassPathURLCheck=true</argLine>
</configuration>
</plugin>
</plugins>
</build>

<dependencies>
<dependency>
<groupId>dev.feast</groupId>
<artifactId>datatypes-java</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* SPDX-License-Identifier: Apache-2.0
* Copyright 2018-2019 The Feast Authors
* Copyright 2018-2020 The Feast Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -14,25 +14,29 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package feast.serving.util;
package feast.common.models;

import feast.proto.core.FeatureSetProto.FeatureSetSpec;
import feast.proto.serving.ServingAPIProto.FeatureReference;

public class RefUtil {
public static String generateFeatureStringRef(FeatureReference featureReference) {
public class Feature {

/**
* Accepts FeatureReference object and returns its reference in String
* "project/featureset_name:feature_name".
*
* @param featureReference {@link FeatureReference}
* @param ignoreProject Flag whether to return FeatureReference with project name
* @return String format of FeatureReference
*/
public static String getFeatureStringRef(
FeatureReference featureReference, boolean ignoreProject) {
String ref = featureReference.getName();
if (!featureReference.getFeatureSet().isEmpty()) {
ref = featureReference.getFeatureSet() + ":" + ref;
}
if (!featureReference.getProject().isEmpty()) {
if (!featureReference.getProject().isEmpty() && !ignoreProject) {
ref = featureReference.getProject() + "/" + ref;
}
return ref;
}

public static String generateFeatureSetStringRef(FeatureSetSpec featureSetSpec) {
String ref = String.format("%s/%s", featureSetSpec.getProject(), featureSetSpec.getName());
return ref;
}
}
44 changes: 44 additions & 0 deletions common/src/main/java/feast/common/models/FeatureSet.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* SPDX-License-Identifier: Apache-2.0
* Copyright 2018-2020 The Feast Authors
*
* Licensed 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
*
* https://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.
*/
package feast.common.models;

import feast.proto.core.FeatureSetProto.FeatureSetSpec;
import feast.proto.core.FeatureSetReferenceProto.FeatureSetReference;

public class FeatureSet {

/**
* Accepts FeatureSetSpec object and returns its reference in String "project/featureset_name".
*
* @param featureSetSpec {@link FeatureSetSpec}
* @return String format of FeatureSetReference
*/
public static String getFeatureSetStringRef(FeatureSetSpec featureSetSpec) {
return String.format("%s/%s", featureSetSpec.getProject(), featureSetSpec.getName());
}

/**
* Accepts FeatureSetReference object and returns its reference in String
* "project/featureset_name".
*
* @param featureSetReference {@link FeatureSetReference}
* @return String format of FeatureSetReference
*/
public static String getFeatureSetStringRef(FeatureSetReference featureSetReference) {
return String.format("%s/%s", featureSetReference.getProject(), featureSetReference.getName());
}
}
98 changes: 98 additions & 0 deletions common/src/main/java/feast/common/models/Store.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
/*
* SPDX-License-Identifier: Apache-2.0
* Copyright 2018-2020 The Feast Authors
*
* Licensed 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
*
* https://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.
*/
package feast.common.models;

import feast.proto.core.StoreProto.Store.Subscription;
import java.util.List;
import java.util.regex.Pattern;

public class Store {

/**
* Accepts a Subscription class object and returns it in string format
*
* @param subscription Subscription class to be converted to string format
* @return String formatted Subscription class
*/
public static String parseSubscriptionFrom(Subscription subscription) {
if (subscription.getName().isEmpty() || subscription.getProject().isEmpty()) {
throw new IllegalArgumentException(
String.format("Missing arguments in subscription string: %s", subscription.toString()));
}

return String.format("%s:%s", subscription.getProject(), subscription.getName());
}

/**
* Accepts a exclude parameter to determine whether to return subscriptions that are excluded.
*
* @param subscription String formatted Subscription to be converted to Subscription class
* @return Subscription class with its respective attributes
*/
public static Subscription convertStringToSubscription(String subscription) {
if (subscription.equals("")) {
return Subscription.newBuilder().build();
}
String[] split = subscription.split(":");
return Subscription.newBuilder().setProject(split[0]).setName(split[1]).build();
}

/**
* The current use of this function is to determine whether a FeatureRow is subscribed to a
* Featureset.
*
* @param subscriptions List of Subscriptions available in Store
* @param projectName Project name used for matching Subscription's Project
* @param featureSetName Featureset name used for matching Subscription's Featureset
* @return boolean flag to signify if FeatureRow is subscribed to Featureset
*/
public static boolean isSubscribedToFeatureSet(
List<Subscription> subscriptions, String projectName, String featureSetName) {
for (Subscription sub : subscriptions) {
// If configuration missing, fail
if (sub.getProject().isEmpty() || sub.getName().isEmpty()) {
throw new IllegalArgumentException(
String.format("Subscription is missing arguments: %s", sub.toString()));
}

// If all wildcards, subscribe to everything
if (sub.getProject().equals("*") || sub.getName().equals("*")) {
return true;
}

// Match project name
if (!projectName.equals(sub.getProject())) {
continue;
}

// Convert wildcard to regex
String subName = sub.getName();
if (!sub.getName().contains(".*")) {
subName = subName.replace("*", ".*");
}

// Match feature set name to pattern
Pattern pattern = Pattern.compile(subName);
if (!pattern.matcher(featureSetName).matches()) {
continue;
}
return true;
}

return false;
}
}
97 changes: 97 additions & 0 deletions common/src/test/java/feast/common/models/FeatureSetTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/*
* SPDX-License-Identifier: Apache-2.0
* Copyright 2018-2020 The Feast Authors
*
* Licensed 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
*
* https://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.
*/
package feast.common.models;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.IsEqual.equalTo;

import feast.proto.core.FeatureSetProto.EntitySpec;
import feast.proto.core.FeatureSetProto.FeatureSetSpec;
import feast.proto.core.FeatureSetProto.FeatureSpec;
import feast.proto.core.FeatureSetReferenceProto;
import feast.proto.types.ValueProto;
import java.util.Arrays;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import org.tensorflow.metadata.v0.*;

public class FeatureSetTest {

private List<EntitySpec> entitySpecs;
private List<FeatureSpec> featureSpecs;

@Before
public void setUp() {
// Entity Specs
EntitySpec entitySpec1 =
EntitySpec.newBuilder()
.setName("entity1")
.setValueType(ValueProto.ValueType.Enum.INT64)
.build();
EntitySpec entitySpec2 =
EntitySpec.newBuilder()
.setName("entity2")
.setValueType(ValueProto.ValueType.Enum.INT64)
.build();

// Feature Specs
FeatureSpec featureSpec1 =
FeatureSpec.newBuilder()
.setName("feature1")
.setValueType(ValueProto.ValueType.Enum.INT64)
.setPresence(FeaturePresence.getDefaultInstance())
.setShape(FixedShape.getDefaultInstance())
.setDomain("mydomain")
.build();
FeatureSpec featureSpec2 =
FeatureSpec.newBuilder()
.setName("feature2")
.setValueType(ValueProto.ValueType.Enum.INT64)
.setGroupPresence(FeaturePresenceWithinGroup.getDefaultInstance())
.setValueCount(ValueCount.getDefaultInstance())
.setIntDomain(IntDomain.getDefaultInstance())
.build();

entitySpecs = Arrays.asList(entitySpec1, entitySpec2);
featureSpecs = Arrays.asList(featureSpec1, featureSpec2);
}

@Test
public void shouldReturnFeatureSetStringRef() {
FeatureSetSpec featureSetSpec =
FeatureSetSpec.newBuilder()
.setProject("project1")
.setName("featureSetWithConstraints")
.addAllEntities(entitySpecs)
.addAllFeatures(featureSpecs)
.build();

FeatureSetReferenceProto.FeatureSetReference featureSetReference =
FeatureSetReferenceProto.FeatureSetReference.newBuilder()
.setName(featureSetSpec.getName())
.setProject(featureSetSpec.getProject())
.build();

String actualFeatureSetStringRef1 = FeatureSet.getFeatureSetStringRef(featureSetSpec);
String actualFeatureSetStringRef2 = FeatureSet.getFeatureSetStringRef(featureSetReference);
String expectedFeatureSetStringRef = "project1/featureSetWithConstraints";

assertThat(actualFeatureSetStringRef1, equalTo(expectedFeatureSetStringRef));
assertThat(actualFeatureSetStringRef2, equalTo(expectedFeatureSetStringRef));
}
}
Loading

0 comments on commit fc53df1

Please sign in to comment.