@@ -142,6 +142,66 @@ impl InstanceState {
142142
143143impl SelfInstanceBuilder for InstanceState { }
144144
145+ /// Helper module for acquiring permits from the outbound connections semaphore.
146+ ///
147+ /// This is used by the outbound HTTP implementations to limit concurrent outbound connections.
148+ mod concurrent_outbound_connections {
149+ use super :: * ;
150+
151+ /// Acquires a semaphore permit for the given interface, if a semaphore is configured.
152+ pub async fn acquire_semaphore < ' a > (
153+ interface : & str ,
154+ semaphore : & ' a Option < Arc < Semaphore > > ,
155+ ) -> Option < tokio:: sync:: SemaphorePermit < ' a > > {
156+ let s = semaphore. as_ref ( ) ?;
157+ acquire ( interface, || s. try_acquire ( ) , async || s. acquire ( ) . await ) . await
158+ }
159+
160+ /// Acquires an owned semaphore permit for the given interface, if a semaphore is configured.
161+ pub async fn acquire_owned_semaphore (
162+ interface : & str ,
163+ semaphore : & Option < Arc < Semaphore > > ,
164+ ) -> Option < tokio:: sync:: OwnedSemaphorePermit > {
165+ let s = semaphore. as_ref ( ) ?;
166+ acquire (
167+ interface,
168+ || s. clone ( ) . try_acquire_owned ( ) ,
169+ async || s. clone ( ) . acquire_owned ( ) . await ,
170+ )
171+ . await
172+ }
173+
174+ /// Helper function to acquire a semaphore permit, either immediately or by waiting.
175+ ///
176+ /// Allows getting either a borrowed or owned permit.
177+ async fn acquire < T > (
178+ interface : & str ,
179+ try_acquire : impl Fn ( ) -> Result < T , tokio:: sync:: TryAcquireError > ,
180+ acquire : impl AsyncFnOnce ( ) -> Result < T , tokio:: sync:: AcquireError > ,
181+ ) -> Option < T > {
182+ // Try to acquire a permit without waiting first
183+ // Keep track of whether we had to wait for metrics purposes.
184+ let mut waited = false ;
185+ let permit = match try_acquire ( ) {
186+ Ok ( p) => Ok ( p) ,
187+ // No available permits right now; wait for one
188+ Err ( tokio:: sync:: TryAcquireError :: NoPermits ) => {
189+ waited = true ;
190+ acquire ( ) . await . map_err ( |_| ( ) )
191+ }
192+ Err ( _) => Err ( ( ) ) ,
193+ } ;
194+ if permit. is_ok ( ) {
195+ spin_telemetry:: monotonic_counter!(
196+ outbound_http. acquired_permits = 1 ,
197+ interface = interface,
198+ waited = waited
199+ ) ;
200+ }
201+ permit. ok ( )
202+ }
203+ }
204+
145205pub type Request = http:: Request < wasmtime_wasi_http:: body:: HyperOutgoingBody > ;
146206pub type Response = http:: Response < wasmtime_wasi_http:: body:: HyperIncomingBody > ;
147207
0 commit comments