/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * license agreements; and to You under the Apache License, version 2.0:
 *
 *   https://www.apache.org/licenses/LICENSE-2.0
 *
 * This file is part of the Apache Pekko project, which was derived from Akka.
 */

/*
 * Copyright (C) 2009-2022 Lightbend Inc. <https://www.lightbend.com>
 */

syntax = "proto2";

option java_package = "org.apache.pekko.cluster.protobuf.msg";
option optimize_for = SPEED;

/****************************************
 * Cluster User Messages
 ****************************************/

/**
 * Leave
 * Sends an Address
 */

/**
 * Down
 * Sends an Address
 */

/****************************************
 * Internal Cluster Action Messages
 ****************************************/

/**
 * Join
 */
message Join {
  required UniqueAddress node = 1;
  repeated string roles = 2;
  optional string appVersion = 3;
}

/**
 * Welcome, reply to Join
 */
message Welcome {
  required UniqueAddress from = 1;
  required Gossip gossip = 2;
}

/**
 * InitJoin
 */
message InitJoin {
  optional string currentConfig = 1;
}

/**
 * InitJoinAck
 */
message InitJoinAck {
  required Address address = 1;
  required ConfigCheck configCheck = 2;
}

message ConfigCheck {
  enum Type {
    UncheckedConfig = 1;
    IncompatibleConfig = 2;
    CompatibleConfig = 3;
  }
  required Type type = 1;

  optional string clusterConfig = 2;
}

/**
 * InitJoinNack
 * Sends an Address
 */


/****************************************
 * Cluster Heartbeat Messages
 ****************************************/

/**
 * Prior to version 2.5.24
 * Heartbeat sends an Address
 * Version 2.5.24 can deserialize this message but does not send it.
 */
message Heartbeat {
  required Address from = 1;
  optional int64 sequenceNr = 2;
  optional sint64 creationTime = 3;
}

/**
 * Prior to version 2.5.24
 * HeartbeatRsp Sends an UniqueAddress
 * Version 2.5.24 can deserialize this message but does not send it.
 */
message HeartBeatResponse {
  required UniqueAddress from = 1;
  optional int64 sequenceNr = 2;
  optional int64 creationTime = 3;
}

/****************************************
 * Cluster Gossip Messages
 ****************************************/

/**
 * Gossip Envelope
 */
message GossipEnvelope {
  required UniqueAddress from = 1;
  required UniqueAddress to = 2;
  required bytes serializedGossip = 3;
}

/**
 * Gossip Status
 */
message GossipStatus {
  required UniqueAddress from = 1;
  repeated string allHashes = 2;
  required VectorClock version = 3;
  optional bytes seenDigest = 4;
}

/**
 * Gossip
 */
message Gossip {
  repeated UniqueAddress allAddresses = 1;
  repeated string allRoles = 2;
  repeated string allHashes = 3;
  repeated Member members = 4;
  required GossipOverview overview = 5;
  required VectorClock version = 6;
  repeated Tombstone tombstones = 7;
  repeated string allAppVersions = 8;
}

/**
 * Gossip Overview
 */
message GossipOverview {
  /* This is the address indexes for the nodes that have seen this gossip */
  repeated int32 seen = 1;
  repeated ObserverReachability observerReachability = 2;
}

/**
 * Reachability
 */
message ObserverReachability {
  required int32 addressIndex = 1;
  required int64 version = 4;
  repeated SubjectReachability subjectReachability = 2;
}

message SubjectReachability {
  required int32 addressIndex = 1;
  required ReachabilityStatus status = 3;
  required int64 version = 4;
}

message Tombstone {
  required int32 addressIndex = 1;
  required int64 timestamp = 2;
}

/**
 * Reachability status
 */
enum ReachabilityStatus {
  Reachable = 0;
  Unreachable = 1;
  Terminated = 2;
}


/**
 * Member
 */
message Member {
  required int32 addressIndex = 1;
  required int32 upNumber = 2;
  required MemberStatus status = 3;
  repeated int32 rolesIndexes = 4 [packed = true];
  optional int32 appVersionIndex = 5;
}

/**
 * Member Status
 */
enum MemberStatus {
  Joining = 0;
  Up = 1;
  Leaving = 2;
  Exiting = 3;
  Down = 4;
  Removed = 5;
  WeaklyUp = 6;
  PreparingForShutdown = 7;
  ReadyForShutdown = 8;
}

/**
 * Vector Clock
 */
message VectorClock {
  message Version {
    required int32 hashIndex = 1;
    required int64 timestamp = 2;
  }
  // the timestamp could be removed but left for test data compatibility
  optional int64 timestamp = 1;
  repeated Version versions = 2;
}

/****************************************
 * Common Datatypes and Messages
 ****************************************/

/**
 * An empty message
 */
message Empty {
 }

/**
 * Defines a remote address.
 */
message Address {
  required string system = 1;
  required string hostname = 2;
  required uint32 port = 3;
  optional string protocol = 4;
}

/**
 * Defines a remote address with uid.
 */
message UniqueAddress {
  required Address address = 1;
  required uint32 uid = 2;
  // 64 bit uids but with backward wire compatibility
  optional uint32 uid2 = 3;
}

/****************************************
 * Cluster routing
 ****************************************/

message ClusterRouterPool {
   required Pool pool = 1;
   required ClusterRouterPoolSettings settings = 2;
 }

message Pool {
   required uint32 serializerId = 1;
   required string manifest = 2;
   required bytes data = 3;
 }

message ClusterRouterPoolSettings {
   required uint32 totalInstances = 1;
   required uint32 maxInstancesPerNode = 2;
   required bool allowLocalRoutees = 3;
   optional string useRole = 4;
   repeated string useRoles = 5;
 }
