mz_compute_client/protocol.rs
1// Copyright Materialize, Inc. and contributors. All rights reserved.
2//
3// Use of this software is governed by the Business Source License
4// included in the LICENSE file.
5//
6// As of the Change Date specified in that file, in accordance with
7// the Business Source License, use of this software will be governed
8// by the Apache License, Version 2.0.
9
10//! The compute protocol defines the communication between the compute controller and indiviual
11//! compute replicas.
12//!
13//! # Overview
14//!
15//! The compute protocol consists of [`ComputeCommand`]s and [`ComputeResponse`]s.
16//! [`ComputeCommand`]s are sent from the compute controller to the replicas and instruct the
17//! receivers to perform some action. [`ComputeResponse`]s are sent in the opposite direction and
18//! inform the receiver about status changes of their senders.
19//!
20//! The compute protocol is an asynchronous protocol. Both participants must expect and be able to
21//! gracefully handle messages that don’t reflect the state of the world described by the messages
22//! they have previously sent. In other words, messages sent take effect only eventually. For
23//! example, after the compute controller has instructed the replica to cancel a peek (by sending a
24//! [`CancelPeek`] command, it must still be ready to accept non-[`Canceled`] responses to the
25//! peek. Similarly, if a replica receives a [`CancelPeek`] command for a peek it has already
26//! answered, it must handle that command gracefully (e.g., by ignoring it).
27//!
28//! While the protocol does not provide any guarantees about the delay between sending a message
29//! and it being received and processed, it does guarantee that messages are delivered in the same
30//! order they are sent in. For example, if the compute controller sends a [`Peek`] command
31//! followed by a [`CancelPeek`] command, it is guaranteed that [`CancelPeek`] is only received by
32//! the replica after the [`Peek`] command.
33//!
34//! # Message Transport and Encoding
35//!
36//! To initiate communication, the replica starts listening on a known host and port, to which the
37//! compute controller then connects. A Cluster Transport Protocol (CTP) connection is established
38//! that allows both peers to stream bincode-encoded messages.
39//!
40//! # Protocol Stages
41//!
42//! The compute protocol consists of four stages that must be transitioned in order:
43//!
44//! 1. Creation
45//! 2. Initialization
46//! 3. Computation (read-only)
47//! 4. Computation (read-write)
48//!
49//! ## Creation Stage
50//!
51//! The creation stage is the first stage of the compute protocol. It is initiated by the
52//! successful establishment of a CTP connection between compute controller and replica. In this
53//! stage, the compute controller must send two creation commands in order:
54//!
55//! 1. A [`Hello`] command, which provides the replica with connection metadata.
56//! 2. A [`CreateInstance`] command, which instructs the replica to initialize the rest of its
57//! state.
58//!
59//! The replica must not send any responses.
60//!
61//! ## Initialization Stage
62//!
63//! The initialization stage begins as soon as the compute controller has sent the
64//! [`CreateInstance`] command. In this stage, the compute controller informs the replica about its
65//! expected dataflow state. It does so by sending any number of [computation
66//! commands](#computation-stage), followed by an [`InitializationComplete`] command, which marks
67//! the end of the initialization stage.
68//!
69//! Upon receiving computation commands during the initialization phase, the replica is obligated
70//! to ensure its state matches what is requested through the commands. It is up to the replica
71//! whether it ensures that by initializing new state or by reusing existing state (through a
72//! reconciliation process).
73//!
74//! The replica may send responses to computation commands it receives. It may also opt to defer
75//! sending responses to the computation stages instead.
76//!
77//! ## Computation Stage (read-only)
78//!
79//! This computation stage begins as soon as the compute controller has sent the
80//! [`InitializationComplete`] command. In this stage, the compute controller instructs the replica
81//! to create and maintain dataflows, and to perform peeks on indexes exported by dataflows.
82//!
83//! While in the read-only computation stage, the replica must not affect
84//! changes to external systems (writes). For the most part this means it cannot
85//! write to persist. The replica can transition out of the read-only stage when
86//! receiving an [`AllowWrites`] command.
87//!
88//! The compute controller may send any number of computation commands:
89//!
90//! - [`CreateDataflow`]
91//! - [`Schedule`]
92//! - [`AllowCompaction`]
93//! - [`Peek`]
94//! - [`CancelPeek`]
95//! - [`UpdateConfiguration`]
96//!
97//! The compute controller must respect dependencies between commands. For example, it must send a
98//! [`CreateDataflow`] command before it sends [`AllowCompaction`] or [`Peek`] commands that target
99//! the created dataflow.
100//!
101//! The replica must send the required responses to computation commands. This includes commands it
102//! has received in the initialization phase that have not already been responded to.
103//!
104//! ## Computation Stage (read-write)
105//!
106//! The read-write computation stage is exactly like the read-only computation stage, with the
107//! addition that now the replica _can_ affect writes to external systems. This stage begins once
108//! the controller has sent the [`AllowWrites`] command.
109//!
110//! The replica cannot transition back to the read-only computation stage from the read-write stage.
111//!
112//! [`ComputeCommand`]: self::command::ComputeCommand
113//! [`Hello`]: self::command::ComputeCommand::Hello
114//! [`CreateInstance`]: self::command::ComputeCommand::CreateInstance
115//! [`InitializationComplete`]: self::command::ComputeCommand::InitializationComplete
116//! [`CreateDataflow`]: self::command::ComputeCommand::CreateDataflow
117//! [`Schedule`]: self::command::ComputeCommand::Schedule
118//! [`AllowCompaction`]: self::command::ComputeCommand::AllowCompaction
119//! [`AllowWrites`]: self::command::ComputeCommand::AllowWrites
120//! [`Peek`]: self::command::ComputeCommand::Peek
121//! [`CancelPeek`]: self::command::ComputeCommand::CancelPeek
122//! [`UpdateConfiguration`]: self::command::ComputeCommand::UpdateConfiguration
123//! [`ComputeResponse`]: self::response::ComputeResponse
124//! [`Canceled`]: self::response::PeekResponse::Canceled
125//! [`SubscribeResponse::DroppedAt`]: self::response::SubscribeResponse::DroppedAt
126
127pub mod command;
128pub mod history;
129pub mod response;