-
Notifications
You must be signed in to change notification settings - Fork 252
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(extensions): Add extensions support #2634
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #2634 +/- ##
=======================================
Coverage 86.46% 86.47%
=======================================
Files 255 256 +1
Lines 24963 25022 +59
=======================================
+ Hits 21584 21637 +53
- Misses 3379 3385 +6 ☔ View full report in Codecov by Sentry. |
Co-authored-by: Kiryl Mialeshka <[email protected]>
RFC: The current Extension SDK implementation exposes the user to Tailcall internal API structs, which are subject to change in the future. #[async_trait::async_trait]
pub trait ExtensionTrait<Json: JsonLikeOwned>: std::fmt::Debug + Send + Sync {
fn load(&self) {}
async fn prepare(&self, context: PrepareContext<Json>) -> Box<IR>;
async fn process(&self, context: ProcessContext<Json>) -> Result<Json, Error>;
} To solve this issue, I suggest we create new enumerations, Proposed solution: #[async_trait::async_trait]
pub trait ExtensionTrait<Json: JsonLikeOwned>: std::fmt::Debug + Send + Sync {
fn load(&self) {}
async fn prepare_steps(&self) -> Box<PrepareOperation>;
async fn process(&self) -> Box<ProcessOperation>;
}
pub enum PrepareOperation {
ModifyRequestHeaders(HashMap<String, String>),
AddRequestCookie(String),
// TODO add other operations
Compose(Box<PrepareOperation>, Box<PrepareOperation>),
}
pub enum ProcessOperation {
ExtractPath(Vec<String>),
ModifyValue(Fn(ProcessContext<Json>) -> Result<Json>),
GroupBy(Vec<String>),
Filter(Vec<String>, Fn(JsonLike) -> bool),
// TODO add other operations
Compose(Box<ProcessOperation>, Box<ProcessOperation>), The design is not final, and it is open to suggestions |
Have you considered a middleware pattern for this? This be could be more ergonomic and familiar for users. Something like this: #[async_trait::async_trait]
pub trait ExtensionTrait<Json: JsonLikeOwned>: std::fmt::Debug + Send + Sync {
fn load(&self) {}
async fn execute(&self, context: Context<Json>) -> Result<Json, Error> {
context.set_cookie(...);
context.set_headers(...);
let response = context.http(...).await;
convert_response(response)
}
} |
@meskill, that's a good idea. I agree with you that more people will be comfortable with the middleware approach. |
Action required: PR inactive for 5 days. |
Action required: PR inactive for 5 days. |
Action required: PR inactive for 5 days. |
We are working on the SDK API |
Action required: PR inactive for 5 days. |
Action required: PR inactive for 5 days. |
PR closed after 10 days of inactivity. |
Summary:
Modify Tailcall to allow users to create a version with custom extension functionality. We achieve that by providing a
@extension
directive and an extension trait that developers must implement on their custom extensions before tailcall can load them. An example that showcases the power of extensions is included.Issue Reference(s):
Fixes #2613
Build & Testing:
To test it run the following command
cargo run -p extension-i18n
and execute the querycargo test
successfully../lint.sh --mode=fix
to fix all linting issues raised by./lint.sh --mode=check
.Checklist:
<type>(<optional scope>): <title>