Archived
el-ui v2: universal platform, service bindings, AOP, auth, publish pipeline
This commit is contained in:
@@ -0,0 +1,113 @@
|
||||
//! Service proxy — the generated client for a service.
|
||||
//!
|
||||
//! A `ServiceProxy` wraps a binding and provides typed method calls.
|
||||
//! The codegen (a future agent) will generate typed proxy structs from service
|
||||
//! definitions. This is the runtime base that generated code builds on.
|
||||
|
||||
use crate::{
|
||||
binding::{Binding, ServiceRequest, ServiceResponse},
|
||||
config::ServiceConfig,
|
||||
ServiceResult,
|
||||
};
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
|
||||
/// A service method descriptor — used by the proxy and codegen.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ServiceMethod {
|
||||
pub name: String,
|
||||
/// Parameter names in order (for positional call support).
|
||||
pub param_names: Vec<String>,
|
||||
pub return_type: String,
|
||||
}
|
||||
|
||||
impl ServiceMethod {
|
||||
pub fn new(name: impl Into<String>, return_type: impl Into<String>) -> Self {
|
||||
Self {
|
||||
name: name.into(),
|
||||
param_names: Vec::new(),
|
||||
return_type: return_type.into(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_params(mut self, params: Vec<impl Into<String>>) -> Self {
|
||||
self.param_names = params.into_iter().map(|p| p.into()).collect();
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
/// A runtime service proxy.
|
||||
///
|
||||
/// The codegen produces a typed wrapper around this.
|
||||
/// Directly usable for dynamic invocation (e.g., from the AOP layer).
|
||||
pub struct ServiceProxy {
|
||||
pub service_name: String,
|
||||
pub config: ServiceConfig,
|
||||
pub binding: Arc<dyn Binding>,
|
||||
pub methods: Vec<ServiceMethod>,
|
||||
}
|
||||
|
||||
impl ServiceProxy {
|
||||
pub fn new(
|
||||
service_name: impl Into<String>,
|
||||
config: ServiceConfig,
|
||||
binding: Arc<dyn Binding>,
|
||||
) -> Self {
|
||||
Self {
|
||||
service_name: service_name.into(),
|
||||
config,
|
||||
binding,
|
||||
methods: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_method(mut self, method: ServiceMethod) -> Self {
|
||||
self.methods.push(method);
|
||||
self
|
||||
}
|
||||
|
||||
/// Call a service method by name with named parameters.
|
||||
pub fn call(
|
||||
&self,
|
||||
method_name: &str,
|
||||
params: HashMap<String, String>,
|
||||
) -> ServiceResult<ServiceResponse> {
|
||||
let request = ServiceRequest {
|
||||
service: self.service_name.clone(),
|
||||
method: method_name.to_string(),
|
||||
params,
|
||||
};
|
||||
self.binding.call(request)
|
||||
}
|
||||
|
||||
/// Call a service method by name with positional parameters.
|
||||
/// Parameters are matched to the method's `param_names` in order.
|
||||
pub fn call_positional(
|
||||
&self,
|
||||
method_name: &str,
|
||||
args: Vec<String>,
|
||||
) -> ServiceResult<ServiceResponse> {
|
||||
let method = self
|
||||
.methods
|
||||
.iter()
|
||||
.find(|m| m.name == method_name)
|
||||
.ok_or_else(|| crate::ServiceError::MethodNotFound {
|
||||
service: self.service_name.clone(),
|
||||
method: method_name.to_string(),
|
||||
})?;
|
||||
|
||||
let params: HashMap<String, String> = method
|
||||
.param_names
|
||||
.iter()
|
||||
.zip(args.iter())
|
||||
.map(|(name, val)| (name.clone(), val.clone()))
|
||||
.collect();
|
||||
|
||||
self.call(method_name, params)
|
||||
}
|
||||
|
||||
/// List all registered method names on this proxy.
|
||||
pub fn method_names(&self) -> Vec<&str> {
|
||||
self.methods.iter().map(|m| m.name.as_str()).collect()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user