Skip to content

Commit

Permalink
feat: add region list/resolve per game
Browse files Browse the repository at this point in the history
  • Loading branch information
MasterPtato committed Apr 12, 2024
1 parent f96c4a4 commit 1d2e1ca
Show file tree
Hide file tree
Showing 41 changed files with 611 additions and 59 deletions.
2 changes: 1 addition & 1 deletion lib/convert/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ mm-lobby-player-count = { path = "../../svc/pkg/mm/ops/lobby-player-count" }
mm-lobby-runtime-aggregate = { path = "../../svc/pkg/mm/ops/lobby-runtime-aggregate" }
mm-player-count-for-namespace = { path = "../../svc/pkg/mm/ops/player-count-for-namespace" }
region-get = { path = "../../svc/pkg/region/ops/get" }
region-list = { path = "../../svc/pkg/region/ops/list" }
region-list-for-game = { path = "../../svc/pkg/region/ops/list-for-game" }
region-resolve = { path = "../../svc/pkg/region/ops/resolve" }
team-get = { path = "../../svc/pkg/team/ops/get" }
team-member-count = { path = "../../svc/pkg/team/ops/member-count" }
Expand Down
5 changes: 3 additions & 2 deletions lib/convert/src/fetch/game.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,9 +169,10 @@ pub async fn state(

pub async fn region_summaries(
ctx: &OperationContext<()>,
game_id: Uuid,
) -> GlobalResult<Vec<models::CloudRegionSummary>> {
let list_res = op!([ctx] region_list {
..Default::default()
let list_res = op!([ctx] region_list_for_game {
game_ids: vec![game_id.into()],
})
.await?;

Expand Down
5 changes: 4 additions & 1 deletion lib/convert/src/impls/cloud/version/matchmaker/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ pub mod lobby_group;

pub async fn config_to_proto(
ctx: &OperationContext<()>,
game_id: Uuid,
value: models::CloudVersionMatchmakerConfig,
) -> GlobalResult<backend::matchmaker::VersionConfig> {
// Fetch region data required to convert models
Expand All @@ -26,7 +27,9 @@ pub async fn config_to_proto(
}
}

let regions_list = op!([ctx] region_list {}).await?;
let regions_list = op!([ctx] region_list_for_game {
game_ids: vec![game_id.into()],
}).await?;
let regions_res = op!([ctx] region_get {
region_ids: regions_list.region_ids.clone(),
})
Expand Down
3 changes: 2 additions & 1 deletion lib/convert/src/impls/cloud/version/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,13 @@ impl ApiTryFrom<backend::game::Version> for models::CloudVersionSummary {
}
pub async fn config_to_proto(
ctx: &OperationContext<()>,
game_id: Uuid,
value: models::CloudVersionConfig,
) -> GlobalResult<backend::cloud::VersionConfig> {
Ok(backend::cloud::VersionConfig {
cdn: value.cdn.map(|x| (*x).api_try_into()).transpose()?,
matchmaker: if let Some(matchmaker) = value.matchmaker {
Some(matchmaker::config_to_proto(ctx, *matchmaker).await?)
Some(matchmaker::config_to_proto(ctx, game_id, *matchmaker).await?)
} else {
None
},
Expand Down
1 change: 1 addition & 0 deletions proto/backend/cluster.proto
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ message Cluster {
rivet.common.Uuid cluster_id = 1;
string name_id = 2;
int64 create_ts = 3;
// Unset for the default cluster.
optional rivet.common.Uuid owner_team_id = 4;
}

Expand Down
47 changes: 44 additions & 3 deletions svc/Cargo.lock

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

3 changes: 3 additions & 0 deletions svc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ members = [
"pkg/cluster/ops/datacenter-resolve-for-name-id",
"pkg/cluster/ops/datacenter-topology-get",
"pkg/cluster/ops/get",
"pkg/cluster/ops/get-for-game",
"pkg/cluster/ops/server-get",
"pkg/cluster/ops/server-list",
"pkg/cluster/ops/server-resolve-for-ip",
Expand Down Expand Up @@ -199,8 +200,10 @@ members = [
"pkg/push-notification/worker",
"pkg/region/ops/get",
"pkg/region/ops/list",
"pkg/region/ops/list-for-game",
"pkg/region/ops/recommend",
"pkg/region/ops/resolve",
"pkg/region/ops/resolve-for-game",
"pkg/team-invite/ops/get",
"pkg/team-invite/worker",
"pkg/team/ops/avatar-upload-complete",
Expand Down
2 changes: 1 addition & 1 deletion svc/api/cloud/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ mm-player-count-for-namespace = { path = "../../pkg/mm/ops/player-count-for-name
job-log-read = { path = "../../pkg/job-log/ops/read" }
perf-log-get = { path = "../../pkg/perf/ops/log-get" }
region-get = { path = "../../pkg/region/ops/get" }
region-list = { path = "../../pkg/region/ops/list" }
region-list-for-game = { path = "../../pkg/region/ops/list-for-game" }
team-get = { path = "../../pkg/team/ops/get" }
team-member-count = { path = "../../pkg/team/ops/member-count" }
team-validate = { path = "../../pkg/team/ops/validate" }
Expand Down
6 changes: 3 additions & 3 deletions svc/api/cloud/src/route/games/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,8 +139,8 @@ async fn gen_default_version_config(
game_id: Uuid,
display_name: &str,
) -> GlobalResult<backend::cloud::VersionConfig> {
let list_regions_res = op!([ctx] region_list {
..Default::default()
let list_regions_res = op!([ctx] region_list_for_game {
game_ids: vec![game_id.into()],
})
.await?;

Expand Down Expand Up @@ -428,7 +428,7 @@ pub async fn get(
.map(ApiTryInto::api_try_into)
.collect::<GlobalResult<Vec<_>>>()?;

let regions = fetch::game::region_summaries(ctx.op_ctx()).await?;
let regions = fetch::game::region_summaries(ctx.op_ctx(), game_id).await?;

Ok(models::CloudGamesGetGameByIdResponse {
game: Box::new(models::CloudGameFull {
Expand Down
4 changes: 2 additions & 2 deletions svc/api/cloud/src/route/games/versions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ pub async fn create(
let user_id = ctx.auth().claims()?.as_user().ok();

let proto_config =
rivet_convert::cloud::version::config_to_proto(ctx.op_ctx(), *body.config).await?;
rivet_convert::cloud::version::config_to_proto(ctx.op_ctx(), game_id, *body.config).await?;
let publish_res = op!([ctx] cloud_version_publish {
game_id: Some(game_id.into()),
display_name: body.display_name,
Expand Down Expand Up @@ -98,7 +98,7 @@ pub async fn validate(
body: models::CloudGamesValidateGameVersionRequest,
) -> GlobalResult<models::CloudGamesValidateGameVersionResponse> {
let proto_config =
rivet_convert::cloud::version::config_to_proto(ctx.op_ctx(), *body.config).await?;
rivet_convert::cloud::version::config_to_proto(ctx.op_ctx(), game_id, *body.config).await?;
let res = op!([ctx] game_version_validate {
game_id: Some(game_id.into()),
display_name: body.display_name,
Expand Down
3 changes: 2 additions & 1 deletion svc/api/matchmaker/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ captcha-verify = { path = "../../pkg/captcha/ops/verify" }
cdn-namespace-get = { path = "../../pkg/cdn/ops/namespace-get" }
game-namespace-get = { path = "../../pkg/game/ops/namespace-get" }
game-namespace-resolve-url = { path = "../../pkg/game/ops/namespace-resolve-url" }
game-resolve-namespace-id = { path = "../../pkg/game/ops/resolve-namespace-id" }
game-user-get = { path = "../../pkg/game-user/ops/get" }
captcha-hcaptcha-config-get = { path = "../../pkg/captcha/ops/hcaptcha-config-get" }
job-run-get = { path = "../../pkg/job-run/ops/get" }
Expand All @@ -55,7 +56,7 @@ mm-lobby-player-count = { path = "../../pkg/mm/ops/lobby-player-count" }
mm-lobby-state-get = { path = "../../pkg/mm/ops/lobby-state-get" }
region-get = { path = "../../pkg/region/ops/get" }
region-recommend = { path = "../../pkg/region/ops/recommend" }
region-resolve = { path = "../../pkg/region/ops/resolve" }
region-resolve-for-game = { path = "../../pkg/region/ops/resolve-for-game" }
token-create = { path = "../../pkg/token/ops/create" }
token-revoke = { path = "../../pkg/token/ops/revoke" }
user-identity-get = { path = "../../pkg/user-identity/ops/get" }
Expand Down
27 changes: 23 additions & 4 deletions svc/api/matchmaker/src/route/lobbies.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,15 @@ pub async fn find(
);

let game_ns = ctx.auth().game_ns(&ctx).await?;
let ns_data = fetch_ns(&ctx, &game_ns).await?;

let (ns_data, game_resolve_res) = tokio::try_join!(
fetch_ns(&ctx, &game_ns),
op!([ctx] game_resolve_namespace_id {
namespace_ids: vec![game_ns.namespace_id.into()],
}),
)?;
let game = unwrap!(game_resolve_res.games.first());
let game_id = unwrap_ref!(game.game_id);

// Fetch version data
let version_res = op!([ctx] mm_config_version_get {
Expand Down Expand Up @@ -186,7 +194,8 @@ pub async fn find(
}

// Resolve region IDs
let region_ids = resolve_region_ids(&ctx, coords, body.regions.as_ref(), &lobby_groups).await?;
let region_ids =
resolve_region_ids(&ctx, coords, body.regions.as_ref(), game_id, &lobby_groups).await?;

// Validate that there is a lobby group and region pair that is valid.
//
Expand Down Expand Up @@ -299,7 +308,14 @@ pub async fn create(
ctx.auth().game_ns(&ctx),
ctx.auth().fetch_game_user_option(ctx.op_ctx()),
)?;
let ns_data = fetch_ns(&ctx, &game_ns).await?;
let (ns_data, game_resolve_res) = tokio::try_join!(
fetch_ns(&ctx, &game_ns),
op!([ctx] game_resolve_namespace_id {
namespace_ids: vec![game_ns.namespace_id.into()],
}),
)?;
let game = unwrap!(game_resolve_res.games.first());
let game_id = unwrap_ref!(game.game_id);

// Fetch version config
let version_config_res = op!([ctx] mm_config_version_get {
Expand Down Expand Up @@ -418,6 +434,7 @@ pub async fn create(
&ctx,
coords,
body.region.map(|r| vec![r]).as_ref(),
game_id,
&[(lobby_group, lobby_group_meta)],
)
.await?;
Expand Down Expand Up @@ -1171,14 +1188,16 @@ async fn resolve_region_ids(
ctx: &Ctx<Auth>,
coords: Option<(f64, f64)>,
regions: Option<&Vec<String>>,
game_id: &common::Uuid,
lobby_groups: &[(
&backend::matchmaker::LobbyGroup,
&backend::matchmaker::LobbyGroupMeta,
)],
) -> GlobalResult<Vec<Uuid>> {
let region_ids = if let Some(region_name_ids) = regions {
// Resolve the region ID corresponding to the name IDs
let resolve_res = op!([ctx] region_resolve {
let resolve_res = op!([ctx] region_resolve_for_game {
game_id: Some(*game_id),
name_ids: region_name_ids.clone(),
})
.await?;
Expand Down
1 change: 0 additions & 1 deletion svc/api/matchmaker/src/route/regions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ pub async fn list(
}

let game_ns = ctx.auth().game_ns(&ctx).await?;

let ns_data = fetch_ns(&ctx, &game_ns).await?;

// Fetch version data
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,3 +93,9 @@ CREATE TABLE server_images_linode_misc (
INDEX (public_ip),
INDEX (image_id)
);

-- Dictates which cluster a game's lobbies will be created in
CREATE TABLE games (
game_id UUID PRIMARY KEY,
cluster_id UUID NOT NULL
);
18 changes: 18 additions & 0 deletions svc/pkg/cluster/ops/get-for-game/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[package]
name = "cluster-get-for-game"
version = "0.0.1"
edition = "2018"
authors = ["Rivet Gaming, LLC <developer@rivet.gg>"]
license = "Apache-2.0"

[dependencies]
chirp-client = { path = "../../../../../lib/chirp/client" }
prost = "0.10"
rivet-operation = { path = "../../../../../lib/operation/core" }

[dependencies.sqlx]
version = "0.7"
default-features = false

[dev-dependencies]
chirp-worker = { path = "../../../../../lib/chirp/worker" }
10 changes: 10 additions & 0 deletions svc/pkg/cluster/ops/get-for-game/Service.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[service]
name = "cluster-get-for-game"

[runtime]
kind = "rust"

[operation]

[databases]
db-cluster = {}
42 changes: 42 additions & 0 deletions svc/pkg/cluster/ops/get-for-game/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
use proto::backend::pkg::*;
use rivet_operation::prelude::*;

#[operation(name = "cluster-get-for-game")]
pub async fn handle(
ctx: OperationContext<cluster::get_for_game::Request>,
) -> GlobalResult<cluster::get_for_game::Response> {
let game_ids = ctx
.game_ids
.iter()
.map(common::Uuid::as_uuid)
.collect::<Vec<_>>();

let rows = sql_fetch_optional!(
[ctx, (Uuid, Option<Uuid>)]
"
SELECT
g.game_id, gc.cluster_id
FROM unnest($1) AS g(game_id)
LEFT JOIN db_cluster.games AS gc
ON g.game_id = gc.game_id
",
game_ids,
)
.await?;

Ok(cluster::get_for_game::Response {
games: rows
.into_iter()
.map(
|(game_id, cluster_id)| cluster::get_for_game::response::Game {
game_id: Some(game_id.into()),
cluster_id: Some(
cluster_id
.unwrap_or_else(util::env::default_cluster_id)
.into(),
),
},
)
.collect::<Vec<_>>(),
})
}
Loading

0 comments on commit 1d2e1ca

Please sign in to comment.