Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 14 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ members = [
"src/catalog",
"src/catalog-debug",
"src/catalog-protos",
"src/catalog-types",
"src/ccsr",
"src/cloud-api",
"src/cloud-provider",
Expand Down Expand Up @@ -142,6 +143,7 @@ default-members = [
"src/catalog",
"src/catalog-debug",
"src/catalog-protos",
"src/catalog-types",
"src/ccsr",
"src/cloud-api",
"src/cloud-provider",
Expand Down
4 changes: 1 addition & 3 deletions src/catalog-protos/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,10 @@ workspace = true

[dependencies]
mz-audit-log = { path = "../audit-log" }
mz-compute-types = { path = "../compute-types" }
mz-controller-types = { path = "../controller-types" }
mz-catalog-types = { path = "../catalog-types" }
mz-proto = { path = "../proto" }
mz-repr = { path = "../repr" }
mz-sql = { path = "../sql" }
mz-storage-types = { path = "../storage-types" }
paste = "1.0.11"
proptest = { version = "1.7.0", default-features = false, features = ["std"] }
proptest-derive = { version = "0.5.1", features = ["boxed_union"] }
Expand Down
20 changes: 4 additions & 16 deletions src/catalog-protos/src/serialization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,14 @@

use std::time::Duration;

use mz_compute_types::config::ComputeReplicaLogging;
use mz_controller_types::ReplicaId;
use mz_catalog_types::cluster::ReplicaId;
use mz_catalog_types::cluster::StorageInstanceId;
use mz_catalog_types::compute::ComputeReplicaLogging;
use mz_proto::{IntoRustIfSome, ProtoMapEntry, ProtoType, RustType, TryFromProtoError};
use mz_repr::adt::mz_acl_item::{AclMode, MzAclItem};
use mz_repr::network_policy_id::NetworkPolicyId;
use mz_repr::role_id::RoleId;
use mz_repr::{CatalogItemId, GlobalId, RelationVersion, Timestamp};
use mz_repr::{CatalogItemId, GlobalId, RelationVersion};
use mz_sql::catalog::{CatalogItemType, ObjectType, RoleAttributes, RoleMembership, RoleVars};
use mz_sql::names::{
CommentObjectId, DatabaseId, ResolvedDatabaseSpecifier, SchemaId, SchemaSpecifier,
Expand All @@ -31,7 +32,6 @@ use mz_sql::plan::{
PolicyAddress,
};
use mz_sql::session::vars::OwnedVarInput;
use mz_storage_types::instances::StorageInstanceId;

use crate::objects::Empty;

Expand Down Expand Up @@ -566,18 +566,6 @@ impl RustType<crate::objects::EpochMillis> for u64 {
}
}

impl RustType<crate::objects::Timestamp> for Timestamp {
Copy link
Member Author

Choose a reason for hiding this comment

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

We're not using this implementation. Should remove the Timestamp type from the proto, but that'd require a migration.

fn into_proto(&self) -> crate::objects::Timestamp {
crate::objects::Timestamp {
internal: self.into(),
}
}

fn from_proto(proto: crate::objects::Timestamp) -> Result<Self, TryFromProtoError> {
Ok(Timestamp::new(proto.internal))
}
}

impl RustType<crate::objects::CatalogItemId> for CatalogItemId {
fn into_proto(&self) -> crate::objects::CatalogItemId {
crate::objects::CatalogItemId {
Expand Down
27 changes: 27 additions & 0 deletions src/catalog-types/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
[package]
name = "mz-catalog-types"
version = "0.0.0"
edition.workspace = true
rust-version.workspace = true
publish = false

[lints]
workspace = true

# The crate deliberately has few dependencies. Please don't add new dependencies without
# discussing with the Materialize team. Specifically, avoid adding dependencies that
# bring in large dependency trees.
[dependencies]
serde = { version = "1.0.219", features = ["derive"] }
tracing = "0.1.37"
workspace-hack = { version = "0.0.0", path = "../workspace-hack", optional = true }

[dev-dependencies]

[build-dependencies]

[package.metadata.cargo-udeps.ignore]
normal = ["workspace-hack"]

[features]
default = ["workspace-hack"]
207 changes: 207 additions & 0 deletions src/catalog-types/src/cluster.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
// Copyright Materialize, Inc. and contributors. All rights reserved.
//
// Use of this software is governed by the Business Source License
// included in the LICENSE file.
//
// As of the Change Date specified in that file, in accordance with
// the Business Source License, use of this software will be governed
// by the Apache License, Version 2.0.

//! Types related to clusters.

use std::fmt;
use std::str::FromStr;

use serde::{Deserialize, Serialize};
use tracing::error;

/// Identifier of a storage instance.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
pub enum StorageInstanceId {
/// A system storage instance.
System(u64),
/// A user storage instance.
User(u64),
}

impl StorageInstanceId {
/// Creates a new `StorageInstanceId` in the system namespace. The top 16 bits of `id` must be
/// 0, because this ID is packed into 48 bits of
/// `mz_repr::GlobalId::IntrospectionSourceIndex`.
pub fn system(id: u64) -> Option<Self> {
Self::new(id, Self::System)
}

/// Creates a new `StorageInstanceId` in the user namespace. The top 16 bits of `id` must be
/// 0, because this ID is packed into 48 bits of
/// `mz_repr::GlobalId::IntrospectionSourceIndex`.
pub fn user(id: u64) -> Option<Self> {
Self::new(id, Self::User)
}

fn new(id: u64, variant: fn(u64) -> Self) -> Option<Self> {
const MASK: u64 = 0xFFFF << 48;
const WARN_MASK: u64 = 1 << 47;
if MASK & id == 0 {
if WARN_MASK & id != 0 {
error!("{WARN_MASK} or more `StorageInstanceId`s allocated, we will run out soon");
}
Some(variant(id))
} else {
None
}
}

/// Extract the inner u64 ID.
pub fn inner_id(&self) -> u64 {
match self {
StorageInstanceId::System(id) | StorageInstanceId::User(id) => *id,
}
}

/// Returns true if this represents a user object.
pub fn is_user(&self) -> bool {
matches!(self, Self::User(_))
}

/// Returns true if this represents a system object.
pub fn is_system(&self) -> bool {
matches!(self, Self::System(_))
}
}

impl FromStr for StorageInstanceId {
type Err = IdParseError<Cluster>;

fn from_str(s: &str) -> Result<Self, Self::Err> {
if s.len() < 2 {
return Err(s.into());
}
let val: u64 = s[1..].parse()?;
match s.chars().next().unwrap() {
's' => Ok(Self::System(val)),
'u' => Ok(Self::User(val)),
_ => Err(s.into()),
}
}
}

/// An error parsing a `StorageInstanceId`.
#[derive(Debug)]
pub struct IdParseError<V> {
reason: String,
_marker: std::marker::PhantomData<V>,
}

impl<V: fmt::Debug> std::error::Error for IdParseError<V> {}

impl<V> fmt::Display for IdParseError<V> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "couldn't parse id {}", self.reason)
}
}

impl<V> From<&str> for IdParseError<V> {
fn from(reason: &str) -> Self {
reason.to_string().into()
}
}

impl<V> From<std::num::ParseIntError> for IdParseError<V> {
fn from(error: std::num::ParseIntError) -> Self {
error.to_string().into()
}
}

impl<V> From<String> for IdParseError<V> {
fn from(reason: String) -> Self {
Self {
reason,
_marker: std::marker::PhantomData,
}
}
}

impl fmt::Display for StorageInstanceId {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Self::System(id) => write!(f, "s{}", id),
Self::User(id) => write!(f, "u{}", id),
}
}
}

/// Identifier of a replica.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
pub enum ReplicaId {
/// A user replica.
User(u64),
/// A system replica.
System(u64),
}

impl ReplicaId {
/// Return the inner numeric ID value.
pub fn inner_id(&self) -> u64 {
match self {
ReplicaId::User(id) => *id,
ReplicaId::System(id) => *id,
}
}

/// Whether this value identifies a user replica.
pub fn is_user(&self) -> bool {
matches!(self, Self::User(_))
}

/// Whether this value identifies a system replica.
pub fn is_system(&self) -> bool {
matches!(self, Self::System(_))
}
}

impl fmt::Display for ReplicaId {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Self::User(id) => write!(f, "u{}", id),
Self::System(id) => write!(f, "s{}", id),
}
}
}

impl FromStr for ReplicaId {
type Err = IdParseError<Replica>;

fn from_str(s: &str) -> Result<Self, Self::Err> {
let first = s.chars().next();
let rest = s.get(1..);
if let (Some(prefix), Some(num)) = (first, rest) {
let id = num.parse()?;
match prefix {
'u' => return Ok(Self::User(id)),
's' => return Ok(Self::System(id)),
_ => (),
}
}

Err(s.into())
}
}

/// A marker type for replica ID parse errors.
#[derive(Debug)]
pub struct Replica;
impl fmt::Display for Replica {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "replica")
}
}

/// A marker type for cluster ID parse errors.
#[derive(Debug)]
pub struct Cluster;
impl fmt::Display for Cluster {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "cluster")
}
}
File renamed without changes.
15 changes: 15 additions & 0 deletions src/catalog-types/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Copyright Materialize, Inc. and contributors. All rights reserved.
//
// Use of this software is governed by the Business Source License
// included in the LICENSE file.
//
// As of the Change Date specified in that file, in accordance with
// the Business Source License, use of this software will be governed
// by the Apache License, Version 2.0.

//! Catalog configuration types.

#![deny(missing_docs)]

pub mod cluster;
pub mod compute;
2 changes: 1 addition & 1 deletion src/cluster-client/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ publish = false
workspace = true

[dependencies]
anyhow = "1.0.100"
mz-catalog-types = { path = "../catalog-types" }
mz-ore = { path = "../ore", features = ["tracing"] }
mz-repr = { path = "../repr" }
prometheus = { version = "0.14.0", default-features = false }
Expand Down
Loading