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

option java_package = "akka.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;
}

/**
 * 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 {
  extensions 100 to 102;

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

  optional string clusterConfig = 2;
}

message UncheckedConfig {
  extend ConfigCheck {
    required UncheckedConfig checkConfig = 100;
  }
}

message IncompatibleConfig {
  extend ConfigCheck {
    required IncompatibleConfig checkConfig = 101;
  }
}

message CompatibleConfig {
  extend ConfigCheck {
    required CompatibleConfig checkConfig = 102;
  }
  required string clusterConfig = 2;
}

/**
 * InitJoinNack
 * Sends an Address
 */


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

/**
 * Heartbeat
 * Sends an Address
 */

/**
 * HeartbeatRsp
 * Sends an UniqueAddress
 */

/****************************************
 * 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;
}

/**
 * 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;
}

/**
 * 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];
}

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

/**
 * 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;
 }