syntax = "proto3";

// Cross-node checkpoint barrier synchronization (two-phase commit).
// Replaces the gossip-KV announce/ack/poll protocol in
// `crates/laminar-core/src/cluster/control/barrier.rs` with direct
// leader-to-follower RPCs, removing the 50ms quorum-polling busy-wait:
// the leader fans Prepare out to every follower and awaits the replies.
//
// The 2PC phase is carried by the RPC method (Prepare / Commit / Abort)
// rather than a redundant enum field; `Ack` is the shared reply.
//
// Code is generated by tonic-build (see this crate's build.rs).
package laminar.barrier.v1;

service BarrierSync {
  // Phase 1. Snapshot state and pre-commit sinks, then report
  // readiness. The follower returns its local watermark so the leader
  // can fold a cluster-wide minimum for the matching Commit.
  rpc Prepare(PrepareRequest) returns (Ack);

  // Phase 2 (success). The durability gate passed cluster-wide; commit
  // sinks. Carries the cluster-wide minimum watermark.
  rpc Commit(CommitRequest) returns (Ack);

  // Phase 2 (failure). Some peer's Prepare failed; roll back the
  // in-flight checkpoint.
  rpc Abort(AbortRequest) returns (Ack);
}

message PrepareRequest {
  uint64 epoch = 1;
  uint64 checkpoint_id = 2;
  // Reserved for unaligned / other barrier flags (mirrors
  // `BarrierAnnouncement.flags`).
  uint64 flags = 3;
}

message CommitRequest {
  uint64 epoch = 1;
  uint64 checkpoint_id = 2;
  uint64 flags = 3;
  // Cluster-wide minimum watermark (event-time units) computed by the
  // leader from the Prepare acks. Absent when no node has a watermark
  // yet (treated as +infinity).
  optional int64 min_watermark_ms = 4;
}

message AbortRequest {
  uint64 epoch = 1;
  uint64 checkpoint_id = 2;
  uint64 flags = 3;
}

// Follower reply to any phase. Mirrors `BarrierAck`.
message Ack {
  uint64 epoch = 1;
  // false = the local snapshot/commit failed; the leader should abort.
  bool ok = 2;
  // Populated only when ok = false.
  optional string error = 3;
  // The follower's local watermark at ack time; absent when unset
  // (fresh boot, no source events yet).
  optional int64 local_watermark_ms = 4;
}
