//
// Copyright 2018 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.
//

syntax = "proto3";
package feast.core;

option go_package = "github.com/feast-dev/feast/sdk/go/protos/feast/core";
option java_outer_classname = "CoreServiceProto";
option java_package = "feast.proto.core";

import "google/protobuf/timestamp.proto";
import "tensorflow_metadata/proto/v0/statistics.proto";
import "feast/core/Entity.proto";
import "feast/core/Feature.proto";
import "feast/core/FeatureTable.proto";
import "feast/core/Store.proto";

service CoreService {
    // Retrieve version information about this Feast deployment
    rpc GetFeastCoreVersion (GetFeastCoreVersionRequest) returns (GetFeastCoreVersionResponse);

    // Returns a specific entity
    rpc GetEntity (GetEntityRequest) returns (GetEntityResponse);

    // Returns all feature references and respective features matching that filter. If none are found
    // an empty map will be returned
    // If no filter is provided in the request, the response will contain all the features
    // currently stored in the default project.
    rpc ListFeatures (ListFeaturesRequest) returns (ListFeaturesResponse);

    // Retrieve store details given a filter.
    //
    // Returns all stores matching that filter. If none are found, an empty list will be returned.
    // If no filter is provided in the request, the response will contain all the stores currently
    // stored in the registry.
    rpc ListStores (ListStoresRequest) returns (ListStoresResponse);

    // Create or update and existing entity.
    //
    // This function is idempotent - it will not create a new entity if schema does not change.
    // Schema changes will update the entity if the changes are valid.
    // Following changes are not valid:
    // - Changes to name
    // - Changes to type
    rpc ApplyEntity (ApplyEntityRequest) returns (ApplyEntityResponse);

    // Returns all entity references and respective entities matching that filter. If none are found
    // an empty map will be returned
    // If no filter is provided in the request, the response will contain all the entities
    // currently stored in the default project.
    rpc ListEntities (ListEntitiesRequest) returns (ListEntitiesResponse);

    // Updates core with the configuration of the store.
    //
    // If the changes are valid, core will return the given store configuration in response, and
    // start or update the necessary feature population jobs for the updated store.
    rpc UpdateStore (UpdateStoreRequest) returns (UpdateStoreResponse);

    // Creates a project. Projects serve as namespaces within which resources like features will be
    // created. Feature table names as must be unique within a project while field (Feature/Entity) names
    // must be unique within a Feature Table. Project names themselves must be globally unique.
    rpc CreateProject (CreateProjectRequest) returns (CreateProjectResponse);

    // Archives a project. Archived projects will continue to exist and function, but won't be visible
    // through the Core API. Any existing ingestion or serving requests will continue to function,
    // but will result in warning messages being logged. It is not possible to unarchive a project
    // through the Core API
    rpc ArchiveProject (ArchiveProjectRequest) returns (ArchiveProjectResponse);

    // Lists all projects active projects.
    rpc ListProjects (ListProjectsRequest) returns (ListProjectsResponse);

    /* Feature Tables */
    // Create or update an existing feature table.
    // This function is idempotent - it will not create a new feature table if the schema does not change.
    // Schema changes will update the feature table if the changes are valid.
    // All changes except the following are valid:
    // - Changes to feature table name.
    // - Changes to entities
    // - Changes to feature name and type
    rpc ApplyFeatureTable (ApplyFeatureTableRequest) returns (ApplyFeatureTableResponse);

    // List feature tables that match a given filter.
    // Returns the references of the Feature Tables matching that filter. If none are found,
    // an empty list will be returned.
    // If no filter is provided in the request, the response will match all the feature
    // tables currently stored in the registry.
    rpc ListFeatureTables (ListFeatureTablesRequest) returns (ListFeatureTablesResponse);

    // Returns a specific feature table
    rpc GetFeatureTable (GetFeatureTableRequest) returns (GetFeatureTableResponse);

    // Delete a specific feature table
    rpc DeleteFeatureTable (DeleteFeatureTableRequest) returns (DeleteFeatureTableResponse);

}

// Request for a single entity
message GetEntityRequest {
    // Name of entity (required).
    string name = 1;

    // Name of project the entity belongs to. If omitted will default to 'default' project.
    string project = 2;
}

// Response containing a single entity
message GetEntityResponse {
    feast.core.Entity entity = 1;
}

// Retrieves details for all versions of a specific entity
message ListEntitiesRequest {
    Filter filter = 1;

    message Filter {
        // Optional. Specifies the name of the project to list Entities in.
        // It is NOT possible to provide an asterisk with a string in order to do pattern matching.
        // If unspecified, this field will default to the default project 'default'.
        string project = 3;

        // Optional. User defined metadata for entity.
        // Entities with all matching labels will be returned.
        map<string,string> labels = 4;
    }
}

message ListEntitiesResponse {
    repeated feast.core.Entity entities = 1;
}

message ListFeaturesRequest {
    message Filter {
        // User defined metadata for feature.
        // Features with all matching labels will be returned.
        map<string,string> labels = 1;

        // List of entities contained within the featureSet that the feature belongs to.
        // Only feature tables with these entities will be searched for features.
        repeated string entities = 2;

        // Name of project that the feature tables belongs to. Filtering on projects is disabled. 
        // It is NOT possible to provide an asterisk with a string in order to do pattern matching.
        // If unspecified this field will default to the default project 'default'.
        string project = 3;
    }

    Filter filter = 1;
}

message ListFeaturesResponse {
    reserved 1;

    map<string, feast.core.FeatureSpecV2> features = 2;
}

message ListStoresRequest {
    message Filter {
        // Name of desired store. Regex is not supported in this query.
        string name = 1;
    }

    Filter filter = 1;
}

message ListStoresResponse {
    repeated feast.core.Store store = 1;
}

message ApplyEntityRequest {
    // If project is unspecified, will default to 'default' project.
    // If project specified does not exist, the project would be automatically created.
    feast.core.EntitySpecV2 spec = 1;

    // Name of project that this entity belongs to.
    string project = 2;
}

message ApplyEntityResponse {
    feast.core.Entity entity = 1;
}

message GetFeastCoreVersionRequest {
}

message GetFeastCoreVersionResponse {
    string version = 1;
}

message UpdateStoreRequest {
    feast.core.Store store = 1;
}

message UpdateStoreResponse {
    enum Status {
        // Existing store config matching the given store id is identical to the given store config.
        NO_CHANGE = 0;

        // New store created or existing config updated.
        UPDATED = 1;
    }
    feast.core.Store store = 1;
    Status status = 2;
}

// Request to create a project
message CreateProjectRequest {
    // Name of project (required)
    string name = 1;
}

// Response for creation of a project
message CreateProjectResponse {
}

// Request for the archival of a project
message ArchiveProjectRequest {
    // Name of project to be archived
    string name = 1;
}

// Response for archival of a project
message ArchiveProjectResponse {
}

// Request for listing of projects
message ListProjectsRequest {
}

// Response for listing of projects
message ListProjectsResponse {
    // List of project names (archived projects are filtered out)
    repeated string projects = 1;
}

message UpdateFeatureSetStatusResponse {}

message ApplyFeatureTableRequest {
    // Optional. Name of the Project to apply the Feature Table to.
    // If unspecified, will apply FeatureTable to the default project.
    string project = 1;
    // Feature Table specification to apply
    FeatureTableSpec table_spec = 2;
}

message ApplyFeatureTableResponse {
    FeatureTable table = 1;
}

message GetFeatureTableRequest {
    // Optional. Name of the Project to retrieve the Feature Table from.
    // If unspecified, will apply FeatureTable to the default project.
    string project = 1;

    // Name of the FeatureTable to retrieve.
    string name = 2;
}

message GetFeatureTableResponse {
    // The Feature Table retrieved.
    FeatureTable table = 1;
}

message ListFeatureTablesRequest {
    message Filter {
        // Optional. Specifies the name of the project to list Feature Tables in.
        // If unspecified would list Feature Tables in the default project.
        string project = 1;

        // Optional. Feature Tables with all matching labels will be returned.
        // If unspecified would list Feature Tables without filtering by labels.
        map<string,string> labels = 3;
    }

    // Filter used when listing Feature Tables
    Filter filter = 1;
}

message ListFeatureTablesResponse {
    // List of matching Feature Tables
    repeated FeatureTable tables = 1;
}

message DeleteFeatureTableRequest {
    // Optional. Name of the Project to delete the Feature Table from.
    // If unspecified, will delete FeatureTable from the default project.
    string project = 1;

    // Name of the FeatureTable to delete.
    string name = 2;
}

message DeleteFeatureTableResponse {}
