Skip to content
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

Closed
wants to merge 27 commits into from

Conversation

karatakis
Copy link
Collaborator

@karatakis karatakis commented Aug 9, 2024

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 query

{
  user(id: 1) {
    id
    name
    company {
      catchPhrase
    }
  }
}
  • I ran cargo test successfully.
  • I have run ./lint.sh --mode=fix to fix all linting issues raised by ./lint.sh --mode=check.

Checklist:

  • I have added relevant unit & integration tests.
  • I have updated the documentation accordingly.
  • I have performed a self-review of my code.
  • PR follows the naming convention of <type>(<optional scope>): <title>

@github-actions github-actions bot added the type: feature Brand new functionality, features, pages, workflows, endpoints, etc. label Aug 9, 2024
Copy link

codecov bot commented Aug 9, 2024

Codecov Report

Attention: Patch coverage is 83.60656% with 10 lines in your changes missing coverage. Please review.

Project coverage is 86.47%. Comparing base (5faf008) to head (656255d).
Report is 145 commits behind head on main.

Files with missing lines Patch % Lines
src/core/blueprint/operators/extension.rs 80.00% 9 Missing ⚠️
src/core/config/config.rs 50.00% 1 Missing ⚠️
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.
📢 Have feedback on the report? Share it here.

@karatakis karatakis changed the title feat(extensions: Add extensions support feat(extensions): Add extensions support Aug 9, 2024
examples/extension-i18n/src/main.rs Outdated Show resolved Hide resolved
src/core/blueprint/operators/extension.rs Outdated Show resolved Hide resolved
src/core/blueprint/operators/extension.rs Outdated Show resolved Hide resolved
src/core/blueprint/operators/extension.rs Outdated Show resolved Hide resolved
src/core/blueprint/operators/extension.rs Outdated Show resolved Hide resolved
src/core/ir/eval.rs Outdated Show resolved Hide resolved
src/core/ir/eval.rs Outdated Show resolved Hide resolved
src/core/ir/model.rs Outdated Show resolved Hide resolved
src/core/ir/model.rs Outdated Show resolved Hide resolved
src/core/ir/eval.rs Outdated Show resolved Hide resolved
src/core/ir/eval.rs Outdated Show resolved Hide resolved
src/core/blueprint/operators/extension.rs Outdated Show resolved Hide resolved
src/core/blueprint/operators/extension.rs Outdated Show resolved Hide resolved
src/core/blueprint/operators/extension.rs Outdated Show resolved Hide resolved
examples/extension-i18n/src/main.rs Outdated Show resolved Hide resolved
examples/extension-i18n/main.graphql Outdated Show resolved Hide resolved
src/core/blueprint/operators/extension.rs Outdated Show resolved Hide resolved
src/core/blueprint/operators/extension.rs Outdated Show resolved Hide resolved
@karatakis karatakis marked this pull request as ready for review August 12, 2024 19:05
@karatakis karatakis marked this pull request as draft August 19, 2024 10:13
@karatakis
Copy link
Collaborator Author

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, PrepareOperation and ProcessOperation, which give a set of pre-defined operations for the Extension SDK user. Those enums follow a similar logic to IR but provide a subset of operations the user can safely use. At the same time, the development team will enforce the rule that it is always backward compatible.

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

@meskill
Copy link
Contributor

meskill commented Aug 22, 2024

RFC:

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)
    }
}

@karatakis
Copy link
Collaborator Author

@meskill, that's a good idea. I agree with you that more people will be comfortable with the middleware approach.

Copy link

Action required: PR inactive for 5 days.
Status update or closure in 10 days.

@github-actions github-actions bot added state: inactive No current action needed/possible; issue fixed, out of scope, or superseded. and removed state: inactive No current action needed/possible; issue fixed, out of scope, or superseded. labels Aug 28, 2024
Copy link

github-actions bot commented Sep 2, 2024

Action required: PR inactive for 5 days.
Status update or closure in 10 days.

@github-actions github-actions bot added state: inactive No current action needed/possible; issue fixed, out of scope, or superseded. and removed state: inactive No current action needed/possible; issue fixed, out of scope, or superseded. labels Sep 2, 2024
Copy link

github-actions bot commented Sep 7, 2024

Action required: PR inactive for 5 days.
Status update or closure in 10 days.

@github-actions github-actions bot added the state: inactive No current action needed/possible; issue fixed, out of scope, or superseded. label Sep 7, 2024
@karatakis
Copy link
Collaborator Author

We are working on the SDK API

@github-actions github-actions bot removed the state: inactive No current action needed/possible; issue fixed, out of scope, or superseded. label Sep 11, 2024
@karatakis karatakis closed this Sep 11, 2024
@karatakis karatakis deleted the feat/tailcall-extensions branch September 11, 2024 22:03
@karatakis karatakis restored the feat/tailcall-extensions branch September 11, 2024 23:14
@karatakis karatakis reopened this Sep 11, 2024
Copy link

Action required: PR inactive for 5 days.
Status update or closure in 10 days.

@github-actions github-actions bot added state: inactive No current action needed/possible; issue fixed, out of scope, or superseded. and removed state: inactive No current action needed/possible; issue fixed, out of scope, or superseded. labels Sep 17, 2024
Copy link

Action required: PR inactive for 5 days.
Status update or closure in 10 days.

@github-actions github-actions bot added the state: inactive No current action needed/possible; issue fixed, out of scope, or superseded. label Sep 22, 2024
Copy link

github-actions bot commented Oct 2, 2024

PR closed after 10 days of inactivity.

@github-actions github-actions bot closed this Oct 2, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
state: inactive No current action needed/possible; issue fixed, out of scope, or superseded. type: feature Brand new functionality, features, pages, workflows, endpoints, etc.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

feature: Custom Extensions
3 participants