pub trait Function:
Send
+ Sync
+ 'static {
type Config: FunctionConfig;
// Required method
fn call(
&self,
ctx: &mut Ctx<'_>,
cfg: &Self::Config,
) -> impl Future<Output = Result<Outcome>> + Send;
// Provided methods
fn spec(&self) -> FunctionSpec { ... }
fn prepare(
&self,
_cfg: &mut Self::Config,
_p: &Prepare<'_>,
) -> Result<(), Vec<Issue>> { ... }
}Expand description
A host function: a typed config compiled once at build, and a call per task run.
call returns a Send future, so an implementation may be written with
async fn. testing::call runs one call of it
outside any workflow:
use dataflow_rs::datavalue::OwnedDataValue;
use dataflow_rs::expr::Output;
use dataflow_rs::function::{FunctionConfig, FunctionSpec, testing};
use dataflow_rs::{Ctx, Expr, Function, Outcome, Registry, Result};
use serde_json::json;
#[derive(FunctionConfig)]
struct FetchConfig {
url: Expr<String>,
#[output(default = "data.response")]
output: Output,
}
struct Fetch;
impl Function for Fetch {
type Config = FetchConfig;
fn spec(&self) -> FunctionSpec {
FunctionSpec::default().with_category("io")
}
async fn call(&self, ctx: &mut Ctx<'_>, cfg: &FetchConfig) -> Result<Outcome> {
let url = ctx.eval(&cfg.url)?;
// A real fetch awaits its response here.
let response = OwnedDataValue::from(&json!({"url": &*url, "status": 200}));
ctx.emit(&cfg.output, response)?;
Ok(Outcome::Ok)
}
}
let mut registry = Registry::default();
registry.register("fetch", Fetch);
let called = testing::call(Fetch, json!({"url": "https://example.com"})).await;
assert_eq!(called.outcome.unwrap(), Outcome::Ok);
let status = called.message.context().get(&"data.response.status".parse().unwrap());
assert_eq!(status, Some(&OwnedDataValue::from(&json!(200))));Required Associated Types§
Sourcetype Config: FunctionConfig
type Config: FunctionConfig
The function’s input, compiled at build.
Required Methods§
Provided Methods§
Sourcefn spec(&self) -> FunctionSpec
fn spec(&self) -> FunctionSpec
What the function says about itself, for tooling. Called once, when it is registered.
Sourcefn prepare(
&self,
_cfg: &mut Self::Config,
_p: &Prepare<'_>,
) -> Result<(), Vec<Issue>>
fn prepare( &self, _cfg: &mut Self::Config, _p: &Prepare<'_>, ) -> Result<(), Vec<Issue>>
Checks or completes a compiled config at build, with what the config alone cannot know. It runs only when the config compiled.
Issue paths are relative to the config. The compiler prefixes the
task’s function.input path and stamps the step, and a Rejected
issue fails the task’s compile.
Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".