From 011e9cdfeac7743499e9875098fd6554749ae931 Mon Sep 17 00:00:00 2001
From: Nikolay Kim
Date: Sat, 2 Nov 2024 12:49:49 +0500
Subject: [PATCH] Added Service::not_ready() method (#449)
---
README.md | 2 +-
ntex-service/CHANGES.md | 4 +
ntex-service/Cargo.toml | 2 +-
ntex-service/src/and_then.rs | 5 +
ntex-service/src/apply.rs | 5 +
ntex-service/src/boxed.rs | 38 +++---
ntex-service/src/ctx.rs | 249 ++++++++++-------------------------
ntex-service/src/lib.rs | 18 ++-
ntex-service/src/macros.rs | 13 ++
ntex-service/src/map_err.rs | 5 +
ntex-service/src/pipeline.rs | 176 +++++++++++++++++++------
ntex-service/src/then.rs | 5 +
ntex-service/src/util.rs | 31 ++++-
13 files changed, 314 insertions(+), 239 deletions(-)
diff --git a/README.md b/README.md
index 175d98ca..fbf20228 100644
--- a/README.md
+++ b/README.md
@@ -9,7 +9,7 @@
[](https://blog.rust-lang.org/2023/12/28/Rust-1.75.0.html)

[](https://codecov.io/gh/ntex-rs/ntex)
-[](https://discord.gg/zBNyhVRz)
+[](https://discord.com/channels/919288597826387979/919288597826387982)
diff --git a/ntex-service/CHANGES.md b/ntex-service/CHANGES.md
index 87525b87..f3e14370 100644
--- a/ntex-service/CHANGES.md
+++ b/ntex-service/CHANGES.md
@@ -1,5 +1,9 @@
# Changes
+## [3.3.0] - 2024-11-02
+
+* Added Service::not_ready() method
+
## [3.2.1] - 2024-10-31
* Fix shared readiness notification
diff --git a/ntex-service/Cargo.toml b/ntex-service/Cargo.toml
index 86ef1147..48b568dc 100644
--- a/ntex-service/Cargo.toml
+++ b/ntex-service/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "ntex-service"
-version = "3.2.1"
+version = "3.3.0"
authors = ["ntex contributors "]
description = "ntex service"
keywords = ["network", "framework", "async", "futures"]
diff --git a/ntex-service/src/and_then.rs b/ntex-service/src/and_then.rs
index fb86be56..4ea3e706 100644
--- a/ntex-service/src/and_then.rs
+++ b/ntex-service/src/and_then.rs
@@ -30,6 +30,11 @@ where
util::ready(&self.svc1, &self.svc2, ctx).await
}
+ #[inline]
+ async fn not_ready(&self) -> Result<(), Self::Error> {
+ util::select(self.svc1.not_ready(), self.svc2.not_ready()).await
+ }
+
#[inline]
async fn shutdown(&self) {
util::shutdown(&self.svc1, &self.svc2).await
diff --git a/ntex-service/src/apply.rs b/ntex-service/src/apply.rs
index 5425d7d2..985cd968 100644
--- a/ntex-service/src/apply.rs
+++ b/ntex-service/src/apply.rs
@@ -104,6 +104,11 @@ where
self.service.ready().await.map_err(From::from)
}
+ #[inline]
+ async fn not_ready(&self) -> Result<(), Err> {
+ self.service.get_ref().not_ready().await.map_err(From::from)
+ }
+
#[inline]
async fn shutdown(&self) {
self.service.shutdown().await
diff --git a/ntex-service/src/boxed.rs b/ntex-service/src/boxed.rs
index ad8f2927..d940d454 100644
--- a/ntex-service/src/boxed.rs
+++ b/ntex-service/src/boxed.rs
@@ -1,4 +1,4 @@
-use std::{fmt, future::Future, pin::Pin, rc::Rc};
+use std::{fmt, future::Future, pin::Pin};
use crate::ctx::{ServiceCtx, WaitersRef};
@@ -50,15 +50,17 @@ trait ServiceObj {
fn ready<'a>(
&'a self,
- idx: usize,
- waiters: &'a Rc,
+ idx: u32,
+ waiters: &'a WaitersRef,
) -> BoxFuture<'a, (), Self::Error>;
+ fn not_ready(&self) -> BoxFuture<'_, (), Self::Error>;
+
fn call<'a>(
&'a self,
req: Req,
- idx: usize,
- waiters: &'a Rc,
+ idx: u32,
+ waiters: &'a WaitersRef,
) -> BoxFuture<'a, Self::Response, Self::Error>;
fn shutdown<'a>(&'a self) -> Pin + 'a>>;
@@ -75,14 +77,15 @@ where
#[inline]
fn ready<'a>(
&'a self,
- idx: usize,
- waiters: &'a Rc,
+ idx: u32,
+ waiters: &'a WaitersRef,
) -> BoxFuture<'a, (), Self::Error> {
- Box::pin(async move {
- ServiceCtx::<'a, S>::from_ref(idx, waiters)
- .ready(self)
- .await
- })
+ Box::pin(async move { ServiceCtx::<'a, S>::new(idx, waiters).ready(self).await })
+ }
+
+ #[inline]
+ fn not_ready(&self) -> BoxFuture<'_, (), Self::Error> {
+ Box::pin(crate::Service::not_ready(self))
}
#[inline]
@@ -94,11 +97,11 @@ where
fn call<'a>(
&'a self,
req: Req,
- idx: usize,
- waiters: &'a Rc,
+ idx: u32,
+ waiters: &'a WaitersRef,
) -> BoxFuture<'a, Self::Response, Self::Error> {
Box::pin(async move {
- ServiceCtx::<'a, S>::from_ref(idx, waiters)
+ ServiceCtx::<'a, S>::new(idx, waiters)
.call_nowait(self, req)
.await
})
@@ -155,6 +158,11 @@ where
self.0.ready(idx, waiters).await
}
+ #[inline]
+ async fn not_ready(&self) -> Result<(), Self::Error> {
+ self.0.not_ready().await
+ }
+
#[inline]
async fn shutdown(&self) {
self.0.shutdown().await
diff --git a/ntex-service/src/ctx.rs b/ntex-service/src/ctx.rs
index c5223fdf..36b07a03 100644
--- a/ntex-service/src/ctx.rs
+++ b/ntex-service/src/ctx.rs
@@ -1,71 +1,90 @@
-use std::{cell, fmt, future::Future, marker, pin::Pin, rc::Rc, task, task::Context};
+use std::task::{Context, Poll, Waker};
+use std::{cell, fmt, future::Future, marker, pin::Pin, rc::Rc};
use crate::Service;
pub struct ServiceCtx<'a, S: ?Sized> {
- idx: usize,
- waiters: &'a Rc,
+ idx: u32,
+ waiters: &'a WaitersRef,
_t: marker::PhantomData>,
}
-#[derive(Clone, Debug)]
-/// Pipeline tag allows to notify pipeline binding
-pub struct PipelineTag(Rc);
-
-pub(crate) struct Waiters {
- index: usize,
- waiters: Rc,
-}
-
#[derive(Debug)]
pub(crate) struct WaitersRef {
- cur: cell::Cell,
- indexes: cell::UnsafeCell>>,
-}
-
-impl PipelineTag {
- /// Notify pipeline dispatcher
- pub fn notify(&self) {
- if let Some(waker) = self.0.get()[0].take() {
- waker.wake();
- }
- }
+ cur: cell::Cell,
+ wakers: cell::UnsafeCell>,
+ indexes: cell::UnsafeCell>>,
}
impl WaitersRef {
+ pub(crate) fn new() -> (u32, Self) {
+ let mut waiters = slab::Slab::new();
+
+ // first insert for wake ups from services
+ let _ = waiters.insert(None);
+
+ (
+ waiters.insert(Default::default()) as u32,
+ WaitersRef {
+ cur: cell::Cell::new(u32::MAX),
+ indexes: cell::UnsafeCell::new(waiters),
+ wakers: cell::UnsafeCell::new(Vec::default()),
+ },
+ )
+ }
+
#[allow(clippy::mut_from_ref)]
- fn get(&self) -> &mut slab::Slab