oxidecomputer / oxidecomputer/omicron

audit use of internal_error in datastore

Open
#1,343 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

mvp
Dominant language
Rust
Stars
572
Forks
97
Avg merge
2d 12h
Merged PRs (30d)
96

Description

There are a number of functions inside DataStore that do something like this:

            some_diesel_stuff
            .execute_async(self.pool())
            .await
            .map_err(|e| {
                Error::internal_error(&format!(
                    "something bad: {:?}",
                    e
                ))
            })?;

This code always produces a 500 Internal Server Error on failure, which is not correct. If the database is down or we can't connect to it, we should be producing a 503 Service Unavailable. This sounds nitty but it's critical because clients know to retry 503s, but 500s indicate bugs and should not be retried. So this can be the difference between surviving transient failures or automatically recovering from outages and ... not doing those things.

This code is correct, though loses some useful information from the internal error message:

            some_diesel_stuff
            .execute_async(self.pool())
            .await
            .map_err(|e| {
                public_error_from_diesel_pool(e, ErrorHandler::Server)
            })?;

To preserve that context, we've talked about something analogous to anyhow::Context for our own Error type. Something like: .internal_message_context that allows you to take any Result<T, Error> and prepend the "internal_message" field of the error with whatever context you give it. Then it might look like this:

            some_diesel_stuff
            .execute_async(self.pool())
            .await
            .map_err(|e| {
                public_error_from_diesel_pool(e, ErrorHandler::Server).internal_message_context("something bad")
            })?;

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by locating the DataStore functions that wrap database operations with Error::internal_error, then compare them with public_error_from_diesel_pool and ErrorHandler::Server. Audit each affected path so database connectivity failures return 503 while retaining useful internal context; the issue does not name specific files or tests.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
backend-api-design, databases
Issue type
Refactor
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
30/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.