@@ -2,6 +2,7 @@ use std::collections::HashMap;
22
33use anyhow:: Result ;
44use axum:: response:: { IntoResponse , Response } ;
5+ use futures_util:: { StreamExt , TryStreamExt } ;
56use rivet_api_builder:: {
67 ApiError ,
78 extract:: { Extension , Json , Path , Query } ,
@@ -85,58 +86,75 @@ async fn upsert_inner(
8586 } )
8687 . next ( ) ;
8788
88- // Apply config
89- let mut any_endpoint_config_changed = false ;
90- for dc in & ctx. config ( ) . topology ( ) . datacenters {
91- if let Some ( runner_config) = body. datacenters . remove ( & dc. name ) {
92- let response = if ctx. config ( ) . dc_label ( ) == dc. datacenter_label {
93- rivet_api_peer:: runner_configs:: upsert (
94- ctx. clone ( ) . into ( ) ,
95- path. clone ( ) ,
96- query. clone ( ) ,
97- rivet_api_peer:: runner_configs:: UpsertRequest ( runner_config) ,
98- )
99- . await ?
100- } else {
101- request_remote_datacenter :: < UpsertResponse > (
102- ctx. config ( ) ,
103- dc. datacenter_label ,
104- & format ! ( "/runner-configs/{}" , path. runner_name) ,
105- axum:: http:: Method :: PUT ,
106- Some ( & query) ,
107- Some ( & runner_config) ,
108- )
109- . await ?
110- } ;
89+ let dcs = ctx
90+ . config ( )
91+ . topology ( )
92+ . datacenters
93+ . iter ( )
94+ . map ( |dc| ( dc. clone ( ) , body. datacenters . remove ( & dc. name ) ) )
95+ . collect :: < Vec < _ > > ( ) ;
96+ let any_endpoint_config_changed = futures_util:: stream:: iter ( dcs)
97+ . map ( |( dc, runner_config) | {
98+ let ctx = ctx. clone ( ) ;
99+ let query = query. clone ( ) ;
100+ let path = path. clone ( ) ;
101+ async move {
102+ if let Some ( runner_config) = runner_config {
103+ let response = if ctx. config ( ) . dc_label ( ) == dc. datacenter_label {
104+ rivet_api_peer:: runner_configs:: upsert (
105+ ctx. clone ( ) . into ( ) ,
106+ path. clone ( ) ,
107+ query. clone ( ) ,
108+ rivet_api_peer:: runner_configs:: UpsertRequest ( runner_config) ,
109+ )
110+ . await ?
111+ } else {
112+ request_remote_datacenter :: < UpsertResponse > (
113+ ctx. config ( ) ,
114+ dc. datacenter_label ,
115+ & format ! ( "/runner-configs/{}" , path. runner_name) ,
116+ axum:: http:: Method :: PUT ,
117+ Some ( & query) ,
118+ Some ( & runner_config) ,
119+ )
120+ . await ?
121+ } ;
111122
112- if response. endpoint_config_changed {
113- any_endpoint_config_changed = true ;
114- }
115- } else {
116- if ctx. config ( ) . dc_label ( ) == dc. datacenter_label {
117- rivet_api_peer:: runner_configs:: delete (
118- ctx. clone ( ) . into ( ) ,
119- DeletePath {
120- runner_name : path. runner_name . clone ( ) ,
121- } ,
122- DeleteQuery {
123- namespace : query. namespace . clone ( ) ,
124- } ,
125- )
126- . await ?;
127- } else {
128- request_remote_datacenter :: < DeleteResponse > (
129- ctx. config ( ) ,
130- dc. datacenter_label ,
131- & format ! ( "/runner-configs/{}" , path. runner_name) ,
132- axum:: http:: Method :: DELETE ,
133- Some ( & query) ,
134- Option :: < & ( ) > :: None ,
135- )
136- . await ?;
123+ anyhow:: Ok ( response. endpoint_config_changed )
124+ } else {
125+ if ctx. config ( ) . dc_label ( ) == dc. datacenter_label {
126+ rivet_api_peer:: runner_configs:: delete (
127+ ctx. clone ( ) . into ( ) ,
128+ DeletePath {
129+ runner_name : path. runner_name . clone ( ) ,
130+ } ,
131+ DeleteQuery {
132+ namespace : query. namespace . clone ( ) ,
133+ } ,
134+ )
135+ . await ?;
136+ } else {
137+ request_remote_datacenter :: < DeleteResponse > (
138+ ctx. config ( ) ,
139+ dc. datacenter_label ,
140+ & format ! ( "/runner-configs/{}" , path. runner_name) ,
141+ axum:: http:: Method :: DELETE ,
142+ Some ( & query) ,
143+ Option :: < & ( ) > :: None ,
144+ )
145+ . await ?;
146+ }
147+
148+ Ok ( false )
149+ }
137150 }
138- }
139- }
151+ } )
152+ . buffer_unordered ( 16 )
153+ . try_collect :: < Vec < _ > > ( )
154+ // NOTE: We must error when any peer request fails, not all
155+ . await ?
156+ . into_iter ( )
157+ . any ( |endpoint_config_changed| endpoint_config_changed) ;
140158
141159 // Update runner metadata
142160 //
0 commit comments