-
Notifications
You must be signed in to change notification settings - Fork 79
Add review context comments #10075
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
Add review context comments #10075
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -2,7 +2,82 @@ | |||||||||||||||||||||||||||||||||
| // License, v. 2.0. If a copy of the MPL was not distributed with this | ||||||||||||||||||||||||||||||||||
| // file, You can obtain one at https://mozilla.org/MPL/2.0/. | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| //! Structures stored to the database. | ||||||||||||||||||||||||||||||||||
| // We only use rustdoc for internal documentation, including private items, so | ||||||||||||||||||||||||||||||||||
| // it's expected that we'll have links to private items in the docs. | ||||||||||||||||||||||||||||||||||
| #![allow(rustdoc::private_intra_doc_links)] | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| //! Rust types that represent rows in the Omicron database (CockroachDB). | ||||||||||||||||||||||||||||||||||
| //! | ||||||||||||||||||||||||||||||||||
| //! Each struct in this crate maps to a database table. The table's columns and | ||||||||||||||||||||||||||||||||||
| //! SQL types are declared in [`nexus_db_schema`] via Diesel's | ||||||||||||||||||||||||||||||||||
| //! [`table!`](diesel::table) macro; the struct here provides the corresponding | ||||||||||||||||||||||||||||||||||
| //! Rust types. `nexus_db_queries` then uses both to build and execute | ||||||||||||||||||||||||||||||||||
| //! queries in its `DataStore` methods. | ||||||||||||||||||||||||||||||||||
| //! | ||||||||||||||||||||||||||||||||||
| //! # How the mapping works | ||||||||||||||||||||||||||||||||||
| //! | ||||||||||||||||||||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think there's probably some Diesel documentation we could also link to here? |
||||||||||||||||||||||||||||||||||
| //! Consider the `vmm` table. The schema declares columns and SQL types: | ||||||||||||||||||||||||||||||||||
| //! | ||||||||||||||||||||||||||||||||||
| //! ```text | ||||||||||||||||||||||||||||||||||
| //! // in nexus-db-schema | ||||||||||||||||||||||||||||||||||
|
Comment on lines
+21
to
+22
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i think it wouldn't be too hard to turn this into |
||||||||||||||||||||||||||||||||||
| //! table! { | ||||||||||||||||||||||||||||||||||
| //! vmm (id) { | ||||||||||||||||||||||||||||||||||
| //! id -> Uuid, | ||||||||||||||||||||||||||||||||||
| //! sled_id -> Uuid, | ||||||||||||||||||||||||||||||||||
| //! state_generation -> Int8, | ||||||||||||||||||||||||||||||||||
| //! state -> VmmStateEnum, | ||||||||||||||||||||||||||||||||||
| //! ... | ||||||||||||||||||||||||||||||||||
| //! } | ||||||||||||||||||||||||||||||||||
| //! } | ||||||||||||||||||||||||||||||||||
| //! ``` | ||||||||||||||||||||||||||||||||||
| //! | ||||||||||||||||||||||||||||||||||
| //! The model struct provides the Rust representation of a row: | ||||||||||||||||||||||||||||||||||
| //! | ||||||||||||||||||||||||||||||||||
| //! ```text | ||||||||||||||||||||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. similarly, if we added some imports, we could probably turn this into |
||||||||||||||||||||||||||||||||||
| //! // in nexus-db-model | ||||||||||||||||||||||||||||||||||
| //! #[derive(Queryable, Insertable, Selectable)] | ||||||||||||||||||||||||||||||||||
| //! #[diesel(table_name = vmm)] | ||||||||||||||||||||||||||||||||||
| //! pub struct Vmm { | ||||||||||||||||||||||||||||||||||
| //! pub id: Uuid, | ||||||||||||||||||||||||||||||||||
| //! pub sled_id: DbTypedUuid<SledKind>, | ||||||||||||||||||||||||||||||||||
| //! #[diesel(column_name = state_generation)] | ||||||||||||||||||||||||||||||||||
| //! pub generation: Generation, | ||||||||||||||||||||||||||||||||||
| //! pub state: VmmState, | ||||||||||||||||||||||||||||||||||
| //! ... | ||||||||||||||||||||||||||||||||||
| //! } | ||||||||||||||||||||||||||||||||||
| //! ``` | ||||||||||||||||||||||||||||||||||
| //! | ||||||||||||||||||||||||||||||||||
| //! A few things to note: | ||||||||||||||||||||||||||||||||||
| //! | ||||||||||||||||||||||||||||||||||
| //! - **Type translation.** Each field's Rust type must implement Diesel's | ||||||||||||||||||||||||||||||||||
| //! [`FromSql`](diesel::deserialize::FromSql) and | ||||||||||||||||||||||||||||||||||
| //! [`ToSql`](diesel::serialize::ToSql) traits for the corresponding column's | ||||||||||||||||||||||||||||||||||
| //! SQL type. Diesel provides these impls for common types (`Uuid`, | ||||||||||||||||||||||||||||||||||
| //! `DateTime<Utc>`, `String`, etc.); this crate defines wrapper types like | ||||||||||||||||||||||||||||||||||
| //! [`DbTypedUuid`] for domain-specific conversions | ||||||||||||||||||||||||||||||||||
| //! (e.g. distinguishing a sled UUID from any other UUID). | ||||||||||||||||||||||||||||||||||
| //! - **Column renaming.** Field names must match column names by default, but | ||||||||||||||||||||||||||||||||||
| //! `#[diesel(column_name = ...)]` allows the Rust name to differ (e.g. | ||||||||||||||||||||||||||||||||||
| //! `generation` for the `state_generation` column). | ||||||||||||||||||||||||||||||||||
| //! - **Positional mapping.** [`diesel::Queryable`] maps SQL result columns to | ||||||||||||||||||||||||||||||||||
| //! struct fields by position, not by name. If the field order doesn't match | ||||||||||||||||||||||||||||||||||
| //! the column order in the query, fields will silently receive wrong values. | ||||||||||||||||||||||||||||||||||
| //! Deriving [`diesel::Selectable`] mitigates this by generating an explicit | ||||||||||||||||||||||||||||||||||
| //! column list, so the result columns are always in the order `Queryable` | ||||||||||||||||||||||||||||||||||
| //! expects. **Always derive both.** | ||||||||||||||||||||||||||||||||||
|
Comment on lines
+52
to
+67
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Personally, I feel like these might be nicer as level 3 subheadings rather than bullet points, at least because then we can link to them from elsewhere? |
||||||||||||||||||||||||||||||||||
| //! | ||||||||||||||||||||||||||||||||||
| //! # Field ordering convention | ||||||||||||||||||||||||||||||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we care: #9927 catches the ordering if it's incorrect. |
||||||||||||||||||||||||||||||||||
| //! | ||||||||||||||||||||||||||||||||||
| //! Fields in `Queryable`/`Insertable` structs should be ordered to match the | ||||||||||||||||||||||||||||||||||
| //! column order in `dbinit.sql`. This keeps the Rust types easy to | ||||||||||||||||||||||||||||||||||
| //! cross-reference with the schema definition and prevents subtle bugs if a | ||||||||||||||||||||||||||||||||||
| //! query ever omits `Selectable`. | ||||||||||||||||||||||||||||||||||
| //! | ||||||||||||||||||||||||||||||||||
| //! # Representing enums | ||||||||||||||||||||||||||||||||||
|
Comment on lines
+69
to
+76
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. these should probably be level 2 or level 3 headings
Suggested change
|
||||||||||||||||||||||||||||||||||
| //! | ||||||||||||||||||||||||||||||||||
| //! For types that map to database enum columns, see the [`impl_enum_type!`] | ||||||||||||||||||||||||||||||||||
| //! and [`impl_enum_wrapper!`] macros defined below. For string-backed enums, | ||||||||||||||||||||||||||||||||||
| //! see the [`DatabaseString`] trait. | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| #[macro_use] | ||||||||||||||||||||||||||||||||||
| extern crate diesel; | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6,7 +6,8 @@ | |
| //! reports (sitreps). | ||
| //! | ||
| //! See [RFD 603](https://rfd.shared.oxide.computer/rfd/0603) for details on the | ||
| //! fault management sitrep. | ||
| //! fault management sitrep, and the [datastore module documentation](super) for | ||
| //! general conventions. | ||
|
|
||
| use super::DataStore; | ||
| use crate::authz; | ||
|
|
@@ -503,6 +504,13 @@ impl DataStore { | |
| // rather than doing smaller ones for each case in the sitrep. This uses | ||
| // more memory in Nexus but reduces the number of small db queries we | ||
| // perform. | ||
| // | ||
| // The ordering of inserts among case child records (ereports, alert | ||
| // requests) and case metadata doesn't matter: there are no foreign key | ||
| // constraints between these tables, and garbage collection is keyed on | ||
| // sitrep_id (which is inserted first above). If we crash partway | ||
| // through, orphaned child records will be cleaned up when the orphaned | ||
| // sitrep is garbage collected. | ||
|
Comment on lines
+511
to
+513
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is #10131 relevant here? |
||
| let mut cases = Vec::with_capacity(sitrep.cases.len()); | ||
| let mut alerts_requested = Vec::new(); | ||
| let mut case_ereports = Vec::new(); | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -3,6 +3,19 @@ | |||||
| // file, You can obtain one at https://mozilla.org/MPL/2.0/. | ||||||
|
|
||||||
| //! Primary control plane interface for database read and write operations | ||||||
| //! | ||||||
| //! # Method naming conventions | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: i believe the typical markdown convention is that a single
Suggested change
|
||||||
| //! | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Another high-level note on naming conventions that I think might be worth writing down is that it's important to remember that almost all the database queries in this crate are defined as methods on the |
||||||
| //! Many methods in this module have a public entry point that acquires a | ||||||
| //! database connection from the pool, paired with a private `_on_conn` (or | ||||||
| //! `_on_connection`) helper that takes an explicit connection parameter. The | ||||||
| //! helper exists so that multiple queries can share the same connection without | ||||||
| //! re-acquiring one from the pool for each step of a multi-query operation. | ||||||
| //! | ||||||
| //! A related convention is `_in_txn` (or `_in_transaction`), for helpers that | ||||||
| //! run inside an explicit database transaction. These typically take an | ||||||
| //! [`OptionalError`](nexus_db_errors::OptionalError) so they can bail | ||||||
| //! out of the entire transaction on application-level errors. | ||||||
|
|
||||||
| // TODO-scalability review all queries for use of indexes (may need | ||||||
| // "time_deleted IS NOT NULL" conditions) Figure out how to automate this. | ||||||
|
|
||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be a level 2 heading since it's not the title of the entire doc comment.