@@ -3,7 +3,7 @@ use chirp_workflow::prelude::*;
3
3
use cluster:: types:: BuildDeliveryMethod ;
4
4
use fdb_util:: SERIALIZABLE ;
5
5
use foundationdb:: { self as fdb, options:: StreamingMode } ;
6
- use futures_util:: TryStreamExt ;
6
+ use futures_util:: StreamExt ;
7
7
use pegboard:: protocol;
8
8
use rivet_api:: models;
9
9
use serde_json:: json;
@@ -18,51 +18,22 @@ pub async fn prewarm_image(
18
18
) -> GlobalResult < serde_json:: Value > {
19
19
ctx. auth ( ) . bypass ( ) ?;
20
20
21
- let client_id = ctx
22
- . fdb ( )
23
- . await ?
24
- . run ( |tx, _mc| async move {
25
- let alloc_idx_subspace = pegboard:: keys:: subspace ( )
26
- . subspace ( & pegboard:: keys:: datacenter:: ClientsByRemainingMemKey :: entire_subspace ( ) ) ;
27
- let ping_threshold_ts =
28
- util:: timestamp:: now ( ) - pegboard:: workflows:: client:: CLIENT_ELIGIBLE_THRESHOLD_MS ;
29
-
30
- let mut stream = tx. get_ranges_keyvalues (
31
- fdb:: RangeOption {
32
- mode : StreamingMode :: Iterator ,
33
- ..( & alloc_idx_subspace) . into ( )
34
- } ,
35
- SERIALIZABLE ,
36
- ) ;
37
-
38
- while let Some ( entry) = stream. try_next ( ) . await ? {
39
- let key = pegboard:: keys:: subspace ( )
40
- . unpack :: < pegboard:: keys:: datacenter:: ClientsByRemainingMemKey > ( entry. key ( ) )
41
- . map_err ( |x| fdb:: FdbBindingError :: CustomError ( x. into ( ) ) ) ?;
42
-
43
- // Scan by last ping
44
- if key. last_ping_ts < ping_threshold_ts {
45
- continue ;
46
- }
47
-
48
- return Ok ( Some ( key. client_id ) ) ;
49
- }
50
-
51
- Ok ( None )
52
- } )
53
- . custom_instrument ( tracing:: info_span!( "prewarm_fetch_tx" ) )
54
- . await ?;
55
-
56
- let Some ( client_id) = client_id else {
57
- tracing:: error!( "no eligible clients found to prewarm image" ) ;
58
- return Ok ( json ! ( { } ) ) ;
59
- } ;
60
-
61
21
let dc_id = ctx. config ( ) . server ( ) ?. rivet . edge ( ) ?. datacenter_id ;
62
- let ( dc_res, builds_res) = tokio:: try_join!(
22
+ let ( dc_res, servers_res , builds_res) = tokio:: try_join!(
63
23
ctx. op( cluster:: ops:: datacenter:: get:: Input {
64
24
datacenter_ids: vec![ dc_id] ,
65
25
} ) ,
26
+ ctx. op( cluster:: ops:: server:: list:: Input {
27
+ filter: cluster:: types:: Filter {
28
+ datacenter_ids: Some ( vec![ dc_id] ) ,
29
+ pool_types: Some ( vec![ cluster:: types:: PoolType :: Ats ] ) ,
30
+ ..Default :: default ( )
31
+ } ,
32
+ include_destroyed: false ,
33
+ exclude_installing: true ,
34
+ exclude_draining: true ,
35
+ exclude_no_vlan: true ,
36
+ } ) ,
66
37
ctx. op( build:: ops:: get:: Input {
67
38
build_ids: vec![ image_id] ,
68
39
} ) ,
@@ -77,45 +48,47 @@ pub async fn prewarm_image(
77
48
return Ok ( json ! ( { } ) ) ;
78
49
} ;
79
50
80
- // Get the artifact size
81
- let uploads_res = op ! ( [ ctx] upload_get {
82
- upload_ids: vec![ build. upload_id. into( ) ] ,
83
- } )
84
- . await ?;
85
- let upload = unwrap ! ( uploads_res. uploads. first( ) ) ;
86
- let artifact_size_bytes = upload. content_length ;
87
-
88
- let res = ctx
89
- . signal ( pegboard:: workflows:: client:: PrewarmImage2 {
90
- image : protocol:: Image {
91
- id : image_id,
92
- artifact_url_stub : pegboard:: util:: image_artifact_url_stub (
93
- ctx. config ( ) ,
94
- build. upload_id ,
95
- & build:: utils:: file_name ( build. kind , build. compression ) ,
96
- ) ?,
97
- // We will never need to fall back to fetching directly from S3. This short
98
- // circuits earlier in the fn.
99
- fallback_artifact_url : None ,
100
- artifact_size_bytes,
101
- kind : build. kind . into ( ) ,
102
- compression : build. compression . into ( ) ,
103
- } ,
104
- } )
105
- . to_workflow :: < pegboard:: workflows:: client:: Workflow > ( )
106
- . tag ( "client_id" , client_id)
107
- . send ( )
108
- . await ;
109
-
110
- if let Some ( WorkflowError :: WorkflowNotFound ) = res. as_workflow_error ( ) {
111
- tracing:: warn!(
112
- ?client_id,
113
- "client workflow not found, likely already stopped"
114
- ) ;
115
- } else {
116
- res?;
51
+ if servers_res. servers . is_empty ( ) {
52
+ tracing:: warn!( ?dc_id, "no ats nodes to prewarm" ) ;
117
53
}
118
54
55
+ let artifact_url_stub = pegboard:: util:: image_artifact_url_stub (
56
+ ctx. config ( ) ,
57
+ build. upload_id ,
58
+ & build:: utils:: file_name ( build. kind , build. compression ) ,
59
+ ) ?;
60
+ let client = rivet_pools:: reqwest:: client ( ) . await ?;
61
+
62
+ futures_util:: stream:: iter (
63
+ servers_res
64
+ . servers
65
+ . into_iter ( )
66
+ . flat_map ( |server| server. lan_ip . map ( |lan_ip| ( server, lan_ip) ) ) ,
67
+ )
68
+ . map ( |( server, lan_ip) | {
69
+ let artifact_url_stub = artifact_url_stub. clone ( ) ;
70
+ let client = client. clone ( ) ;
71
+
72
+ async move {
73
+ if let Err ( err) = client
74
+ . get ( format ! ( "http://{}:8080{}" , lan_ip, & artifact_url_stub) )
75
+ . send ( )
76
+ . await
77
+ . and_then ( |res| res. error_for_status ( ) )
78
+ {
79
+ tracing:: error!(
80
+ ?err,
81
+ server_id=?server. server_id,
82
+ build_id=?build. build_id,
83
+ "failed prewarming" ,
84
+ ) ;
85
+ }
86
+ }
87
+ } )
88
+ . buffer_unordered ( 16 )
89
+ . collect :: < ( ) > ( )
90
+ . await ;
91
+
119
92
Ok ( json ! ( { } ) )
120
93
}
121
94
@@ -171,43 +144,3 @@ pub async fn toggle_drain_client(
171
144
172
145
Ok ( json ! ( { } ) )
173
146
}
174
-
175
- async fn resolve_image_fallback_artifact_url (
176
- ctx : & Ctx < Auth > ,
177
- dc_build_delivery_method : BuildDeliveryMethod ,
178
- build : & build:: types:: Build ,
179
- ) -> GlobalResult < Option < String > > {
180
- if let BuildDeliveryMethod :: S3Direct = dc_build_delivery_method {
181
- tracing:: debug!( "using s3 direct delivery" ) ;
182
-
183
- // Build client
184
- let s3_client = s3_util:: Client :: with_bucket_and_endpoint (
185
- ctx. config ( ) ,
186
- "bucket-build" ,
187
- s3_util:: EndpointKind :: EdgeInternal ,
188
- )
189
- . await ?;
190
-
191
- let presigned_req = s3_client
192
- . get_object ( )
193
- . bucket ( s3_client. bucket ( ) )
194
- . key ( format ! (
195
- "{upload_id}/{file_name}" ,
196
- upload_id = build. upload_id,
197
- file_name = build:: utils:: file_name( build. kind, build. compression) ,
198
- ) )
199
- . presigned (
200
- s3_util:: aws_sdk_s3:: presigning:: PresigningConfig :: builder ( )
201
- . expires_in ( std:: time:: Duration :: from_secs ( 15 * 60 ) )
202
- . build ( ) ?,
203
- )
204
- . await ?;
205
-
206
- let addr_str = presigned_req. uri ( ) . to_string ( ) ;
207
- tracing:: debug!( addr = %addr_str, "resolved artifact s3 presigned request" ) ;
208
-
209
- Ok ( Some ( addr_str) )
210
- } else {
211
- Ok ( None )
212
- }
213
- }
0 commit comments