@@ -34,79 +34,169 @@ use std::sync::LazyLock;
34
34
use std:: sync:: RwLock ;
35
35
use std:: time:: Duration ;
36
36
37
+ use serde:: Deserialize ;
38
+ use serde:: Serialize ;
37
39
use shell_quote:: QuoteRefExt ;
38
40
41
+ use crate as hyperactor;
39
42
use crate :: attrs:: AttrKeyInfo ;
43
+ use crate :: attrs:: AttrValue ;
40
44
use crate :: attrs:: Attrs ;
41
45
use crate :: attrs:: SerializableValue ;
42
46
use crate :: attrs:: declare_attrs;
43
- use crate :: data:: Encoding ;
47
+ use crate :: data:: Encoding ; // for macros
48
+
49
+ /// Metadata describing how a configuration key is exposed across
50
+ /// environments.
51
+ ///
52
+ /// Each `ConfigAttr` entry defines how a Rust configuration key maps
53
+ /// to external representations:
54
+ /// - `env_name`: the environment variable consulted by
55
+ /// [`init_from_env()`] when loading configuration.
56
+ /// - `py_name`: the Python keyword argument accepted by
57
+ /// `monarch.configure(...)` and returned by `get_configuration()`.
58
+ ///
59
+ /// All configuration keys should carry this meta-attribute via
60
+ /// `@meta(CONFIG = ConfigAttr { ... })`.
61
+ #[ derive( Clone , Debug , Serialize , Deserialize , hyperactor:: Named ) ]
62
+ pub struct ConfigAttr {
63
+ /// Environment variable consulted by `init_from_env()`.
64
+ pub env_name : Option < String > ,
65
+
66
+ /// Python kwarg name used by `monarch.configure(...)` and
67
+ /// `get_configuration()`.
68
+ pub py_name : Option < String > ,
69
+ }
70
+
71
+ impl AttrValue for ConfigAttr {
72
+ fn display ( & self ) -> String {
73
+ serde_json:: to_string ( self ) . unwrap_or_else ( |_| "<invalid ConfigAttr>" . into ( ) )
74
+ }
75
+ fn parse ( s : & str ) -> Result < Self , anyhow:: Error > {
76
+ Ok ( serde_json:: from_str ( s) ?)
77
+ }
78
+ }
44
79
45
80
// Declare configuration keys using the new attrs system with defaults
46
81
declare_attrs ! {
47
- /// This is a meta-attribute specifying the environment variable used by the configuration
48
- /// key.
49
- pub attr CONFIG_ENV_VAR : String ;
50
-
51
- /// This is a meta-attribute specifying the name of the kwarg to pass to monarch.configure()
52
- /// to set the attribute value in the global config.
53
- pub attr PYTHON_CONFIG_KEY : String ;
82
+ /// This is a meta-attribute marking a configuration key.
83
+ ///
84
+ /// It carries metadata used to bridge Rust, environment
85
+ /// variables, and Python:
86
+ /// - `env_name`: environment variable name consulted by
87
+ /// `init_from_env()`.
88
+ /// - `py_name`: keyword argument name recognized by
89
+ /// `monarch.configure(...)`.
90
+ ///
91
+ /// All configuration keys should be annotated with this
92
+ /// attribute.
93
+ pub attr CONFIG : ConfigAttr ;
94
+
95
+ // /// This is a meta-attribute specifying the environment variable used by the configuration
96
+ // /// key.
97
+ // pub attr CONFIG_ENV_VAR: String;
98
+ //
99
+ // /// This is a meta-attribute specifying the name of the kwarg to pass to monarch.configure()
100
+ // /// to set the attribute value in the global config.
101
+ // pub attr PYTHON_CONFIG_KEY: String;
54
102
55
103
/// Maximum frame length for codec
56
- @meta( CONFIG_ENV_VAR = "HYPERACTOR_CODEC_MAX_FRAME_LENGTH" . to_string( ) )
104
+ @meta( CONFIG = ConfigAttr {
105
+ env_name: Some ( "HYPERACTOR_CODEC_MAX_FRAME_LENGTH" . to_string( ) ) ,
106
+ py_name: None ,
107
+ } )
57
108
pub attr CODEC_MAX_FRAME_LENGTH : usize = 10 * 1024 * 1024 * 1024 ; // 10 GiB
58
109
59
110
/// Message delivery timeout
60
- @meta( CONFIG_ENV_VAR = "HYPERACTOR_MESSAGE_DELIVERY_TIMEOUT" . to_string( ) )
111
+ @meta( CONFIG = ConfigAttr {
112
+ env_name: Some ( "HYPERACTOR_MESSAGE_DELIVERY_TIMEOUT" . to_string( ) ) ,
113
+ py_name: None ,
114
+ } )
61
115
pub attr MESSAGE_DELIVERY_TIMEOUT : Duration = Duration :: from_secs( 30 ) ;
62
116
63
117
/// Timeout used by allocator for stopping a proc.
64
- @meta( CONFIG_ENV_VAR = "HYPERACTOR_PROCESS_EXIT_TIMEOUT" . to_string( ) )
118
+ @meta( CONFIG = ConfigAttr {
119
+ env_name: Some ( "HYPERACTOR_PROCESS_EXIT_TIMEOUT" . to_string( ) ) ,
120
+ py_name: None ,
121
+ } )
65
122
pub attr PROCESS_EXIT_TIMEOUT : Duration = Duration :: from_secs( 10 ) ;
66
123
67
124
/// Message acknowledgment interval
68
- @meta( CONFIG_ENV_VAR = "HYPERACTOR_MESSAGE_ACK_TIME_INTERVAL" . to_string( ) )
125
+ @meta( CONFIG = ConfigAttr {
126
+ env_name: Some ( "HYPERACTOR_MESSAGE_ACK_TIME_INTERVAL" . to_string( ) ) ,
127
+ py_name: None ,
128
+ } )
69
129
pub attr MESSAGE_ACK_TIME_INTERVAL : Duration = Duration :: from_millis( 500 ) ;
70
130
71
131
/// Number of messages after which to send an acknowledgment
72
- @meta( CONFIG_ENV_VAR = "HYPERACTOR_MESSAGE_ACK_EVERY_N_MESSAGES" . to_string( ) )
132
+ @meta( CONFIG = ConfigAttr {
133
+ env_name: Some ( "HYPERACTOR_MESSAGE_ACK_EVERY_N_MESSAGES" . to_string( ) ) ,
134
+ py_name: None ,
135
+ } )
73
136
pub attr MESSAGE_ACK_EVERY_N_MESSAGES : u64 = 1000 ;
74
137
75
138
/// Default hop Time-To-Live for message envelopes.
76
- @meta( CONFIG_ENV_VAR = "HYPERACTOR_MESSAGE_TTL_DEFAULT" . to_string( ) )
139
+ @meta( CONFIG = ConfigAttr {
140
+ env_name: Some ( "HYPERACTOR_MESSAGE_TTL_DEFAULT" . to_string( ) ) ,
141
+ py_name: None ,
142
+ } )
77
143
pub attr MESSAGE_TTL_DEFAULT : u8 = 64 ;
78
144
79
145
/// Maximum buffer size for split port messages
80
- @meta( CONFIG_ENV_VAR = "HYPERACTOR_SPLIT_MAX_BUFFER_SIZE" . to_string( ) )
146
+ @meta( CONFIG = ConfigAttr {
147
+ env_name: Some ( "HYPERACTOR_SPLIT_MAX_BUFFER_SIZE" . to_string( ) ) ,
148
+ py_name: None ,
149
+ } )
81
150
pub attr SPLIT_MAX_BUFFER_SIZE : usize = 5 ;
82
151
83
152
/// The maximum time an update can be buffered before being reduced.
84
- @meta( CONFIG_ENV_VAR = "HYPERACTOR_SPLIT_MAX_BUFFER_AGE" . to_string( ) )
153
+ @meta( CONFIG = ConfigAttr {
154
+ env_name: Some ( "HYPERACTOR_SPLIT_MAX_BUFFER_AGE" . to_string( ) ) ,
155
+ py_name: None ,
156
+ } )
85
157
pub attr SPLIT_MAX_BUFFER_AGE : Duration = Duration :: from_millis( 50 ) ;
86
158
87
159
/// Timeout used by proc mesh for stopping an actor.
88
- @meta( CONFIG_ENV_VAR = "HYPERACTOR_STOP_ACTOR_TIMEOUT" . to_string( ) )
160
+ @meta( CONFIG = ConfigAttr {
161
+ env_name: Some ( "HYPERACTOR_STOP_ACTOR_TIMEOUT" . to_string( ) ) ,
162
+ py_name: None ,
163
+ } )
89
164
pub attr STOP_ACTOR_TIMEOUT : Duration = Duration :: from_secs( 1 ) ;
90
165
91
166
/// Heartbeat interval for remote allocator
92
- @meta( CONFIG_ENV_VAR = "HYPERACTOR_REMOTE_ALLOCATOR_HEARTBEAT_INTERVAL" . to_string( ) )
167
+ @meta( CONFIG = ConfigAttr {
168
+ env_name: Some ( "HYPERACTOR_REMOTE_ALLOCATOR_HEARTBEAT_INTERVAL" . to_string( ) ) ,
169
+ py_name: None ,
170
+ } )
93
171
pub attr REMOTE_ALLOCATOR_HEARTBEAT_INTERVAL : Duration = Duration :: from_secs( 5 ) ;
94
172
95
173
/// The default encoding to be used.
96
- @meta( CONFIG_ENV_VAR = "HYPERACTOR_DEFAULT_ENCODING" . to_string( ) )
174
+ @meta( CONFIG = ConfigAttr {
175
+ env_name: Some ( "HYPERACTOR_DEFAULT_ENCODING" . to_string( ) ) ,
176
+ py_name: None ,
177
+ } )
97
178
pub attr DEFAULT_ENCODING : Encoding = Encoding :: Multipart ;
98
179
99
180
/// Whether to use multipart encoding for network channel communications.
100
- @meta( CONFIG_ENV_VAR = "HYPERACTOR_CHANNEL_MULTIPART" . to_string( ) )
181
+ @meta( CONFIG = ConfigAttr {
182
+ env_name: Some ( "HYPERACTOR_CHANNEL_MULTIPART" . to_string( ) ) ,
183
+ py_name: None ,
184
+ } )
101
185
pub attr CHANNEL_MULTIPART : bool = true ;
102
186
103
187
/// How often to check for full MSPC channel on NetRx.
104
- @meta( CONFIG_ENV_VAR = "HYPERACTOR_CHANNEL_NET_RX_BUFFER_FULL_CHECK_INTERVAL" . to_string( ) )
188
+ @meta( CONFIG = ConfigAttr {
189
+ env_name: Some ( "HYPERACTOR_CHANNEL_NET_RX_BUFFER_FULL_CHECK_INTERVAL" . to_string( ) ) ,
190
+ py_name: None ,
191
+ } )
105
192
pub attr CHANNEL_NET_RX_BUFFER_FULL_CHECK_INTERVAL : Duration = Duration :: from_secs( 5 ) ;
106
193
107
194
/// Sampling rate for logging message latency
108
195
/// Set to 0.01 for 1% sampling, 0.1 for 10% sampling, 0.90 for 90% sampling, etc.
109
- @meta( CONFIG_ENV_VAR = "HYPERACTOR_MESSAGE_LATENCY_SAMPLING_RATE" . to_string( ) )
196
+ @meta( CONFIG = ConfigAttr {
197
+ env_name: Some ( "HYPERACTOR_MESSAGE_LATENCY_SAMPLING_RATE" . to_string( ) ) ,
198
+ py_name: None ,
199
+ } )
110
200
pub attr MESSAGE_LATENCY_SAMPLING_RATE : f32 = 0.01 ;
111
201
112
202
/// Whether to enable client sequence assignment.
@@ -116,7 +206,10 @@ declare_attrs! {
116
206
///
117
207
/// Default: 10 seconds. If set to zero, disables the timeout and
118
208
/// waits indefinitely.
119
- @meta( CONFIG_ENV_VAR = "HYPERACTOR_HOST_SPAWN_READY_TIMEOUT" . to_string( ) )
209
+ @meta( CONFIG = ConfigAttr {
210
+ env_name: Some ( "HYPERACTOR_HOST_SPAWN_READY_TIMEOUT" . to_string( ) ) ,
211
+ py_name: None ,
212
+ } )
120
213
pub attr HOST_SPAWN_READY_TIMEOUT : Duration = Duration :: from_secs( 10 ) ;
121
214
}
122
215
@@ -134,9 +227,14 @@ pub fn from_env() -> Attrs {
134
227
}
135
228
136
229
for key in inventory:: iter :: < AttrKeyInfo > ( ) {
137
- let Some ( env_var) = key. meta . get ( CONFIG_ENV_VAR ) else {
230
+ // New: look up CONFIG, then env_name inside it
231
+ let Some ( cfg_meta) = key. meta . get ( CONFIG ) else {
138
232
continue ;
139
233
} ;
234
+ let Some ( env_var) = cfg_meta. env_name . as_deref ( ) else {
235
+ continue ;
236
+ } ;
237
+
140
238
let Ok ( val) = env:: var ( env_var) else {
141
239
// Default value
142
240
output. push_str ( "# " ) ;
0 commit comments