Skip to content

fix: Misleading error messages in iceberg-catalog-rest and allow StatusCode::OK in responses#962

Merged
Xuanwo merged 1 commit intoapache:mainfrom
connortsui20:rest-client-err-msg
Feb 11, 2025
Merged

fix: Misleading error messages in iceberg-catalog-rest and allow StatusCode::OK in responses#962
Xuanwo merged 1 commit intoapache:mainfrom
connortsui20:rest-client-err-msg

Conversation

@connortsui20
Copy link
Copy Markdown
Contributor

Several of the error messages in iceberg-catalog-rest had misleading error messages, so this PR fixes some of those.

Additionally, several of the Catalog methods on RestCatalog do not accept StatusCode::OK as a successful response, so I've added that in as well. This meant that some of the client.rs functions had to change, but given that they are only used so many times I thought it was fine to remove the const generics.

There are also a few other things that could be cleaned up but I'll keep this PR short.

@connortsui20 connortsui20 changed the title fix(REST): Misleading error messages in iceberg-catalog-rest and allow StatusCode::OK in responses fix: Misleading error messages in iceberg-catalog-rest and allow StatusCode::OK in responses Feb 11, 2025
Copy link
Copy Markdown
Member

@Xuanwo Xuanwo left a comment

Choose a reason for hiding this comment

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

Thank you @connortsui20, I love this change.

@Xuanwo Xuanwo merged commit c21b73e into apache:main Feb 11, 2025
17 checks passed
@connortsui20 connortsui20 deleted the rest-client-err-msg branch February 11, 2025 14:21
@connortsui20
Copy link
Copy Markdown
Contributor Author

Ok so it turns out this introduces a bug where namespace_exists getting back a StatusCode::OK actually means that the namespace doesn't exist... I'm digging into this more

@connortsui20
Copy link
Copy Markdown
Contributor Author

connortsui20 commented Feb 12, 2025

@Xuanwo just a heads up my change introduced a bug because I was unaware of the endpoint responses: https://github.com/apache/iceberg/blob/main/open-api/rest-catalog-open-api.yaml

I am working right now on a fix that will hopefully consolidate the 3 types of request functions in client.rs.

Every single endpoint has exactly 1 "OK" case except GET /v1/{prefix}/namespaces/{namespace}/tables/{table} as can return 304 if the table's metadata hasn't changed. So I'm probably going to write a method on HttpClient that accepts a closure that does the conversion from &Response to the owned and deserialized result type we want. That would also allow each type of request to know exactly which error cases it has and thus they could handle each error accordingly (rather than a blanket error response that isn't super descriptive)

Xuanwo pushed a commit that referenced this pull request Mar 10, 2025
Followup of #962

#962 Introduced a bug where it is not some of the methods allow for both
`StatusCode::OK` and `StatusCode::NO_CONTENT` as success cases, when in
reality it should be one or the other (this was me, sorry about that).

This PR attempts to unify the 3 different types of response helpers that
essentially all do the exact same thing slightly differently. The main
addition here is a function `query_catalog`:

```rust
    // Queries the Iceberg REST catalog with the given `Request` and a provided handler.
    pub async fn query_catalog<R, H, Fut>(&self, mut request: Request, handler: H) -> Result<R>
    where
        R: DeserializeOwned,
        H: FnOnce(Response) -> Fut,
        Fut: Future<Output = Result<R>>,
    {
        self.authenticate(&mut request).await?;

        let response = self.client.execute(request).await?;

        handler(response).await
    }
```

By allowing each `Catalog` method to specify how they want to handle the
responses, it gets much finer control on the success/error cases as well
as the error messages. Previously, there were 3 functions that all did
similar things:

```rust
    pub async fn query<R: DeserializeOwned, E: DeserializeOwned + Into<Error>>(
        &self,
        mut request: Request,
    ) -> Result<R> {

    pub async fn execute<E: DeserializeOwned + Into<Error>>(
        &self,
        mut request: Request,
    ) -> Result<()> {

    pub async fn do_execute<R, E: DeserializeOwned + Into<Error>>(
        &self,
        mut request: Request,
        handler: impl FnOnce(&Response) -> Option<R>,
    ) -> Result<R> {
```

I'm also somewhat using this as a chance to refactor some other parts of
this crate, mainly documentation and examples.

@Xuanwo It would be great if I could get feedback on some of these
proposed changes before I keep going!
ZENOTME pushed a commit to risingwavelabs/iceberg-rust that referenced this pull request Mar 12, 2025
Followup of apache#962

apache#962 Introduced a bug where it is not some of the methods allow for both
`StatusCode::OK` and `StatusCode::NO_CONTENT` as success cases, when in
reality it should be one or the other (this was me, sorry about that).

This PR attempts to unify the 3 different types of response helpers that
essentially all do the exact same thing slightly differently. The main
addition here is a function `query_catalog`:

```rust
    // Queries the Iceberg REST catalog with the given `Request` and a provided handler.
    pub async fn query_catalog<R, H, Fut>(&self, mut request: Request, handler: H) -> Result<R>
    where
        R: DeserializeOwned,
        H: FnOnce(Response) -> Fut,
        Fut: Future<Output = Result<R>>,
    {
        self.authenticate(&mut request).await?;

        let response = self.client.execute(request).await?;

        handler(response).await
    }
```

By allowing each `Catalog` method to specify how they want to handle the
responses, it gets much finer control on the success/error cases as well
as the error messages. Previously, there were 3 functions that all did
similar things:

```rust
    pub async fn query<R: DeserializeOwned, E: DeserializeOwned + Into<Error>>(
        &self,
        mut request: Request,
    ) -> Result<R> {

    pub async fn execute<E: DeserializeOwned + Into<Error>>(
        &self,
        mut request: Request,
    ) -> Result<()> {

    pub async fn do_execute<R, E: DeserializeOwned + Into<Error>>(
        &self,
        mut request: Request,
        handler: impl FnOnce(&Response) -> Option<R>,
    ) -> Result<R> {
```

I'm also somewhat using this as a chance to refactor some other parts of
this crate, mainly documentation and examples.

@Xuanwo It would be great if I could get feedback on some of these
proposed changes before I keep going!
ZENOTME pushed a commit to risingwavelabs/iceberg-rust that referenced this pull request Mar 20, 2025
Followup of apache#962

apache#962 Introduced a bug where it is not some of the methods allow for both
`StatusCode::OK` and `StatusCode::NO_CONTENT` as success cases, when in
reality it should be one or the other (this was me, sorry about that).

This PR attempts to unify the 3 different types of response helpers that
essentially all do the exact same thing slightly differently. The main
addition here is a function `query_catalog`:

```rust
    // Queries the Iceberg REST catalog with the given `Request` and a provided handler.
    pub async fn query_catalog<R, H, Fut>(&self, mut request: Request, handler: H) -> Result<R>
    where
        R: DeserializeOwned,
        H: FnOnce(Response) -> Fut,
        Fut: Future<Output = Result<R>>,
    {
        self.authenticate(&mut request).await?;

        let response = self.client.execute(request).await?;

        handler(response).await
    }
```

By allowing each `Catalog` method to specify how they want to handle the
responses, it gets much finer control on the success/error cases as well
as the error messages. Previously, there were 3 functions that all did
similar things:

```rust
    pub async fn query<R: DeserializeOwned, E: DeserializeOwned + Into<Error>>(
        &self,
        mut request: Request,
    ) -> Result<R> {

    pub async fn execute<E: DeserializeOwned + Into<Error>>(
        &self,
        mut request: Request,
    ) -> Result<()> {

    pub async fn do_execute<R, E: DeserializeOwned + Into<Error>>(
        &self,
        mut request: Request,
        handler: impl FnOnce(&Response) -> Option<R>,
    ) -> Result<R> {
```

I'm also somewhat using this as a chance to refactor some other parts of
this crate, mainly documentation and examples.

@Xuanwo It would be great if I could get feedback on some of these
proposed changes before I keep going!
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.

2 participants