Skip to content

Conversation

Soroushsrd
Copy link
Contributor

  • Add ExtractorHook trait for lifecycle observability
  • Add ExtractorValidatorHook trait for custom validation
  • Add ExtractorWithHooks extension trait
  • Add comprehensive documentation and examples
  • Add integration tests for hook functionality"

closes #770

@Soroushsrd
Copy link
Contributor Author

Hey Josh. I would love to hear your take on how I implemented this feature. If it can be done better, please let me know

- Add ExtractorHook trait for lifecycle observability
- Add ExtractorValidatorHook trait for custom validation
- Add ExtractorWithHooks extension trait
- Add comprehensive documentation and examples
- Add integration tests for hook functionality"
Copy link
Contributor

@joshua-mo-143 joshua-mo-143 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work! Some changes needed but I think otherwise mostly OK. Good job on ensuring docstrings, too.

Generally speaking:

  • Avoid Vec<Box<T>> (and &[Box<T>]) where possible as an input argument - we should be handling this internally (see ToolSet struct if stuck). For example:
struct Hooks(Vec<Box<dyn ExtractorHook>>);

impl Hooks {
    fn add_hook<T>(mut self, hook: T) -> Self 
        where 
        T: ExtractorHook + 'static {
        self.0.push(Box::new(hook));
        self
    }
}
  • Having ExtractorWithHooks<T> might be a bit too far of a leap in terms of traits at the moment. Ideally we should have a way to simply transition from one struct, Extractor<M, T> to an ExtractorWithHooks<M, T>.
  • Please add an example to the rig-core examples list.

/// ```
///
/// [`extract_with_hooks`]: ExtractorWithHooks::extract_with_hooks
pub trait ExtractorWithHooks<T>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is generalising perhaps a bit too far for the scope. We should ideally have an ExtractorWithHooks struct I think for now. If it's evident that users actually want this trait because they need to build their own extractors (and the extractor hooks into other things), then I think we should consider it then.

/// validation failure will cause the extraction attempt to fail:
///
/// ```rust
/// let validators: Vec<Box<dyn ExtractorValidatorHook<Person>>> = vec![
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should try to abstract away as much as possible the need to use Vec<Box<T>> from the user side. It is a bit clunky in terms of DX.


for i in 0..=self.retries {
tracing::debug!(
"Attempting to extract Json. Retries left:{retries}",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be JSON or json, not Json

}
Err(e) => {
tracing::warn!(
"Attempt number {i} to extract Json failed: {e:?}. Retrying..."
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here

/// This implementation creates the complete extraction lifecycle with
/// observability and validation. It manages the retry loop, coordinates
/// hook calls, and ensures validators are executed in the correct sequence.
fn extract_with_hooks(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fyi I believe when you are implementing a trait for a type (that has fn() -> <some_future>, you can use async fn rather than just rawdogging the future

&self,
text: impl Into<Message> + Send,
attempt: u64,
hooks: &[Box<dyn ExtractorHook>],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as mentioned before, we should try to avoid using arrays of Box<T> where possible


#[tokio::test]
#[ignore]
async fn test_multiple_validators() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

general comment: An example to hold one of these tests in would be great. I know there's literally a gazillion examples already (and we will be cleaning it up!), but for now an example would be great.

@Soroushsrd
Copy link
Contributor Author

Got it. thank you for the comments. will sort them out.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

feat: extractor hooks
2 participants