Skip to content
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

[wip] Sketching out API, DB models for affinity and anti-affinity #7076

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

smklein
Copy link
Collaborator

@smklein smklein commented Nov 15, 2024

Extremely WIP, this is an exploratory implementation of RFD 522

See: #1705


#[derive(Clone, Copy, Debug, Deserialize, Serialize, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum AffinityDistance {
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Could rename this to "failure domain", if that seems useful?

Copy link
Member

Choose a reason for hiding this comment

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

I like "failure domain", seems more semantically meaningful IMO.


#[derive(Clone, Debug, Deserialize, Serialize, JsonSchema)]
pub enum AffinityGroupMember {
Instance(Uuid),
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I know this is an "enum of one", but RFD 522 discusses having anti-affinity groups which contain "either instances or affinity groups". I figured I'd just define these as "members" to be flexible for future work

#[derive(Clone, Copy, Debug, Deserialize, Serialize, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum AffinityPolicy {
Allow,
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I know I'm calling this "Allow" instead of "Alert", but without a fleshed-out alerting system, I wanted to keep this honest.

We can add "Alert" later, when it can actually be implemented.

Copy link
Member

Choose a reason for hiding this comment

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

That makes sense to me. Perhaps we should document the behavior here?

@hawkw hawkw self-requested a review November 15, 2024 18:03
Copy link
Member

@hawkw hawkw left a comment

Choose a reason for hiding this comment

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

Hopefully a quick drive-by review wasn't too premature, but this stuff is relevant to my interests, so I wanted to take a peek. Overall, everything looks very straightforward and reasonable --- I commented on a few small things, but it's quite possible you were planning to get to all of them and just hadn't gotten around to it yet.


#[derive(Clone, Copy, Debug, Deserialize, Serialize, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum AffinityDistance {
Copy link
Member

Choose a reason for hiding this comment

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

I like "failure domain", seems more semantically meaningful IMO.

Comment on lines +47 to +71
#[derive(Queryable, Insertable, Clone, Debug, Selectable)]
#[diesel(table_name = affinity_group)]
pub struct AffinityGroup {
pub id: DbTypedUuid<AffinityGroupKind>,
pub name: String,
pub description: String,
pub time_created: DateTime<Utc>,
pub time_modified: DateTime<Utc>,
pub time_deleted: Option<DateTime<Utc>>,
pub policy: AffinityPolicy,
pub distance: AffinityDistance,
}

#[derive(Queryable, Insertable, Clone, Debug, Selectable)]
#[diesel(table_name = anti_affinity_group)]
pub struct AntiAffinityGroup {
pub id: DbTypedUuid<AntiAffinityGroupKind>,
pub name: String,
pub description: String,
pub time_created: DateTime<Utc>,
pub time_modified: DateTime<Utc>,
pub time_deleted: Option<DateTime<Utc>>,
pub policy: AffinityPolicy,
pub distance: AffinityDistance,
}
Copy link
Member

Choose a reason for hiding this comment

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

Part of me wonders whether it makes sense to use the same model to represent these, since they share all the same fields...but I think the type-level distinction between what's an affinity group and what's an anti-affinity group will probably prevent bugs in the future, and using different typed UUIDs for the IDs is definitely the right move. Potentially shared bits like the policy and distance fields could be factored out later if there was a need to have functions that can operate on either, but at present it seems like there probably isn't!

Comment on lines +73 to +85
#[derive(Queryable, Insertable, Clone, Debug, Selectable)]
#[diesel(table_name = affinity_group_instance_membership)]
pub struct AffinityGroupInstanceMembership {
pub group_id: DbTypedUuid<AffinityGroupKind>,
pub instance_id: DbTypedUuid<InstanceKind>,
}

#[derive(Queryable, Insertable, Clone, Debug, Selectable)]
#[diesel(table_name = anti_affinity_group_instance_membership)]
pub struct AntiAffinityGroupInstanceMembership {
pub group_id: DbTypedUuid<AntiAffinityGroupKind>,
pub instance_id: DbTypedUuid<InstanceKind>,
}
Copy link
Member

Choose a reason for hiding this comment

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

I note that these lack created/deleted timestamps, implying that:

  1. we intend to hard-delete rather than soft-delete them, and,
  2. we don't presently record when instances were added to affinity/anti-affinity groups, so we can't present that in UIs in the future.

I'm not sure if either of these matter to us, but I figured I'd comment on it.

Comment on lines +497 to +509
table! {
affinity_group_instance_membership (group_id, instance_id) {
group_id -> Uuid,
instance_id -> Uuid,
}
}

table! {
anti_affinity_group_instance_membership (group_id, instance_id) {
group_id -> Uuid,
instance_id -> Uuid,
}
}
Copy link
Member

Choose a reason for hiding this comment

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

I presume we'll want to add joinable!/allow_tables_to_appear_in_same_query! for joining the affinity/anti-affinity group tables on the instances table?

Comment on lines +1265 to +1275
/// List members of an affinity group
#[endpoint {
method = GET,
path = "/v1/affinity-groups/{affinity_group}",
tags = ["affinity"],
}]
async fn affinity_group_member_list(
rqctx: RequestContext<Self::Context>,
query_params: Query<params::OptionalProjectSelector>,
path_params: Path<params::AffinityGroupPath>,
) -> Result<HttpResponseOk<ResultsPage<AffinityGroupMember>>, HttpError>;
Copy link
Member

Choose a reason for hiding this comment

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

This returns a ResultsPage but appears to be missing pagination params --- should it be paginated? Or am I missing something?

Comment on lines +1336 to +1346
/// List members of an anti-affinity group
#[endpoint {
method = GET,
path = "/v1/anti-affinity-groups/{anti_affinity_group}",
tags = ["affinity"],
}]
async fn anti_affinity_group_member_list(
rqctx: RequestContext<Self::Context>,
query_params: Query<params::OptionalProjectSelector>,
path_params: Path<params::AntiAffinityGroupPath>,
) -> Result<HttpResponseOk<ResultsPage<AntiAffinityGroupMember>>, HttpError>;
Copy link
Member

Choose a reason for hiding this comment

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

Similarly, should this be paginated?

#[derive(Clone, Copy, Debug, Deserialize, Serialize, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum AffinityPolicy {
Allow,
Copy link
Member

Choose a reason for hiding this comment

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

That makes sense to me. Perhaps we should document the behavior here?

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