Skip to content

Datastore has its own error type#357

Closed
david-crespo wants to merge 3 commits into
mainfrom
db-errors
Closed

Datastore has its own error type#357
david-crespo wants to merge 3 commits into
mainfrom
db-errors

Conversation

@david-crespo

@david-crespo david-crespo commented Nov 2, 2021

Copy link
Copy Markdown
Contributor

Getting a start on prototyping #347. Generally I think all the datastore functions should return a datastore error, and then it's the responsibility of the nexus wrapper (probably, could also be the endpoint) to convert it to an external error. UpdateResult is trivial to convert because there's only one query in all three examples, so I started with that.

The insight that I'm rolling with here is that if public_error_from_diesel_pool is what we call with errors everywhere, then roughly speaking the datastore error struct just needs to represent the args to public_error_from_diesel_pool:

pub struct DSError {
    error: PoolError,
    resource_type: ResourceType,
    lookup_type: LookupType,
}

And then we can make public_error_from_diesel_pool the From that converts a DSError to an external error.

impl From<DSError> for Error {
    fn from(e: DSError) -> Self {
        public_error_from_diesel_pool(e.error, e.resource_type, e.lookup_type)
    }
}

Unfortunately it's not quite that simple, because there's also public_error_from_diesel_pool_create for create errors, which would be ok, but there are methods that might return both kinds of error, for example project create: it gives a normal error if it can't find the org, but a create error if it can't create the project.

.map_err(|e| match e {
InsertError::CollectionNotFound => Error::ObjectNotFound {
type_name: ResourceType::Organization,
lookup_type: LookupType::ById(organization_id),
},
InsertError::DatabaseError(e) => {
public_error_from_diesel_pool_create(
e,
ResourceType::Project,
&name,
)
}
})

So if there's a single common datastore Error type, it probably has to be an enum of both create and non-create error info.

@david-crespo david-crespo marked this pull request as draft November 3, 2021 15:50
@davepacheco

Copy link
Copy Markdown
Collaborator

I think authorization errors will show up too. You can have the equivalents of both Error::Unauthenticated and Error::Forbidden. We also currently return InternalError from Datastore in some cases.

@david-crespo david-crespo force-pushed the db-errors branch 2 times, most recently from f51a485 to 2288092 Compare November 8, 2021 17:37
Comment thread nexus/src/db/datastore.rs
Invariant {
message: String,
},
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

different kinds of errors have different metadata, so this becomes a whole thing

Comment thread nexus/src/db/datastore.rs
pub type LookupResult<T> = Result<T, Error>;
/** Result of an update operation for the specified type */
pub type UpdateResult<T> = Result<T, DSError>;

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

these don't all have to have the same kind of error — instead of the big pattern match on the error type in Error::from, there could be CreateError etc and they each have their own Error::from

@david-crespo

Copy link
Copy Markdown
Contributor Author

I will come back to this later.

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