monarch_messages/
client.rs

1/*
2 * Copyright (c) Meta Platforms, Inc. and affiliates.
3 * All rights reserved.
4 *
5 * This source code is licensed under the BSD-style license found in the
6 * LICENSE file in the root directory of this source tree.
7 */
8
9// EnumAsInner generates code that triggers a false positive
10// unused_assignments lint on struct variant fields. #[allow] on the
11// enum itself doesn't propagate into derive-macro-generated code, so
12// the suppression must be at module scope.
13#![allow(unused_assignments)]
14
15use enum_as_inner::EnumAsInner;
16use hyperactor::HandleClient;
17use hyperactor::Handler;
18use hyperactor::RefClient;
19use hyperactor::reference;
20use serde::Deserialize;
21use serde::Serialize;
22use typeuri::Named;
23
24use crate::controller::DeviceFailure;
25use crate::controller::Seq;
26use crate::controller::WorkerError;
27use crate::debugger::DebuggerAction;
28
29/// An exception to commanded execution, exposed to the client.
30#[derive(
31    Debug,
32    Clone,
33    Serialize,
34    Deserialize,
35    PartialEq,
36    thiserror::Error,
37    EnumAsInner
38)]
39pub enum Exception {
40    /// A failure is a non-deterministic problem with the underlying device
41    /// or its infrastructure. For example, a controller may enter a crash loop,
42    /// or its GPU may be lost
43    #[error("failure: {0}")]
44    Failure(#[from] DeviceFailure),
45
46    /// A deterministic problem with the user's code. For example, an OOM
47    /// resulting in trying to allocate too much GPU memory, or violating
48    /// some invariant enforced by the various APIs.
49    #[error("WorkerError: seq: {0}, error: {1}")]
50    Error(Seq, Seq, WorkerError),
51}
52
53/// Log levels for ClientMessage::Log.
54#[derive(Debug, Deserialize, Clone, Serialize)]
55pub enum LogLevel {
56    /// Log with severity INFO
57    Info,
58
59    /// Log with severity WARNING
60    Warn,
61
62    /// Log with severity ERROR
63    Error,
64}
65
66/// Client messages. These define the messages that the controller can
67/// send to the client. The actual handling of these messages will be
68/// defined on the python side in the client implementation.
69// TODO: Potentially just create a Client derive macro that can be used
70// to just generate the client code without generating the handler for
71// cases where the actor will be implemented in a different language over
72// ffi.
73#[derive(
74    Handler,
75    HandleClient,
76    RefClient,
77    Serialize,
78    Deserialize,
79    Debug,
80    Clone,
81    EnumAsInner,
82    Named
83)]
84pub enum ClientMessage {
85    /// A fetched result of an invoked operation.
86    Result {
87        seq: Seq,
88        result: Option<Result<wirevalue::Any, Exception>>,
89    },
90
91    /// Notify the client of an event.
92    Log { level: LogLevel, message: String },
93
94    /// Notify the client of a debugger event.
95    DebuggerMessage {
96        /// The actor id of the debugger.
97        debugger_actor_id: reference::ActorId,
98        /// The action to take.
99        action: DebuggerAction,
100    },
101}
102
103hyperactor::behavior!(ClientActor, ClientMessage);