/agent/register
The agent, sent exactly once for the life of the container; the proxy sends exactly one answer, registered or an error, and closes the connection.
The server opens /agent/register and sends exactly one message, the
request defined below as JSON. The proxy sends exactly one message
and closes the connection. In the message, a first byte of 0 states
that the agent is registered; a first byte of 1 is followed by an
error as JSON.
- Once. The agent is fixed for the life of the container. A
registration after a successful registration is answered with an
error. A loop asked for before a registration is answered with an
error on
/agent/run. - No repetition. A registration whose path ended abruptly has an answer the server did not receive. No party retries it.
The request is defined by
diverge-provider-sdk/src/container_proxy/agent/register/request/request.rs:
//! The agent, as the request that made the container carried it.
use serde::{Deserialize, Serialize};
use serde_json::Value;
use crate::decode::Decode;
use crate::encode::{Encode, Writer};
/// The agent, handed to the container once: the
/// [`agent`](crate::endpoints::containers::agents::run::client::request::Frame::agent)
/// of the request that made it, typed to the same depth for the same
/// reason — a JSON value, because the image defines what an agent
/// is, and what the value may be is what
/// [`agent_schema`](crate::shared::containers::agent_schema) answers.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
pub struct Request {
/// The agent, as the image defines it.
pub agent: Value,
}
impl Encode for Request {
/// The ordinary JSON failure.
type Error = serde_json::Error;
fn encode(&self, out: &mut Writer<'_>) -> Result<(), Self::Error> {
serde_json::to_writer(out, self)
}
}
impl Decode<'_> for Request {
/// The ordinary JSON failure.
type Error = serde_json::Error;
fn decode(bytes: &[u8]) -> Result<Self, Self::Error> {
serde_json::from_slice(bytes)
}
}
The answer is defined by
diverge-provider-sdk/src/container_proxy/agent/register/response/frame.rs:
//! The one message on `/agent/register`.
use std::error;
use std::fmt;
use crate::decode::Decode;
use crate::encode::{Encode, Writer};
use crate::shared;
/// One frame, then the close: the agent taken, or not.
///
/// A payload leads with one byte saying which; only
/// [`Error`](Self::Error) carries anything after it.
#[derive(Debug, Clone, PartialEq)]
pub enum Frame {
/// The container holds the agent now, for its life. Tag `0`.
Registered,
/// The container refused it. Tag `1`. The agent's server's own
/// words: a value the image will not take, or an agent already
/// registered.
Error(shared::error::Error),
}
/// Tag for [`Frame::Registered`].
const REGISTERED: u8 = 0;
/// Tag for [`Frame::Error`].
const ERROR: u8 = 1;
/// A tag, and — for the error alone — that variant's own JSON.
impl Encode for Frame {
/// The ordinary JSON failure. `Registered` cannot fail at all.
type Error = serde_json::Error;
// Spelled out rather than `Self::Error`: this enum has a variant
// called `Error`, so the associated type is ambiguous by that name.
fn encode(&self, out: &mut Writer<'_>) -> Result<(), serde_json::Error> {
match self {
Frame::Registered => {
out.extend_from_slice(&[REGISTERED]);
Ok(())
}
Frame::Error(error) => {
out.extend_from_slice(&[ERROR]);
error.encode(out)
}
}
}
}
impl Decode<'_> for Frame {
/// Three ways to fail, and only one of them is JSON.
type Error = FrameError;
// Spelled out for the same reason as `encode` above.
fn decode(bytes: &[u8]) -> Result<Self, FrameError> {
let (tag, rest) = bytes.split_first().ok_or(FrameError::Empty)?;
match *tag {
REGISTERED => Ok(Frame::Registered),
ERROR => shared::error::Error::decode(rest)
.map(Frame::Error)
.map_err(FrameError::Body),
tag => Err(FrameError::UnknownTag(tag)),
}
}
}
/// A registration answer that could not be read.
#[derive(Debug)]
pub enum FrameError {
/// No bytes at all, so not even a tag.
Empty,
/// A tag that is none of this frame's two.
UnknownTag(u8),
/// The error payload after the tag did not parse.
Body(serde_json::Error),
}
impl fmt::Display for FrameError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
FrameError::Empty => f.write_str("register answer frame is empty"),
FrameError::UnknownTag(tag) => {
write!(f, "unknown register answer tag {tag}")
}
FrameError::Body(error) => {
write!(f, "register answer error did not parse: {error}")
}
}
}
}
impl error::Error for FrameError {
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
match self {
FrameError::Body(error) => Some(error),
FrameError::Empty | FrameError::UnknownTag(_) => None,
}
}
}