// Copyright 2023 Greptime Team
//
// 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
//
//     http://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 greptime.v1.meta;

option go_package = "github.com/GreptimeTeam/greptime-proto/go/greptime/v1/meta";

import "greptime/v1/meta/common.proto";

service Heartbeat {
  // Heartbeat, there may be many contents of the heartbeat, such as:
  // 1. Metadata to be registered to meta server and discoverable by other
  //    nodes.
  // 2. Some performance metrics, such as Load, CPU usage, etc.
  // 3. The number of computing tasks being executed.
  rpc Heartbeat(stream HeartbeatRequest) returns (stream HeartbeatResponse) {}

  // Ask leader's endpoint.
  rpc AskLeader(AskLeaderRequest) returns (AskLeaderResponse) {}
}

message HeartbeatRequest {
  RequestHeader header = 1;
  // Self peer
  Peer peer = 2;
  // Actually reported time interval
  TimeInterval report_interval = 3;
  // Region stats on this node
  repeated RegionStat region_stats = 4;
  // Mailbox send message to Metasrv
  MailboxMessage mailbox_message = 5;
  // The duration since the heartbeat task's epoch in milliseconds.
  uint64 duration_since_epoch = 6;
  // The node's epoch
  uint64 node_epoch = 7;
  NodeInfo info = 8;
  FlowStat flow_stat = 9;
  /// The workloads of the node.
  oneof node_workloads {
    DatanodeWorkloads datanode = 10;
    FrontendWorkloads frontend = 11;
    FlownodeWorkloads flownode = 12;
  }
}

/// The workload types of the datanode.
message DatanodeWorkloads {
  repeated int32 types = 1;
}

/// The workload types of the frontend.
message FrontendWorkloads {
  repeated int32 types = 1;
}

/// The workload types of the flownode.
message FlownodeWorkloads {
  repeated int32 types = 1;
}

enum RegionRole {
  // Writable region(mito2), Readonly region(file).
  Leader = 0;
  // Readonly region.
  Follower = 1;
  // A downgrading region, which is in the process of downgrading from Leader to
  // Follower.
  //
  // This role is used to prevent the region from being written during the
  // downgrade process.
  DowngradingLeader = 2;
}

message NodeInfo {
  // The node build version
  string version = 1;
  // The node build git commit hash
  string git_commit = 2;
  // The node start timestamp
  uint64 start_time_ms = 3;
  // The CPU cores number in the node.
  uint32 cpus = 4;
}

message RegionStat {
  uint64 region_id = 1;
  // The read capacity units during this period
  int64 rcus = 2;
  // The write capacity units during this period
  int64 wcus = 3;
  // Approximate bytes of this region
  int64 approximate_bytes = 4;
  // Engine name
  string engine = 6;
  // Region role
  RegionRole role = 7;
  map<string, bytes> extensions = 99;
}

message FlowStat {
  // Each flow's in mem state's size in bytes
  // due to protobuf's key can't be a message, so we use uint32 as the key which
  // is [`FlowId`]'s inner field `id`
  map<uint32, uint64> flow_stat_size = 1;
  map<uint32, int64> flow_last_exec_time_map = 2;
}

message HeartbeatResponse {
  ResponseHeader header = 1;
  MailboxMessage mailbox_message = 2;
  RegionLease region_lease = 3;
}

// The granted region is the region that the meta server granted leases.
message GrantedRegion {
  uint64 region_id = 1;
  RegionRole role = 2;
  map<string, bytes> extensions = 99;
}

message RegionLease {
  repeated GrantedRegion regions = 1;
  uint64 duration_since_epoch = 2;
  uint64 lease_seconds = 3;
  repeated uint64 closeable_region_ids = 4;
}

message AskLeaderRequest { RequestHeader header = 1; }

message AskLeaderResponse {
  ResponseHeader header = 1;
  Peer leader = 2;
}

message MailboxMessage {
  // The id is used to associate request and response.
  uint64 id = 1;
  // The following information plays a bigger role in making messages traceable
  // and facilitating debugging.
  string subject = 2;
  string from = 3;
  string to = 4;
  // The unix timestamp in milliseconds.
  int64 timestamp_millis = 5;
  // The message body.
  oneof payload { string json = 6; }
}
