syntax="proto3";

import "google/protobuf/any.proto";
import "minknow/rpc/rpc_options.proto";

package ont.rpc.keystore;

// Allows arbitrary data to be associated with this MinKNOW instance.
//
// This can be used by the protocol to communicate information to the outside world (including a
// user interface), for example.
//
// Value names should be stored in the form <product>:<name>, where <product> is the name of the
// product that has decided what form the value should take (generally either the software that is
// setting the value, or the software that is consuming it).
//
// In particular, the prefixes "minknow:", "bream:", "protocol:" and "gui:" are reserved for MinKNOW
// and the software that ships with MinKNOW. Names starting with ":" are also reserved for
// "well-known" values that will be listed in this or related documentation.
service KeyStoreService {
    // Store one or more values.
    //
    // Anyone watching those values will be notified of the change. If they are watching several of
    // the values in a single watch() call, all the updates will be sent in a single message.
    rpc store (StoreRequest) returns (StoreResponse) {}

    // Remove a value from the store.
    rpc remove (RemoveRequest) returns (RemoveResponse) {}

    // Get a single value.
    //
    // This is a convenient alternative to get() when you only want a single value. If you want
    // multiple values, it is more efficient to request them all in a single get() call.
    //
    // If the requested value is not in the store, this will return an error.
    rpc get_one (GetOneRequest) returns (GetOneResponse) {}

    // Get any number of values.
    rpc get (GetRequest) returns (GetResponse) {}

    // Watch for values being updates.
    //
    // On calling this, you will get a message containing the current values, and then messages with
    // updates as and when store() is called. The updates will only contain those values that
    // changed.
    rpc watch (WatchRequest) returns (stream WatchResponse) {}
}

enum Lifetime {
    // Automatically remove the value next time a protocol starts.
    UNTIL_NEXT_PROTOCOL_START = 0;

    // Automatically remove the value next time a protocol ends.
    UNTIL_PROTOCOL_END = 1;

    // Keep the value until the MinKNOW instance terminates.
    //
    // Be careful when using this value, as there is a maximum amount of data that can be stored.
    UNTIL_INSTANCE_END = 2;
}

message StoreRequest {
    // The values to store.
    //
    // See the notes in the KeyStore service documentation about names - in short, for any values
    // not documented elsewhere, you should be prefixing the name with "<product>:", where <product>
    // is the name of your software product.
    map<string, google.protobuf.Any> values = 1 [(rpc_required) = true];

    // Specify the lifetime of a value.
    //
    // Note that calling remove() will remove the value regardless of this setting.
    Lifetime lifetime = 2;
}

message StoreResponse {
}

message RemoveRequest {
    // The names of the values you wish to remove.
    repeated string names = 1 [(rpc_required) = true];

    // Whether to allow missing values.
    //
    // If set, names that are not present in the store will be ignored, but any present values will
    // still be removed. Otherwise, missing values will cause an error to be returned (in which case
    // nothing will be removed).
    //
    // Defaults to 'false'
    bool allow_missing = 2;
}

message RemoveResponse {
}

message GetOneRequest {
    // The name of the value to fetch.
    string name = 1 [(rpc_required) = true];
}

message GetOneResponse {
    // The requested value.
    google.protobuf.Any value = 2;
}

message GetRequest {
    // The names of the values you wish to fetch.
    repeated string names = 1;

    // Whether to allow missing values.
    //
    // If set, names that are not present in the store will simply be omitted from the response.
    // Otherwise, missing values will cause an error to be returned.
    //
    // Defaults to 'false'
    bool allow_missing = 2;
}

message GetResponse {
    // The requested values.
    map<string, google.protobuf.Any> values = 1;
}

message WatchRequest {
    // The names of the values you wish to watch.
    repeated string names = 1 [(rpc_required) = true];

    // Whether to allow missing values.
    //
    // If set, names that are not present in the store will be omitted from the first response, but
    // will still be watched. If and when they are added, a message will be sent with the set
    // values. Otherwise, missing values will cause an immediate error.
    //
    // Defaults to 'false'
    bool allow_missing = 2;
}

message WatchResponse {
    // The values that have changed.
    //
    // The first received message will contain the current state of all the watched values.
    // Subsequent messages will only contain the values that changed.
    map<string, google.protobuf.Any> values = 1;

    // The values that have been removed.
    repeated string removed_values = 2;
}
