feat: add replay-stream-tasks pattern support

This commit is contained in:
2025-03-08 16:43:00 +08:00
parent e66573b315
commit f94e175082
47 changed files with 989 additions and 318 deletions

View File

@@ -2,19 +2,23 @@ use std::{borrow::Cow, sync::Arc};
use axum::Router;
use crate::app::AppContext;
use crate::app::AppContextTrait;
pub trait ControllerTrait: Sized {
fn apply_to(self, router: Router<Arc<AppContext>>) -> Router<Arc<AppContext>>;
fn apply_to(self, router: Router<Arc<dyn AppContextTrait>>)
-> Router<Arc<dyn AppContextTrait>>;
}
pub struct PrefixController {
prefix: Cow<'static, str>,
router: Router<Arc<AppContext>>,
router: Router<Arc<dyn AppContextTrait>>,
}
impl PrefixController {
pub fn new(prefix: impl Into<Cow<'static, str>>, router: Router<Arc<AppContext>>) -> Self {
pub fn new(
prefix: impl Into<Cow<'static, str>>,
router: Router<Arc<dyn AppContextTrait>>,
) -> Self {
Self {
prefix: prefix.into(),
router,
@@ -23,7 +27,10 @@ impl PrefixController {
}
impl ControllerTrait for PrefixController {
fn apply_to(self, router: Router<Arc<AppContext>>) -> Router<Arc<AppContext>> {
fn apply_to(
self,
router: Router<Arc<dyn AppContextTrait>>,
) -> Router<Arc<dyn AppContextTrait>> {
router.nest(&self.prefix, self.router)
}
}
@@ -35,14 +42,17 @@ pub enum Controller {
impl Controller {
pub fn from_prefix(
prefix: impl Into<Cow<'static, str>>,
router: Router<Arc<AppContext>>,
router: Router<Arc<dyn AppContextTrait>>,
) -> Self {
Self::Prefix(PrefixController::new(prefix, router))
}
}
impl ControllerTrait for Controller {
fn apply_to(self, router: Router<Arc<AppContext>>) -> Router<Arc<AppContext>> {
fn apply_to(
self,
router: Router<Arc<dyn AppContextTrait>>,
) -> Router<Arc<dyn AppContextTrait>> {
match self {
Self::Prefix(p) => p.apply_to(router),
}

View File

@@ -5,7 +5,7 @@ use axum::{Extension, Router, extract::State, middleware::from_fn_with_state, ro
use super::core::Controller;
use crate::{
app::AppContext,
app::AppContextTrait,
auth::{AuthUserInfo, header_www_authenticate_middleware},
errors::RResult,
};
@@ -13,11 +13,11 @@ use crate::{
pub const CONTROLLER_PREFIX: &str = "/api/graphql";
async fn graphql_handler(
State(ctx): State<Arc<AppContext>>,
State(ctx): State<Arc<dyn AppContextTrait>>,
Extension(auth_user_info): Extension<AuthUserInfo>,
req: GraphQLRequest,
) -> GraphQLResponse {
let graphql_service = &ctx.graphql;
let graphql_service = ctx.graphql();
let mut req = req.into_inner();
req = req.data(auth_user_info);
@@ -25,8 +25,8 @@ async fn graphql_handler(
graphql_service.schema.execute(req).await.into()
}
pub async fn create(ctx: Arc<AppContext>) -> RResult<Controller> {
let router = Router::<Arc<AppContext>>::new()
pub async fn create(ctx: Arc<dyn AppContextTrait>) -> RResult<Controller> {
let router = Router::<Arc<dyn AppContextTrait>>::new()
.route("/", post(graphql_handler))
.layer(from_fn_with_state(ctx, header_www_authenticate_middleware));
Ok(Controller::from_prefix(CONTROLLER_PREFIX, router))

View File

@@ -9,7 +9,7 @@ use axum::{
use super::core::Controller;
use crate::{
app::AppContext,
app::AppContextTrait,
auth::{
AuthError, AuthService, AuthServiceTrait,
oidc::{OidcAuthCallbackPayload, OidcAuthCallbackQuery, OidcAuthRequest},
@@ -22,10 +22,10 @@ use crate::{
pub const CONTROLLER_PREFIX: &str = "/api/oidc";
async fn oidc_callback(
State(ctx): State<Arc<AppContext>>,
State(ctx): State<Arc<dyn AppContextTrait>>,
Query(query): Query<OidcAuthCallbackQuery>,
) -> Result<Json<OidcAuthCallbackPayload>, AuthError> {
let auth_service = &ctx.auth;
let auth_service = ctx.auth();
if let AuthService::Oidc(oidc_auth_service) = auth_service {
let response = oidc_auth_service
.extract_authorization_request_callback(query)
@@ -40,10 +40,10 @@ async fn oidc_callback(
}
async fn oidc_auth(
State(ctx): State<Arc<AppContext>>,
State(ctx): State<Arc<dyn AppContextTrait>>,
parts: Parts,
) -> Result<Json<OidcAuthRequest>, AuthError> {
let auth_service = &ctx.auth;
let auth_service = ctx.auth();
if let AuthService::Oidc(oidc_auth_service) = auth_service {
let mut redirect_uri = ForwardedRelatedInfo::from_request_parts(&parts)
.resolved_origin()
@@ -70,8 +70,8 @@ async fn oidc_auth(
}
}
pub async fn create(_context: Arc<AppContext>) -> RResult<Controller> {
let router = Router::<Arc<AppContext>>::new()
pub async fn create(_context: Arc<dyn AppContextTrait>) -> RResult<Controller> {
let router = Router::<Arc<dyn AppContextTrait>>::new()
.route("/auth", get(oidc_auth))
.route("/callback", get(oidc_callback));