diff --git a/CHANGELOG.md b/CHANGELOG.md index 1432bfe99d..3625e5a666 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,12 +9,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- **Cloud** Support multipart uploads for builds - **Infra** Support configuring multiple S3 providers - **Infra** Support multipart uploads - **Infra** Replace Promtail-based log shipping with native Loki Docker driver -- **Infra** Add local Traefik Cloudflare proxy daemon for connecting to Cloudflare Access services +- **Infra** Local Traefik Cloudflare proxy daemon for connecting to Cloudflare Access services +- **Infra** Upload service builds to default S3 provider instead of hardcoded bucket - **Bolt** Support for connecting to Redis databases with `bolt redis sh` -- **Bolt** Add confirmation before running any command in the production namespace +- **Bolt** Confirmation before running any command in the production namespace +- **Bolt** `--start-at` flag for all infra commands ### Changed @@ -25,12 +28,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - **Infra** Update Consul to 1.16.0 - **Infra** Update Imagor to 1.4.7 - **Infra** Update NATS server to 2.9.20 -- **Infra** Update Node Exporter server to 1.6.1 -- **Infra** Update Nomad to 1.6.1 +- **Infra** Update Node Exporter server to 1.6.0 +- **Infra** Update Nomad to 1.6.0 - **Infra** Update Prometheus server to 2.46.0 - **Infra** Update Redis Exporter to 1.52.0 - **Infra** Update Redis to 7.0.12 - **Infra** Update Treafik to 2.10.4 +- **Bolt** PostHog events are now captured in a background task +- **Bolt** Auto-install rsync on Salt Master +- **Bolt** Recursively add dependencies from overridden services when using additional roots +- **KV** Significantly rate limit of all endpoints ### Security @@ -40,4 +47,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - **Portal** Skip captcha if no Turnstile key provided - **Infra** Resolve [RUSTSEC-2023-0044](https://rustsec.org/advisories/RUSTSEC-2023-0044) +- **Infra** Missing dpenedency on mounting volumn before setting permissions of /var/* for Cockroach, ClickHouse, Prometheus, and Traffic Server +- **Chrip** Empty message parameters now have placeholder so NATS doesn't throw an error +- **Chrip** Messages with no parameters no longer have a trailing dot - **Bolt** Correctly resolve project root when building services natively +- **Bolt** Correctly determine executable path for `ExecServiceDriver::UploadedBinaryArtifact` with different Cargo names + diff --git a/docs/getting_started/INTERNAL_DASHBOARDS.md b/docs/getting_started/INTERNAL_DASHBOARDS.md index 5ff86616ab..bb907fa1ed 100644 --- a/docs/getting_started/INTERNAL_DASHBOARDS.md +++ b/docs/getting_started/INTERNAL_DASHBOARDS.md @@ -6,14 +6,14 @@ Exposed tunnels & applications are configured [here](/lib/bolt/core/src/dep/terr Replace `MAIN_DOMAIN` with the value of `dns.domain.main`. -- [Consul](https://consul.MAIN_DOMAIN)) -- [Nomad](https://nomad.MAIN_DOMAIN)) -- [Cockroach](https://cockroach-http.MAIN_DOMAIN)) -- [ClickHouse](https://clickhouse-http.MAIN_DOMAIN)) -- [Prometheus (svc)](https://prometheus-svc.MAIN_DOMAIN)) -- [Prometheus (job)](https://prometheus-job.MAIN_DOMAIN)) -- [Minio](https://minio-console.MAIN_DOMAIN)) -- [Traefik (proxied)](https://ing-px.MAIN_DOMAIN)) -- [Traefik (job)](https://ing-job.MAIN_DOMAIN)) +- [Consul](https://consul.MAIN_DOMAIN) +- [Nomad](https://nomad.MAIN_DOMAIN) +- [Cockroach](https://cockroach-http.MAIN_DOMAIN) +- [ClickHouse](https://clickhouse-http.MAIN_DOMAIN) +- [Prometheus (svc)](https://prometheus-svc.MAIN_DOMAIN) +- [Prometheus (job)](https://prometheus-job.MAIN_DOMAIN) +- [Minio](https://minio-console.MAIN_DOMAIN) +- [Traefik (proxied)](https://ing-px.MAIN_DOMAIN) +- [Traefik (job)](https://ing-job.MAIN_DOMAIN) - This does not support regional dashboards at the moment (SVC-2584) - Will choose a random region until fixed diff --git a/docs/infrastructure/nats/TROUBLESHOOTING.md b/docs/infrastructure/nats/TROUBLESHOOTING.md new file mode 100644 index 0000000000..27f9acd3bc --- /dev/null +++ b/docs/infrastructure/nats/TROUBLESHOOTING.md @@ -0,0 +1,10 @@ +# Troubleshooting + +## Checking the health of the cluster manually... + +1. `bolt ssh pool nats` +2. `nix-shell -p natscli` +3. `nats --server=10.0.44.2:4222 --user admin --password password context save default` +4. `nats context select default` +5. `nats server report connections` + diff --git a/docs/infrastructure/saltstack/TROUBLESHOOTING.md b/docs/infrastructure/saltstack/TROUBLESHOOTING.md index 331675e0d9..0f624cdcec 100644 --- a/docs/infrastructure/saltstack/TROUBLESHOOTING.md +++ b/docs/infrastructure/saltstack/TROUBLESHOOTING.md @@ -31,3 +31,15 @@ Try a few things to figure this out: - Run `pstree -p my-pid` on the `salt-minion` process to see what subcommand is being ran - Read the `salt-minion` logs with `journalctl -u salt-minion` - Try applying specific SLS files with `salt apply 'my-minion' --sls my_file` + +## Error when bootstrapping Minion: `RSA key format is not supported` + +```bash +# Uninstall Salt +bolt ssh name staging-lnd-atl-crdb-05-2 'systemctl stop salt-minion; apt remove -y salt-cloud salt-common salt-minion; rm -rf /etc/salt /opt/saltstack /var/log/salt /var/cache/salt /run/salt /usr/bin/salt-*; echo Done' + +# Re-run install_salt_minion +(cd infra/tf/pools && terraform state rm 'module.install_salt_minion["staging-lnd-atl-crdb-05-2"]') +bolt tf apply pools +``` + diff --git a/errors/mm/auto-create-failed.md b/errors/mm/auto-create-failed.md new file mode 100644 index 0000000000..5a7cc00e3e --- /dev/null +++ b/errors/mm/auto-create-failed.md @@ -0,0 +1,9 @@ +--- +name = "MATCHMAKER_AUTO_CREATE_FAILED" +description = "Could not find a valid game mode and region pair for automatic lobby creation." +http_status = 400 +--- + +# Matchmaker Auto Create Failed + +Could not find a valid game mode and region pair for automatic lobby creation. diff --git a/errors/mm/custom-lobbies-disabled.md b/errors/mm/custom-lobbies-disabled.md new file mode 100644 index 0000000000..278aa2f096 --- /dev/null +++ b/errors/mm/custom-lobbies-disabled.md @@ -0,0 +1,9 @@ +--- +name = "MATCHMAKER_CUSTOM_LOBBIES_DISABLED" +description = "Custom lobbies are not allowed for the selected game mode." +http_status = 400 +--- + +# Matchmaker Custom Lobbies Disabled + +Custom lobbies are not allowed for the selected game mode. diff --git a/errors/mm/custom-lobby-config-invalid.md b/errors/mm/custom-lobby-config-invalid.md new file mode 100644 index 0000000000..982b743c17 --- /dev/null +++ b/errors/mm/custom-lobby-config-invalid.md @@ -0,0 +1,10 @@ +--- +name = "MATCHMAKER_CUSTOM_LOBBY_CONFIG_INVALID" +description = "The given custom lobby config is invalid: {reason}" +description_basic = "The given custom lobby config is invalid." +http_status = 400 +--- + +# Matchmaker Custom Lobby Config Invalid + +The given custom lobby config is invalid. This is most likely because it exceeds the maximum size limit of 16KiB. diff --git a/errors/mm/custom-lobby-limit-reached.md b/errors/mm/custom-lobby-limit-reached.md new file mode 100644 index 0000000000..c62f995bf2 --- /dev/null +++ b/errors/mm/custom-lobby-limit-reached.md @@ -0,0 +1,9 @@ +--- +name = "MATCHMAKER_CUSTOM_LOBBY_LIMIT_REACHED" +description = "User cannot create any more custom lobbies." +http_status = 400 +--- + +# Matchmaker Custom Lobby Limit Reached + +User cannot create any more custom lobbies. diff --git a/errors/mm/find-disabled.md b/errors/mm/find-disabled.md new file mode 100644 index 0000000000..4b9c1c7905 --- /dev/null +++ b/errors/mm/find-disabled.md @@ -0,0 +1,9 @@ +--- +name = "MATCHMAKER_FIND_DISABLED" +description = "The find endpoint has been disabled by the developer." +http_status = 400 +--- + +# Matchmaker Find Disabled + +The find endpoint has been disabled by the developer. diff --git a/errors/mm/identity-required.md b/errors/mm/identity-required.md new file mode 100644 index 0000000000..f3ab928bf1 --- /dev/null +++ b/errors/mm/identity-required.md @@ -0,0 +1,12 @@ +--- +name = "MATCHMAKER_IDENTITY_REQUIRED" +description = "This resource can not be accessed without an identity." +http_status = 400 +--- + +# Matchmaker Identity Required + +This resource can not be accessed without an identity. + +If you are a developer seeing this error, make sure your API calls to matchmaker endpoints include a bearer +token with game user entitlements. diff --git a/errors/mm/join-disabled.md b/errors/mm/join-disabled.md new file mode 100644 index 0000000000..0ed4dea4d6 --- /dev/null +++ b/errors/mm/join-disabled.md @@ -0,0 +1,9 @@ +--- +name = "MATCHMAKER_JOIN_DISABLED" +description = "The join endpoint has been disabled by the developer." +http_status = 400 +--- + +# Matchmaker Join Disabled + +The join endpoint has been disabled by the developer. diff --git a/errors/mm/region-not-enabled-for-game-mode.md b/errors/mm/region-not-enabled-for-game-mode.md index 12661c9919..3514ac8b97 100644 --- a/errors/mm/region-not-enabled-for-game-mode.md +++ b/errors/mm/region-not-enabled-for-game-mode.md @@ -4,7 +4,7 @@ description = "Region not enabled for game mode." http_status = 400 --- -# Matchmaker Region Not Enabled +# Matchmaker Region Not Enabled For Game Mode The region is not enabled for the game mode. diff --git a/errors/mm/region-not-found.md b/errors/mm/region-not-found.md new file mode 100644 index 0000000000..a7ce22092f --- /dev/null +++ b/errors/mm/region-not-found.md @@ -0,0 +1,9 @@ +--- +name = "MATCHMAKER_REGION_NOT_FOUND" +description = "One or more of the provided regions was not found." +http_status = 400 +--- + +# Matchmaker Region Not Found + +The region(s) provided were not found. diff --git a/errors/mm/registration-required.md b/errors/mm/registration-required.md new file mode 100644 index 0000000000..367229ab65 --- /dev/null +++ b/errors/mm/registration-required.md @@ -0,0 +1,12 @@ +--- +name = "MATCHMAKER_REGISTRATION_REQUIRED" +description = "This resource can not be accessed without a registered identity." +http_status = 400 +--- + +# Matchmaker Registration Required + +This resource can not be accessed without a registered identity. + +If you are a developer seeing this error, make sure your API calls to matchmaker endpoints include a bearer +token with game user entitlements, and the given game user is registered on Rivet. diff --git a/errors/mm/verification-failed.md b/errors/mm/verification-failed.md new file mode 100644 index 0000000000..80171e565a --- /dev/null +++ b/errors/mm/verification-failed.md @@ -0,0 +1,9 @@ +--- +name = "MATCHMAKER_VERIFICATION_FAILED" +description = "The user did not pass external matchmaker verification." +http_status = 400 +--- + +# Matchmaker Verification Failed + +The user did not pass external matchmaker verification. diff --git a/errors/mm/verification-request-failed.md b/errors/mm/verification-request-failed.md new file mode 100644 index 0000000000..8a6c4e3e9b --- /dev/null +++ b/errors/mm/verification-request-failed.md @@ -0,0 +1,13 @@ +--- +name = "MATCHMAKER_VERIFICATION_REQUEST_FAILED" +description = "The external matchmaker verification system failed or returned an invalid response." +http_status = 400 +--- + +# Matchmaker Verification Failed + +The external matchmaker verification system failed or returned an invalid response. This is not an error that +has been caused by the user. + +If you are a developer seeing this error, check to see if your external matchmaker verification server is +correctly responding to Rivet's requests. diff --git a/fern/api/definition/cloud/games/builds.yml b/fern/api/definition/cloud/games/builds.yml index 0fe300e243..b6e3caac62 100644 --- a/fern/api/definition/cloud/games/builds.yml +++ b/fern/api/definition/cloud/games/builds.yml @@ -44,6 +44,8 @@ types: docs: A tag given to the game build. type: string image_file: uploadCommons.PrepareFile + multipart_upload: + type: optional CreateGameBuildResponse: properties: @@ -51,8 +53,6 @@ types: type: uuid upload_id: type: uuid - image_presigned_request: - docs: >- - **Deprecated: use image_presigned_requests instead** - type: uploadCommons.PresignedRequest - image_presigned_requests: list + image_presigned_request: optional + image_presigned_requests: optional> + diff --git a/fern/api/definition/cloud/version/matchmaker/game_mode.yml b/fern/api/definition/cloud/version/matchmaker/game_mode.yml index 3bc68c7719..543af12ddc 100644 --- a/fern/api/definition/cloud/version/matchmaker/game_mode.yml +++ b/fern/api/definition/cloud/version/matchmaker/game_mode.yml @@ -18,6 +18,15 @@ types: type: optional docker: type: optional + listable: + type: optional + + find_config: + type: optional + join_config: + type: optional + create_config: + type: optional # Region overrides tier: @@ -76,3 +85,58 @@ types: properties: min: integer max: integer + + GameModeIdentityRequirement: + docs: >- + The registration requirement for a user when joining/finding/creating a + lobby. "None" allows for connections without an identity. + enum: + - none + - guest + - registered + + GameModeVerificationConfig: + # TODO: Add link to tutorial in docs + docs: >- + Configuration that tells Rivet where to send validation requests and with + what headers. When set, Rivet will send the `verification_data` property + (given by the user in the find/join/create endpoint) to the given url + along with the headers provided and some information about the requested + lobby. The response of this request will determine if the user can join + that lobby or not. + properties: + url: string + headers: map + + GameModeFindConfig: + docs: >- + Configures the requirements and authentication for the /find endpoint. + If this value is not set in the config, the /find endpoint is still enabled. + properties: + enabled: + docs: Sets whether or not the /find endpoint is enabled. + type: boolean + identity_requirement: GameModeIdentityRequirement + verification_config: optional + + GameModeJoinConfig: + docs: >- + Configures the requirements and authentication for the /join endpoint. + If this value is not set in the config, the /join endpoint is still enabled. + properties: + enabled: + docs: Sets whether or not the /join endpoint is enabled. + type: boolean + identity_requirement: GameModeIdentityRequirement + verification_config: optional + + GameModeCreateConfig: + docs: >- + Configures the requirements and authentication for the /create endpoint. + If this value is not set in the config, the /create endpoint is NOT enabled. + properties: + identity_requirement: GameModeIdentityRequirement + verification_config: optional + enable_public: boolean + enable_private: boolean + max_lobbies_per_identity: optional diff --git a/fern/api/definition/matchmaker/common.yml b/fern/api/definition/matchmaker/common.yml index eb6a509470..b89dab0f3c 100644 --- a/fern/api/definition/matchmaker/common.yml +++ b/fern/api/definition/matchmaker/common.yml @@ -86,3 +86,8 @@ types: Pass this token through the socket to the lobby server. The lobby server will validate this token with `PlayerConnected.player_token` type: commons.JWT + + CustomLobbyPublicity: + enum: + - public + - private diff --git a/fern/api/definition/matchmaker/lobbies.yml b/fern/api/definition/matchmaker/lobbies.yml index 8b3e2c015f..ce66f6c209 100644 --- a/fern/api/definition/matchmaker/lobbies.yml +++ b/fern/api/definition/matchmaker/lobbies.yml @@ -49,6 +49,7 @@ service: regions: optional> prevent_auto_create_lobby: optional captcha: optional + verification_data: optional response: FindLobbyResponse join: @@ -64,8 +65,26 @@ service: properties: lobby_id: string captcha: optional + verification_data: optional response: JoinLobbyResponse + create: + path: /create + method: POST + docs: | + Creates a custom lobby. + request: + name: CreateLobbyRequest + body: + properties: + game_mode: string + region: optional + captcha: optional + publicity: localCommons.CustomLobbyPublicity + lobby_config: optional + verification_data: optional + response: CreateLobbyResponse + list: path: /list method: GET @@ -85,6 +104,12 @@ types: ports: map player: matchmakerCommons.JoinPlayer + CreateLobbyResponse: + properties: + lobby: matchmakerCommons.JoinLobby + ports: map + player: matchmakerCommons.JoinPlayer + ListLobbiesResponse: properties: game_modes: list diff --git a/gen/openapi/external/spec/openapi.yml b/gen/openapi/external/spec/openapi.yml index c24c4c0d10..ffe382ef24 100644 --- a/gen/openapi/external/spec/openapi.yml +++ b/gen/openapi/external/spec/openapi.yml @@ -7500,6 +7500,7 @@ paths: type: boolean captcha: $ref: '#/components/schemas/CaptchaConfig' + verification_data: {} required: - game_modes /lobbies/join: @@ -7569,8 +7570,83 @@ paths: type: string captcha: $ref: '#/components/schemas/CaptchaConfig' + verification_data: {} required: - lobby_id + /lobbies/create: + post: + description: | + Creates a custom lobby. + operationId: matchmaker_lobbies_create + tags: + - MatchmakerLobbies + parameters: [] + responses: + '200': + description: '' + content: + application/json: + schema: + $ref: '#/components/schemas/MatchmakerCreateLobbyResponse' + '400': + description: '' + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorBody' + '403': + description: '' + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorBody' + '404': + description: '' + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorBody' + '408': + description: '' + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorBody' + '429': + description: '' + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorBody' + '500': + description: '' + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorBody' + servers: + - url: https://matchmaker.api.rivet.gg/v1 + security: *ref_0 + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + game_mode: + type: string + region: + type: string + captcha: + $ref: '#/components/schemas/CaptchaConfig' + publicity: + $ref: '#/components/schemas/MatchmakerCustomLobbyPublicity' + lobby_config: {} + verification_data: {} + required: + - game_mode + - publicity /lobbies/list: get: description: Lists all open lobbies. @@ -9882,6 +9958,8 @@ components: description: A tag given to the game build. image_file: $ref: '#/components/schemas/UploadPrepareFile' + multipart_upload: + type: boolean required: - display_name - image_tag @@ -9897,7 +9975,6 @@ components: format: uuid image_presigned_request: $ref: '#/components/schemas/UploadPresignedRequest' - description: '**Deprecated: use image_presigned_requests instead**' image_presigned_requests: type: array items: @@ -9905,8 +9982,6 @@ components: required: - build_id - upload_id - - image_presigned_request - - image_presigned_requests CloudGamesListGameCdnSitesResponse: type: object properties: @@ -10504,6 +10579,14 @@ components: type: integer docker: $ref: '#/components/schemas/CloudVersionMatchmakerGameModeRuntimeDocker' + listable: + type: boolean + find_config: + $ref: '#/components/schemas/CloudVersionMatchmakerGameModeFindConfig' + join_config: + $ref: '#/components/schemas/CloudVersionMatchmakerGameModeJoinConfig' + create_config: + $ref: '#/components/schemas/CloudVersionMatchmakerGameModeCreateConfig' tier: type: string idle_lobbies: @@ -10578,6 +10661,95 @@ components: required: - min - max + CloudVersionMatchmakerGameModeIdentityRequirement: + type: string + enum: + - none + - guest + - registered + description: >- + The registration requirement for a user when joining/finding/creating a + lobby. "None" allows for connections without an identity. + CloudVersionMatchmakerGameModeVerificationConfig: + type: object + description: >- + Configuration that tells Rivet where to send validation requests and + with what headers. When set, Rivet will send the `verification_data` + property (given by the user in the find/join/create endpoint) to the + given url along with the headers provided and some information about the + requested lobby. The response of this request will determine if the user + can join that lobby or not. + properties: + url: + type: string + headers: + type: object + additionalProperties: + type: string + required: + - url + - headers + CloudVersionMatchmakerGameModeFindConfig: + type: object + description: >- + Configures the requirements and authentication for the /find endpoint. + If this value is not set in the config, the /find endpoint is still + enabled. + properties: + enabled: + type: boolean + description: Sets whether or not the /find endpoint is enabled. + identity_requirement: + $ref: >- + #/components/schemas/CloudVersionMatchmakerGameModeIdentityRequirement + verification_config: + $ref: >- + #/components/schemas/CloudVersionMatchmakerGameModeVerificationConfig + required: + - enabled + - identity_requirement + CloudVersionMatchmakerGameModeJoinConfig: + type: object + description: >- + Configures the requirements and authentication for the /join endpoint. + If this value is not set in the config, the /join endpoint is still + enabled. + properties: + enabled: + type: boolean + description: Sets whether or not the /join endpoint is enabled. + identity_requirement: + $ref: >- + #/components/schemas/CloudVersionMatchmakerGameModeIdentityRequirement + verification_config: + $ref: >- + #/components/schemas/CloudVersionMatchmakerGameModeVerificationConfig + required: + - enabled + - identity_requirement + CloudVersionMatchmakerGameModeCreateConfig: + type: object + description: >- + Configures the requirements and authentication for the /create endpoint. + If this value is not set in the config, the /create endpoint is NOT + enabled. + properties: + identity_requirement: + $ref: >- + #/components/schemas/CloudVersionMatchmakerGameModeIdentityRequirement + verification_config: + $ref: >- + #/components/schemas/CloudVersionMatchmakerGameModeVerificationConfig + enable_public: + type: boolean + enable_private: + type: boolean + max_lobbies_per_identity: + type: integer + required: + - identity_requirement + - enable_public + - enable_private CloudVersionMatchmakerLobbyGroup: type: object description: A game mode. @@ -11783,6 +11955,11 @@ components: server will validate this token with `PlayerConnected.player_token` required: - token + MatchmakerCustomLobbyPublicity: + type: string + enum: + - public + - private MatchmakerFindLobbyResponse: type: object properties: @@ -11813,6 +11990,21 @@ components: - lobby - ports - player + MatchmakerCreateLobbyResponse: + type: object + properties: + lobby: + $ref: '#/components/schemas/MatchmakerJoinLobby' + ports: + type: object + additionalProperties: + $ref: '#/components/schemas/MatchmakerJoinPort' + player: + $ref: '#/components/schemas/MatchmakerJoinPlayer' + required: + - lobby + - ports + - player MatchmakerListLobbiesResponse: type: object properties: diff --git a/gen/openapi/internal/rust/.openapi-generator/FILES b/gen/openapi/internal/rust/.openapi-generator/FILES index 11fe5f1b45..f41adecaad 100644 --- a/gen/openapi/internal/rust/.openapi-generator/FILES +++ b/gen/openapi/internal/rust/.openapi-generator/FILES @@ -184,10 +184,15 @@ docs/CloudVersionMatchmakerCaptchaTurnstile.md docs/CloudVersionMatchmakerCaptchaTurnstileDomain.md docs/CloudVersionMatchmakerConfig.md docs/CloudVersionMatchmakerGameMode.md +docs/CloudVersionMatchmakerGameModeCreateConfig.md +docs/CloudVersionMatchmakerGameModeFindConfig.md +docs/CloudVersionMatchmakerGameModeIdentityRequirement.md docs/CloudVersionMatchmakerGameModeIdleLobbiesConfig.md +docs/CloudVersionMatchmakerGameModeJoinConfig.md docs/CloudVersionMatchmakerGameModeRegion.md docs/CloudVersionMatchmakerGameModeRuntimeDocker.md docs/CloudVersionMatchmakerGameModeRuntimeDockerPort.md +docs/CloudVersionMatchmakerGameModeVerificationConfig.md docs/CloudVersionMatchmakerLobbyGroup.md docs/CloudVersionMatchmakerLobbyGroupIdleLobbiesConfig.md docs/CloudVersionMatchmakerLobbyGroupRegion.md @@ -307,6 +312,8 @@ docs/KvListResponse.md docs/KvPutBatchRequest.md docs/KvPutEntry.md docs/KvPutRequest.md +docs/MatchmakerCreateLobbyResponse.md +docs/MatchmakerCustomLobbyPublicity.md docs/MatchmakerFindLobbyResponse.md docs/MatchmakerGameModeInfo.md docs/MatchmakerGameModeStatistics.md @@ -320,6 +327,7 @@ docs/MatchmakerJoinRegion.md docs/MatchmakerListLobbiesResponse.md docs/MatchmakerListRegionsResponse.md docs/MatchmakerLobbiesApi.md +docs/MatchmakerLobbiesCreateRequest.md docs/MatchmakerLobbiesFindRequest.md docs/MatchmakerLobbiesJoinRequest.md docs/MatchmakerLobbiesSetClosedRequest.md @@ -543,10 +551,15 @@ src/models/cloud_version_matchmaker_captcha_turnstile.rs src/models/cloud_version_matchmaker_captcha_turnstile_domain.rs src/models/cloud_version_matchmaker_config.rs src/models/cloud_version_matchmaker_game_mode.rs +src/models/cloud_version_matchmaker_game_mode_create_config.rs +src/models/cloud_version_matchmaker_game_mode_find_config.rs +src/models/cloud_version_matchmaker_game_mode_identity_requirement.rs src/models/cloud_version_matchmaker_game_mode_idle_lobbies_config.rs +src/models/cloud_version_matchmaker_game_mode_join_config.rs src/models/cloud_version_matchmaker_game_mode_region.rs src/models/cloud_version_matchmaker_game_mode_runtime_docker.rs src/models/cloud_version_matchmaker_game_mode_runtime_docker_port.rs +src/models/cloud_version_matchmaker_game_mode_verification_config.rs src/models/cloud_version_matchmaker_lobby_group.rs src/models/cloud_version_matchmaker_lobby_group_idle_lobbies_config.rs src/models/cloud_version_matchmaker_lobby_group_region.rs @@ -657,6 +670,8 @@ src/models/kv_list_response.rs src/models/kv_put_batch_request.rs src/models/kv_put_entry.rs src/models/kv_put_request.rs +src/models/matchmaker_create_lobby_response.rs +src/models/matchmaker_custom_lobby_publicity.rs src/models/matchmaker_find_lobby_response.rs src/models/matchmaker_game_mode_info.rs src/models/matchmaker_game_mode_statistics.rs @@ -669,6 +684,7 @@ src/models/matchmaker_join_port_range.rs src/models/matchmaker_join_region.rs src/models/matchmaker_list_lobbies_response.rs src/models/matchmaker_list_regions_response.rs +src/models/matchmaker_lobbies_create_request.rs src/models/matchmaker_lobbies_find_request.rs src/models/matchmaker_lobbies_join_request.rs src/models/matchmaker_lobbies_set_closed_request.rs diff --git a/gen/openapi/internal/rust/README.md b/gen/openapi/internal/rust/README.md index efa6219597..84d65b8cbc 100644 --- a/gen/openapi/internal/rust/README.md +++ b/gen/openapi/internal/rust/README.md @@ -148,6 +148,7 @@ Class | Method | HTTP request | Description *KvApi* | [**kv_list**](docs/KvApi.md#kv_list) | **GET** /entries/list | *KvApi* | [**kv_put**](docs/KvApi.md#kv_put) | **PUT** /entries | *KvApi* | [**kv_put_batch**](docs/KvApi.md#kv_put_batch) | **PUT** /entries/batch | +*MatchmakerLobbiesApi* | [**matchmaker_lobbies_create**](docs/MatchmakerLobbiesApi.md#matchmaker_lobbies_create) | **POST** /lobbies/create | *MatchmakerLobbiesApi* | [**matchmaker_lobbies_find**](docs/MatchmakerLobbiesApi.md#matchmaker_lobbies_find) | **POST** /lobbies/find | *MatchmakerLobbiesApi* | [**matchmaker_lobbies_join**](docs/MatchmakerLobbiesApi.md#matchmaker_lobbies_join) | **POST** /lobbies/join | *MatchmakerLobbiesApi* | [**matchmaker_lobbies_list**](docs/MatchmakerLobbiesApi.md#matchmaker_lobbies_list) | **GET** /lobbies/list | @@ -325,10 +326,15 @@ Class | Method | HTTP request | Description - [CloudVersionMatchmakerCaptchaTurnstileDomain](docs/CloudVersionMatchmakerCaptchaTurnstileDomain.md) - [CloudVersionMatchmakerConfig](docs/CloudVersionMatchmakerConfig.md) - [CloudVersionMatchmakerGameMode](docs/CloudVersionMatchmakerGameMode.md) + - [CloudVersionMatchmakerGameModeCreateConfig](docs/CloudVersionMatchmakerGameModeCreateConfig.md) + - [CloudVersionMatchmakerGameModeFindConfig](docs/CloudVersionMatchmakerGameModeFindConfig.md) + - [CloudVersionMatchmakerGameModeIdentityRequirement](docs/CloudVersionMatchmakerGameModeIdentityRequirement.md) - [CloudVersionMatchmakerGameModeIdleLobbiesConfig](docs/CloudVersionMatchmakerGameModeIdleLobbiesConfig.md) + - [CloudVersionMatchmakerGameModeJoinConfig](docs/CloudVersionMatchmakerGameModeJoinConfig.md) - [CloudVersionMatchmakerGameModeRegion](docs/CloudVersionMatchmakerGameModeRegion.md) - [CloudVersionMatchmakerGameModeRuntimeDocker](docs/CloudVersionMatchmakerGameModeRuntimeDocker.md) - [CloudVersionMatchmakerGameModeRuntimeDockerPort](docs/CloudVersionMatchmakerGameModeRuntimeDockerPort.md) + - [CloudVersionMatchmakerGameModeVerificationConfig](docs/CloudVersionMatchmakerGameModeVerificationConfig.md) - [CloudVersionMatchmakerLobbyGroup](docs/CloudVersionMatchmakerLobbyGroup.md) - [CloudVersionMatchmakerLobbyGroupIdleLobbiesConfig](docs/CloudVersionMatchmakerLobbyGroupIdleLobbiesConfig.md) - [CloudVersionMatchmakerLobbyGroupRegion](docs/CloudVersionMatchmakerLobbyGroupRegion.md) @@ -439,6 +445,8 @@ Class | Method | HTTP request | Description - [KvPutBatchRequest](docs/KvPutBatchRequest.md) - [KvPutEntry](docs/KvPutEntry.md) - [KvPutRequest](docs/KvPutRequest.md) + - [MatchmakerCreateLobbyResponse](docs/MatchmakerCreateLobbyResponse.md) + - [MatchmakerCustomLobbyPublicity](docs/MatchmakerCustomLobbyPublicity.md) - [MatchmakerFindLobbyResponse](docs/MatchmakerFindLobbyResponse.md) - [MatchmakerGameModeInfo](docs/MatchmakerGameModeInfo.md) - [MatchmakerGameModeStatistics](docs/MatchmakerGameModeStatistics.md) @@ -451,6 +459,7 @@ Class | Method | HTTP request | Description - [MatchmakerJoinRegion](docs/MatchmakerJoinRegion.md) - [MatchmakerListLobbiesResponse](docs/MatchmakerListLobbiesResponse.md) - [MatchmakerListRegionsResponse](docs/MatchmakerListRegionsResponse.md) + - [MatchmakerLobbiesCreateRequest](docs/MatchmakerLobbiesCreateRequest.md) - [MatchmakerLobbiesFindRequest](docs/MatchmakerLobbiesFindRequest.md) - [MatchmakerLobbiesJoinRequest](docs/MatchmakerLobbiesJoinRequest.md) - [MatchmakerLobbiesSetClosedRequest](docs/MatchmakerLobbiesSetClosedRequest.md) diff --git a/gen/openapi/internal/rust/docs/CloudGamesCreateGameBuildRequest.md b/gen/openapi/internal/rust/docs/CloudGamesCreateGameBuildRequest.md index 52a1167c8b..0e0024eb05 100644 --- a/gen/openapi/internal/rust/docs/CloudGamesCreateGameBuildRequest.md +++ b/gen/openapi/internal/rust/docs/CloudGamesCreateGameBuildRequest.md @@ -7,6 +7,7 @@ Name | Type | Description | Notes **display_name** | **String** | Represent a resource's readable display name. | **image_file** | [**crate::models::UploadPrepareFile**](UploadPrepareFile.md) | | **image_tag** | **String** | A tag given to the game build. | +**multipart_upload** | Option<**bool**> | | [optional] [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) diff --git a/gen/openapi/internal/rust/docs/CloudGamesCreateGameBuildResponse.md b/gen/openapi/internal/rust/docs/CloudGamesCreateGameBuildResponse.md index da36496605..fb3c4a586a 100644 --- a/gen/openapi/internal/rust/docs/CloudGamesCreateGameBuildResponse.md +++ b/gen/openapi/internal/rust/docs/CloudGamesCreateGameBuildResponse.md @@ -5,8 +5,8 @@ Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- **build_id** | [**uuid::Uuid**](uuid::Uuid.md) | | -**image_presigned_request** | [**crate::models::UploadPresignedRequest**](UploadPresignedRequest.md) | | -**image_presigned_requests** | [**Vec**](UploadPresignedRequest.md) | | +**image_presigned_request** | Option<[**crate::models::UploadPresignedRequest**](UploadPresignedRequest.md)> | | [optional] +**image_presigned_requests** | Option<[**Vec**](UploadPresignedRequest.md)> | | [optional] **upload_id** | [**uuid::Uuid**](uuid::Uuid.md) | | [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) diff --git a/gen/openapi/internal/rust/docs/CloudVersionMatchmakerGameMode.md b/gen/openapi/internal/rust/docs/CloudVersionMatchmakerGameMode.md index 5ae158699e..7606032f36 100644 --- a/gen/openapi/internal/rust/docs/CloudVersionMatchmakerGameMode.md +++ b/gen/openapi/internal/rust/docs/CloudVersionMatchmakerGameMode.md @@ -4,8 +4,12 @@ Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- +**create_config** | Option<[**crate::models::CloudVersionMatchmakerGameModeCreateConfig**](CloudVersionMatchmakerGameModeCreateConfig.md)> | | [optional] **docker** | Option<[**crate::models::CloudVersionMatchmakerGameModeRuntimeDocker**](CloudVersionMatchmakerGameModeRuntimeDocker.md)> | | [optional] +**find_config** | Option<[**crate::models::CloudVersionMatchmakerGameModeFindConfig**](CloudVersionMatchmakerGameModeFindConfig.md)> | | [optional] **idle_lobbies** | Option<[**crate::models::CloudVersionMatchmakerGameModeIdleLobbiesConfig**](CloudVersionMatchmakerGameModeIdleLobbiesConfig.md)> | | [optional] +**join_config** | Option<[**crate::models::CloudVersionMatchmakerGameModeJoinConfig**](CloudVersionMatchmakerGameModeJoinConfig.md)> | | [optional] +**listable** | Option<**bool**> | | [optional] **max_players** | Option<**i32**> | | [optional] **max_players_direct** | Option<**i32**> | | [optional] **max_players_party** | Option<**i32**> | | [optional] diff --git a/gen/openapi/internal/rust/docs/CloudVersionMatchmakerGameModeCreateConfig.md b/gen/openapi/internal/rust/docs/CloudVersionMatchmakerGameModeCreateConfig.md new file mode 100644 index 0000000000..de317b2632 --- /dev/null +++ b/gen/openapi/internal/rust/docs/CloudVersionMatchmakerGameModeCreateConfig.md @@ -0,0 +1,15 @@ +# CloudVersionMatchmakerGameModeCreateConfig + +## Properties + +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**enable_private** | **bool** | | +**enable_public** | **bool** | | +**identity_requirement** | [**crate::models::CloudVersionMatchmakerGameModeIdentityRequirement**](CloudVersionMatchmakerGameModeIdentityRequirement.md) | | +**max_lobbies_per_identity** | Option<**i32**> | | [optional] +**verification_config** | Option<[**crate::models::CloudVersionMatchmakerGameModeVerificationConfig**](CloudVersionMatchmakerGameModeVerificationConfig.md)> | | [optional] + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/gen/openapi/internal/rust/docs/CloudVersionMatchmakerGameModeFindConfig.md b/gen/openapi/internal/rust/docs/CloudVersionMatchmakerGameModeFindConfig.md new file mode 100644 index 0000000000..aa05da2af1 --- /dev/null +++ b/gen/openapi/internal/rust/docs/CloudVersionMatchmakerGameModeFindConfig.md @@ -0,0 +1,13 @@ +# CloudVersionMatchmakerGameModeFindConfig + +## Properties + +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**enabled** | **bool** | Sets whether or not the /find endpoint is enabled. | +**identity_requirement** | [**crate::models::CloudVersionMatchmakerGameModeIdentityRequirement**](CloudVersionMatchmakerGameModeIdentityRequirement.md) | | +**verification_config** | Option<[**crate::models::CloudVersionMatchmakerGameModeVerificationConfig**](CloudVersionMatchmakerGameModeVerificationConfig.md)> | | [optional] + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/gen/openapi/internal/rust/docs/CloudVersionMatchmakerGameModeIdentityRequirement.md b/gen/openapi/internal/rust/docs/CloudVersionMatchmakerGameModeIdentityRequirement.md new file mode 100644 index 0000000000..f8d550d34d --- /dev/null +++ b/gen/openapi/internal/rust/docs/CloudVersionMatchmakerGameModeIdentityRequirement.md @@ -0,0 +1,10 @@ +# CloudVersionMatchmakerGameModeIdentityRequirement + +## Properties + +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/gen/openapi/internal/rust/docs/CloudVersionMatchmakerGameModeJoinConfig.md b/gen/openapi/internal/rust/docs/CloudVersionMatchmakerGameModeJoinConfig.md new file mode 100644 index 0000000000..814c5de579 --- /dev/null +++ b/gen/openapi/internal/rust/docs/CloudVersionMatchmakerGameModeJoinConfig.md @@ -0,0 +1,13 @@ +# CloudVersionMatchmakerGameModeJoinConfig + +## Properties + +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**enabled** | **bool** | Sets whether or not the /join endpoint is enabled. | +**identity_requirement** | [**crate::models::CloudVersionMatchmakerGameModeIdentityRequirement**](CloudVersionMatchmakerGameModeIdentityRequirement.md) | | +**verification_config** | Option<[**crate::models::CloudVersionMatchmakerGameModeVerificationConfig**](CloudVersionMatchmakerGameModeVerificationConfig.md)> | | [optional] + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/gen/openapi/internal/rust/docs/CloudVersionMatchmakerGameModeVerificationConfig.md b/gen/openapi/internal/rust/docs/CloudVersionMatchmakerGameModeVerificationConfig.md new file mode 100644 index 0000000000..f2788127bb --- /dev/null +++ b/gen/openapi/internal/rust/docs/CloudVersionMatchmakerGameModeVerificationConfig.md @@ -0,0 +1,12 @@ +# CloudVersionMatchmakerGameModeVerificationConfig + +## Properties + +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**headers** | **::std::collections::HashMap** | | +**url** | **String** | | + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/gen/openapi/internal/rust/docs/MatchmakerCreateLobbyResponse.md b/gen/openapi/internal/rust/docs/MatchmakerCreateLobbyResponse.md new file mode 100644 index 0000000000..d00ff19503 --- /dev/null +++ b/gen/openapi/internal/rust/docs/MatchmakerCreateLobbyResponse.md @@ -0,0 +1,13 @@ +# MatchmakerCreateLobbyResponse + +## Properties + +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**lobby** | [**crate::models::MatchmakerJoinLobby**](MatchmakerJoinLobby.md) | | +**player** | [**crate::models::MatchmakerJoinPlayer**](MatchmakerJoinPlayer.md) | | +**ports** | [**::std::collections::HashMap**](MatchmakerJoinPort.md) | | + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/gen/openapi/internal/rust/docs/MatchmakerCustomLobbyPublicity.md b/gen/openapi/internal/rust/docs/MatchmakerCustomLobbyPublicity.md new file mode 100644 index 0000000000..9ef8998a74 --- /dev/null +++ b/gen/openapi/internal/rust/docs/MatchmakerCustomLobbyPublicity.md @@ -0,0 +1,10 @@ +# MatchmakerCustomLobbyPublicity + +## Properties + +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/gen/openapi/internal/rust/docs/MatchmakerLobbiesApi.md b/gen/openapi/internal/rust/docs/MatchmakerLobbiesApi.md index 7ec18651a5..2bc7719ffe 100644 --- a/gen/openapi/internal/rust/docs/MatchmakerLobbiesApi.md +++ b/gen/openapi/internal/rust/docs/MatchmakerLobbiesApi.md @@ -4,6 +4,7 @@ All URIs are relative to *http://localhost* Method | HTTP request | Description ------------- | ------------- | ------------- +[**matchmaker_lobbies_create**](MatchmakerLobbiesApi.md#matchmaker_lobbies_create) | **POST** /lobbies/create | [**matchmaker_lobbies_find**](MatchmakerLobbiesApi.md#matchmaker_lobbies_find) | **POST** /lobbies/find | [**matchmaker_lobbies_join**](MatchmakerLobbiesApi.md#matchmaker_lobbies_join) | **POST** /lobbies/join | [**matchmaker_lobbies_list**](MatchmakerLobbiesApi.md#matchmaker_lobbies_list) | **GET** /lobbies/list | @@ -12,6 +13,36 @@ Method | HTTP request | Description +## matchmaker_lobbies_create + +> crate::models::MatchmakerCreateLobbyResponse matchmaker_lobbies_create(matchmaker_lobbies_create_request) + + +Creates a custom lobby. + +### Parameters + + +Name | Type | Description | Required | Notes +------------- | ------------- | ------------- | ------------- | ------------- +**matchmaker_lobbies_create_request** | [**MatchmakerLobbiesCreateRequest**](MatchmakerLobbiesCreateRequest.md) | | [required] | + +### Return type + +[**crate::models::MatchmakerCreateLobbyResponse**](MatchmakerCreateLobbyResponse.md) + +### Authorization + +[BearerAuth](../README.md#BearerAuth) + +### HTTP request headers + +- **Content-Type**: application/json +- **Accept**: application/json + +[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) + + ## matchmaker_lobbies_find > crate::models::MatchmakerFindLobbyResponse matchmaker_lobbies_find(matchmaker_lobbies_find_request, origin) diff --git a/gen/openapi/internal/rust/docs/MatchmakerLobbiesCreateRequest.md b/gen/openapi/internal/rust/docs/MatchmakerLobbiesCreateRequest.md new file mode 100644 index 0000000000..5ba0a9904c --- /dev/null +++ b/gen/openapi/internal/rust/docs/MatchmakerLobbiesCreateRequest.md @@ -0,0 +1,16 @@ +# MatchmakerLobbiesCreateRequest + +## Properties + +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**captcha** | Option<[**crate::models::CaptchaConfig**](CaptchaConfig.md)> | | [optional] +**game_mode** | **String** | | +**lobby_config** | Option<[**serde_json::Value**](.md)> | | [optional] +**publicity** | [**crate::models::MatchmakerCustomLobbyPublicity**](MatchmakerCustomLobbyPublicity.md) | | +**region** | Option<**String**> | | [optional] +**verification_data** | Option<[**serde_json::Value**](.md)> | | [optional] + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/gen/openapi/internal/rust/docs/MatchmakerLobbiesFindRequest.md b/gen/openapi/internal/rust/docs/MatchmakerLobbiesFindRequest.md index d5a37dcce6..953ba3b105 100644 --- a/gen/openapi/internal/rust/docs/MatchmakerLobbiesFindRequest.md +++ b/gen/openapi/internal/rust/docs/MatchmakerLobbiesFindRequest.md @@ -8,6 +8,7 @@ Name | Type | Description | Notes **game_modes** | **Vec** | | **prevent_auto_create_lobby** | Option<**bool**> | | [optional] **regions** | Option<**Vec**> | | [optional] +**verification_data** | Option<[**serde_json::Value**](.md)> | | [optional] [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) diff --git a/gen/openapi/internal/rust/docs/MatchmakerLobbiesJoinRequest.md b/gen/openapi/internal/rust/docs/MatchmakerLobbiesJoinRequest.md index c0e9afd937..afffc6e3b2 100644 --- a/gen/openapi/internal/rust/docs/MatchmakerLobbiesJoinRequest.md +++ b/gen/openapi/internal/rust/docs/MatchmakerLobbiesJoinRequest.md @@ -6,6 +6,7 @@ Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- **captcha** | Option<[**crate::models::CaptchaConfig**](CaptchaConfig.md)> | | [optional] **lobby_id** | **String** | | +**verification_data** | Option<[**serde_json::Value**](.md)> | | [optional] [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) diff --git a/gen/openapi/internal/rust/src/apis/matchmaker_lobbies_api.rs b/gen/openapi/internal/rust/src/apis/matchmaker_lobbies_api.rs index f4702c54aa..a32512eac8 100644 --- a/gen/openapi/internal/rust/src/apis/matchmaker_lobbies_api.rs +++ b/gen/openapi/internal/rust/src/apis/matchmaker_lobbies_api.rs @@ -15,6 +15,19 @@ use crate::apis::ResponseContent; use super::{Error, configuration}; +/// struct for typed errors of method [`matchmaker_lobbies_create`] +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(untagged)] +pub enum MatchmakerLobbiesCreateError { + Status400(crate::models::ErrorBody), + Status403(crate::models::ErrorBody), + Status404(crate::models::ErrorBody), + Status408(crate::models::ErrorBody), + Status429(crate::models::ErrorBody), + Status500(crate::models::ErrorBody), + UnknownValue(serde_json::Value), +} + /// struct for typed errors of method [`matchmaker_lobbies_find`] #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] @@ -81,6 +94,38 @@ pub enum MatchmakerLobbiesSetClosedError { } +/// Creates a custom lobby. +pub async fn matchmaker_lobbies_create(configuration: &configuration::Configuration, matchmaker_lobbies_create_request: crate::models::MatchmakerLobbiesCreateRequest) -> Result> { + let local_var_configuration = configuration; + + let local_var_client = &local_var_configuration.client; + + let local_var_uri_str = format!("{}/lobbies/create", local_var_configuration.base_path); + let mut local_var_req_builder = local_var_client.request(reqwest::Method::POST, local_var_uri_str.as_str()); + + if let Some(ref local_var_user_agent) = local_var_configuration.user_agent { + local_var_req_builder = local_var_req_builder.header(reqwest::header::USER_AGENT, local_var_user_agent.clone()); + } + if let Some(ref local_var_token) = local_var_configuration.bearer_access_token { + local_var_req_builder = local_var_req_builder.bearer_auth(local_var_token.to_owned()); + }; + local_var_req_builder = local_var_req_builder.json(&matchmaker_lobbies_create_request); + + let local_var_req = local_var_req_builder.build()?; + let local_var_resp = local_var_client.execute(local_var_req).await?; + + let local_var_status = local_var_resp.status(); + let local_var_content = local_var_resp.text().await?; + + if !local_var_status.is_client_error() && !local_var_status.is_server_error() { + serde_json::from_str(&local_var_content).map_err(Error::from) + } else { + let local_var_entity: Option = serde_json::from_str(&local_var_content).ok(); + let local_var_error = ResponseContent { status: local_var_status, content: local_var_content, entity: local_var_entity }; + Err(Error::ResponseError(local_var_error)) + } +} + /// Finds a lobby based on the given criteria. If a lobby is not found and `prevent_auto_create_lobby` is `true`, a new lobby will be created. pub async fn matchmaker_lobbies_find(configuration: &configuration::Configuration, matchmaker_lobbies_find_request: crate::models::MatchmakerLobbiesFindRequest, origin: Option<&str>) -> Result> { let local_var_configuration = configuration; diff --git a/gen/openapi/internal/rust/src/models/cloud_games_create_game_build_request.rs b/gen/openapi/internal/rust/src/models/cloud_games_create_game_build_request.rs index 64139e9a8f..f15f843689 100644 --- a/gen/openapi/internal/rust/src/models/cloud_games_create_game_build_request.rs +++ b/gen/openapi/internal/rust/src/models/cloud_games_create_game_build_request.rs @@ -21,6 +21,8 @@ pub struct CloudGamesCreateGameBuildRequest { /// A tag given to the game build. #[serde(rename = "image_tag")] pub image_tag: String, + #[serde(rename = "multipart_upload", skip_serializing_if = "Option::is_none")] + pub multipart_upload: Option, } impl CloudGamesCreateGameBuildRequest { @@ -29,6 +31,7 @@ impl CloudGamesCreateGameBuildRequest { display_name, image_file: Box::new(image_file), image_tag, + multipart_upload: None, } } } diff --git a/gen/openapi/internal/rust/src/models/cloud_games_create_game_build_response.rs b/gen/openapi/internal/rust/src/models/cloud_games_create_game_build_response.rs index 90a2191d66..bf7ed65cca 100644 --- a/gen/openapi/internal/rust/src/models/cloud_games_create_game_build_response.rs +++ b/gen/openapi/internal/rust/src/models/cloud_games_create_game_build_response.rs @@ -15,20 +15,20 @@ pub struct CloudGamesCreateGameBuildResponse { #[serde(rename = "build_id")] pub build_id: uuid::Uuid, - #[serde(rename = "image_presigned_request")] - pub image_presigned_request: Box, - #[serde(rename = "image_presigned_requests")] - pub image_presigned_requests: Vec, + #[serde(rename = "image_presigned_request", skip_serializing_if = "Option::is_none")] + pub image_presigned_request: Option>, + #[serde(rename = "image_presigned_requests", skip_serializing_if = "Option::is_none")] + pub image_presigned_requests: Option>, #[serde(rename = "upload_id")] pub upload_id: uuid::Uuid, } impl CloudGamesCreateGameBuildResponse { - pub fn new(build_id: uuid::Uuid, image_presigned_request: crate::models::UploadPresignedRequest, image_presigned_requests: Vec, upload_id: uuid::Uuid) -> CloudGamesCreateGameBuildResponse { + pub fn new(build_id: uuid::Uuid, upload_id: uuid::Uuid) -> CloudGamesCreateGameBuildResponse { CloudGamesCreateGameBuildResponse { build_id, - image_presigned_request: Box::new(image_presigned_request), - image_presigned_requests, + image_presigned_request: None, + image_presigned_requests: None, upload_id, } } diff --git a/gen/openapi/internal/rust/src/models/cloud_version_matchmaker_game_mode.rs b/gen/openapi/internal/rust/src/models/cloud_version_matchmaker_game_mode.rs index c9a8dc599f..cc55a3dd60 100644 --- a/gen/openapi/internal/rust/src/models/cloud_version_matchmaker_game_mode.rs +++ b/gen/openapi/internal/rust/src/models/cloud_version_matchmaker_game_mode.rs @@ -14,10 +14,18 @@ #[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] pub struct CloudVersionMatchmakerGameMode { + #[serde(rename = "create_config", skip_serializing_if = "Option::is_none")] + pub create_config: Option>, #[serde(rename = "docker", skip_serializing_if = "Option::is_none")] pub docker: Option>, + #[serde(rename = "find_config", skip_serializing_if = "Option::is_none")] + pub find_config: Option>, #[serde(rename = "idle_lobbies", skip_serializing_if = "Option::is_none")] pub idle_lobbies: Option>, + #[serde(rename = "join_config", skip_serializing_if = "Option::is_none")] + pub join_config: Option>, + #[serde(rename = "listable", skip_serializing_if = "Option::is_none")] + pub listable: Option, #[serde(rename = "max_players", skip_serializing_if = "Option::is_none")] pub max_players: Option, #[serde(rename = "max_players_direct", skip_serializing_if = "Option::is_none")] @@ -34,8 +42,12 @@ impl CloudVersionMatchmakerGameMode { /// A game mode. pub fn new() -> CloudVersionMatchmakerGameMode { CloudVersionMatchmakerGameMode { + create_config: None, docker: None, + find_config: None, idle_lobbies: None, + join_config: None, + listable: None, max_players: None, max_players_direct: None, max_players_party: None, diff --git a/gen/openapi/internal/rust/src/models/cloud_version_matchmaker_game_mode_create_config.rs b/gen/openapi/internal/rust/src/models/cloud_version_matchmaker_game_mode_create_config.rs new file mode 100644 index 0000000000..638492cb81 --- /dev/null +++ b/gen/openapi/internal/rust/src/models/cloud_version_matchmaker_game_mode_create_config.rs @@ -0,0 +1,42 @@ +/* + * Rivet API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: 0.0.1 + * + * Generated by: https://openapi-generator.tech + */ + +/// CloudVersionMatchmakerGameModeCreateConfig : Configures the requirements and authentication for the /create endpoint. If this value is not set in the config, the /create endpoint is NOT enabled. + + + +#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +pub struct CloudVersionMatchmakerGameModeCreateConfig { + #[serde(rename = "enable_private")] + pub enable_private: bool, + #[serde(rename = "enable_public")] + pub enable_public: bool, + #[serde(rename = "identity_requirement")] + pub identity_requirement: crate::models::CloudVersionMatchmakerGameModeIdentityRequirement, + #[serde(rename = "max_lobbies_per_identity", skip_serializing_if = "Option::is_none")] + pub max_lobbies_per_identity: Option, + #[serde(rename = "verification_config", skip_serializing_if = "Option::is_none")] + pub verification_config: Option>, +} + +impl CloudVersionMatchmakerGameModeCreateConfig { + /// Configures the requirements and authentication for the /create endpoint. If this value is not set in the config, the /create endpoint is NOT enabled. + pub fn new(enable_private: bool, enable_public: bool, identity_requirement: crate::models::CloudVersionMatchmakerGameModeIdentityRequirement) -> CloudVersionMatchmakerGameModeCreateConfig { + CloudVersionMatchmakerGameModeCreateConfig { + enable_private, + enable_public, + identity_requirement, + max_lobbies_per_identity: None, + verification_config: None, + } + } +} + + diff --git a/gen/openapi/internal/rust/src/models/cloud_version_matchmaker_game_mode_find_config.rs b/gen/openapi/internal/rust/src/models/cloud_version_matchmaker_game_mode_find_config.rs new file mode 100644 index 0000000000..697d176954 --- /dev/null +++ b/gen/openapi/internal/rust/src/models/cloud_version_matchmaker_game_mode_find_config.rs @@ -0,0 +1,37 @@ +/* + * Rivet API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: 0.0.1 + * + * Generated by: https://openapi-generator.tech + */ + +/// CloudVersionMatchmakerGameModeFindConfig : Configures the requirements and authentication for the /find endpoint. If this value is not set in the config, the /find endpoint is still enabled. + + + +#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +pub struct CloudVersionMatchmakerGameModeFindConfig { + /// Sets whether or not the /find endpoint is enabled. + #[serde(rename = "enabled")] + pub enabled: bool, + #[serde(rename = "identity_requirement")] + pub identity_requirement: crate::models::CloudVersionMatchmakerGameModeIdentityRequirement, + #[serde(rename = "verification_config", skip_serializing_if = "Option::is_none")] + pub verification_config: Option>, +} + +impl CloudVersionMatchmakerGameModeFindConfig { + /// Configures the requirements and authentication for the /find endpoint. If this value is not set in the config, the /find endpoint is still enabled. + pub fn new(enabled: bool, identity_requirement: crate::models::CloudVersionMatchmakerGameModeIdentityRequirement) -> CloudVersionMatchmakerGameModeFindConfig { + CloudVersionMatchmakerGameModeFindConfig { + enabled, + identity_requirement, + verification_config: None, + } + } +} + + diff --git a/gen/openapi/internal/rust/src/models/cloud_version_matchmaker_game_mode_identity_requirement.rs b/gen/openapi/internal/rust/src/models/cloud_version_matchmaker_game_mode_identity_requirement.rs new file mode 100644 index 0000000000..b7b86f843b --- /dev/null +++ b/gen/openapi/internal/rust/src/models/cloud_version_matchmaker_game_mode_identity_requirement.rs @@ -0,0 +1,43 @@ +/* + * Rivet API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: 0.0.1 + * + * Generated by: https://openapi-generator.tech + */ + +/// CloudVersionMatchmakerGameModeIdentityRequirement : The registration requirement for a user when joining/finding/creating a lobby. \"None\" allows for connections without an identity. + +/// The registration requirement for a user when joining/finding/creating a lobby. \"None\" allows for connections without an identity. +#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)] +pub enum CloudVersionMatchmakerGameModeIdentityRequirement { + #[serde(rename = "none")] + None, + #[serde(rename = "guest")] + Guest, + #[serde(rename = "registered")] + Registered, + +} + +impl ToString for CloudVersionMatchmakerGameModeIdentityRequirement { + fn to_string(&self) -> String { + match self { + Self::None => String::from("none"), + Self::Guest => String::from("guest"), + Self::Registered => String::from("registered"), + } + } +} + +impl Default for CloudVersionMatchmakerGameModeIdentityRequirement { + fn default() -> CloudVersionMatchmakerGameModeIdentityRequirement { + Self::None + } +} + + + + diff --git a/gen/openapi/internal/rust/src/models/cloud_version_matchmaker_game_mode_join_config.rs b/gen/openapi/internal/rust/src/models/cloud_version_matchmaker_game_mode_join_config.rs new file mode 100644 index 0000000000..afd3b65d8e --- /dev/null +++ b/gen/openapi/internal/rust/src/models/cloud_version_matchmaker_game_mode_join_config.rs @@ -0,0 +1,37 @@ +/* + * Rivet API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: 0.0.1 + * + * Generated by: https://openapi-generator.tech + */ + +/// CloudVersionMatchmakerGameModeJoinConfig : Configures the requirements and authentication for the /join endpoint. If this value is not set in the config, the /join endpoint is still enabled. + + + +#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +pub struct CloudVersionMatchmakerGameModeJoinConfig { + /// Sets whether or not the /join endpoint is enabled. + #[serde(rename = "enabled")] + pub enabled: bool, + #[serde(rename = "identity_requirement")] + pub identity_requirement: crate::models::CloudVersionMatchmakerGameModeIdentityRequirement, + #[serde(rename = "verification_config", skip_serializing_if = "Option::is_none")] + pub verification_config: Option>, +} + +impl CloudVersionMatchmakerGameModeJoinConfig { + /// Configures the requirements and authentication for the /join endpoint. If this value is not set in the config, the /join endpoint is still enabled. + pub fn new(enabled: bool, identity_requirement: crate::models::CloudVersionMatchmakerGameModeIdentityRequirement) -> CloudVersionMatchmakerGameModeJoinConfig { + CloudVersionMatchmakerGameModeJoinConfig { + enabled, + identity_requirement, + verification_config: None, + } + } +} + + diff --git a/gen/openapi/internal/rust/src/models/cloud_version_matchmaker_game_mode_verification_config.rs b/gen/openapi/internal/rust/src/models/cloud_version_matchmaker_game_mode_verification_config.rs new file mode 100644 index 0000000000..306ca5d409 --- /dev/null +++ b/gen/openapi/internal/rust/src/models/cloud_version_matchmaker_game_mode_verification_config.rs @@ -0,0 +1,33 @@ +/* + * Rivet API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: 0.0.1 + * + * Generated by: https://openapi-generator.tech + */ + +/// CloudVersionMatchmakerGameModeVerificationConfig : Configuration that tells Rivet where to send validation requests and with what headers. When set, Rivet will send the `verification_data` property (given by the user in the find/join/create endpoint) to the given url along with the headers provided and some information about the requested lobby. The response of this request will determine if the user can join that lobby or not. + + + +#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +pub struct CloudVersionMatchmakerGameModeVerificationConfig { + #[serde(rename = "headers")] + pub headers: ::std::collections::HashMap, + #[serde(rename = "url")] + pub url: String, +} + +impl CloudVersionMatchmakerGameModeVerificationConfig { + /// Configuration that tells Rivet where to send validation requests and with what headers. When set, Rivet will send the `verification_data` property (given by the user in the find/join/create endpoint) to the given url along with the headers provided and some information about the requested lobby. The response of this request will determine if the user can join that lobby or not. + pub fn new(headers: ::std::collections::HashMap, url: String) -> CloudVersionMatchmakerGameModeVerificationConfig { + CloudVersionMatchmakerGameModeVerificationConfig { + headers, + url, + } + } +} + + diff --git a/gen/openapi/internal/rust/src/models/matchmaker_create_lobby_response.rs b/gen/openapi/internal/rust/src/models/matchmaker_create_lobby_response.rs new file mode 100644 index 0000000000..0d1bcc029a --- /dev/null +++ b/gen/openapi/internal/rust/src/models/matchmaker_create_lobby_response.rs @@ -0,0 +1,34 @@ +/* + * Rivet API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: 0.0.1 + * + * Generated by: https://openapi-generator.tech + */ + + + + +#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +pub struct MatchmakerCreateLobbyResponse { + #[serde(rename = "lobby")] + pub lobby: Box, + #[serde(rename = "player")] + pub player: Box, + #[serde(rename = "ports")] + pub ports: ::std::collections::HashMap, +} + +impl MatchmakerCreateLobbyResponse { + pub fn new(lobby: crate::models::MatchmakerJoinLobby, player: crate::models::MatchmakerJoinPlayer, ports: ::std::collections::HashMap) -> MatchmakerCreateLobbyResponse { + MatchmakerCreateLobbyResponse { + lobby: Box::new(lobby), + player: Box::new(player), + ports, + } + } +} + + diff --git a/gen/openapi/internal/rust/src/models/matchmaker_custom_lobby_publicity.rs b/gen/openapi/internal/rust/src/models/matchmaker_custom_lobby_publicity.rs new file mode 100644 index 0000000000..e3dcead796 --- /dev/null +++ b/gen/openapi/internal/rust/src/models/matchmaker_custom_lobby_publicity.rs @@ -0,0 +1,39 @@ +/* + * Rivet API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: 0.0.1 + * + * Generated by: https://openapi-generator.tech + */ + + +/// +#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)] +pub enum MatchmakerCustomLobbyPublicity { + #[serde(rename = "public")] + Public, + #[serde(rename = "private")] + Private, + +} + +impl ToString for MatchmakerCustomLobbyPublicity { + fn to_string(&self) -> String { + match self { + Self::Public => String::from("public"), + Self::Private => String::from("private"), + } + } +} + +impl Default for MatchmakerCustomLobbyPublicity { + fn default() -> MatchmakerCustomLobbyPublicity { + Self::Public + } +} + + + + diff --git a/gen/openapi/internal/rust/src/models/matchmaker_lobbies_create_request.rs b/gen/openapi/internal/rust/src/models/matchmaker_lobbies_create_request.rs new file mode 100644 index 0000000000..85b37c69f2 --- /dev/null +++ b/gen/openapi/internal/rust/src/models/matchmaker_lobbies_create_request.rs @@ -0,0 +1,43 @@ +/* + * Rivet API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: 0.0.1 + * + * Generated by: https://openapi-generator.tech + */ + + + + +#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +pub struct MatchmakerLobbiesCreateRequest { + #[serde(rename = "captcha", skip_serializing_if = "Option::is_none")] + pub captcha: Option>, + #[serde(rename = "game_mode")] + pub game_mode: String, + #[serde(rename = "lobby_config", default, with = "::serde_with::rust::double_option", skip_serializing_if = "Option::is_none")] + pub lobby_config: Option>, + #[serde(rename = "publicity")] + pub publicity: crate::models::MatchmakerCustomLobbyPublicity, + #[serde(rename = "region", skip_serializing_if = "Option::is_none")] + pub region: Option, + #[serde(rename = "verification_data", default, with = "::serde_with::rust::double_option", skip_serializing_if = "Option::is_none")] + pub verification_data: Option>, +} + +impl MatchmakerLobbiesCreateRequest { + pub fn new(game_mode: String, publicity: crate::models::MatchmakerCustomLobbyPublicity) -> MatchmakerLobbiesCreateRequest { + MatchmakerLobbiesCreateRequest { + captcha: None, + game_mode, + lobby_config: None, + publicity, + region: None, + verification_data: None, + } + } +} + + diff --git a/gen/openapi/internal/rust/src/models/matchmaker_lobbies_find_request.rs b/gen/openapi/internal/rust/src/models/matchmaker_lobbies_find_request.rs index a218d9dba6..9244d5373c 100644 --- a/gen/openapi/internal/rust/src/models/matchmaker_lobbies_find_request.rs +++ b/gen/openapi/internal/rust/src/models/matchmaker_lobbies_find_request.rs @@ -21,6 +21,8 @@ pub struct MatchmakerLobbiesFindRequest { pub prevent_auto_create_lobby: Option, #[serde(rename = "regions", skip_serializing_if = "Option::is_none")] pub regions: Option>, + #[serde(rename = "verification_data", default, with = "::serde_with::rust::double_option", skip_serializing_if = "Option::is_none")] + pub verification_data: Option>, } impl MatchmakerLobbiesFindRequest { @@ -30,6 +32,7 @@ impl MatchmakerLobbiesFindRequest { game_modes, prevent_auto_create_lobby: None, regions: None, + verification_data: None, } } } diff --git a/gen/openapi/internal/rust/src/models/matchmaker_lobbies_join_request.rs b/gen/openapi/internal/rust/src/models/matchmaker_lobbies_join_request.rs index 9b9683c869..6f622e00a1 100644 --- a/gen/openapi/internal/rust/src/models/matchmaker_lobbies_join_request.rs +++ b/gen/openapi/internal/rust/src/models/matchmaker_lobbies_join_request.rs @@ -17,6 +17,8 @@ pub struct MatchmakerLobbiesJoinRequest { pub captcha: Option>, #[serde(rename = "lobby_id")] pub lobby_id: String, + #[serde(rename = "verification_data", default, with = "::serde_with::rust::double_option", skip_serializing_if = "Option::is_none")] + pub verification_data: Option>, } impl MatchmakerLobbiesJoinRequest { @@ -24,6 +26,7 @@ impl MatchmakerLobbiesJoinRequest { MatchmakerLobbiesJoinRequest { captcha: None, lobby_id, + verification_data: None, } } } diff --git a/gen/openapi/internal/rust/src/models/mod.rs b/gen/openapi/internal/rust/src/models/mod.rs index c0cdeff2e5..99cae4fb9b 100644 --- a/gen/openapi/internal/rust/src/models/mod.rs +++ b/gen/openapi/internal/rust/src/models/mod.rs @@ -318,14 +318,24 @@ pub mod cloud_version_matchmaker_config; pub use self::cloud_version_matchmaker_config::CloudVersionMatchmakerConfig; pub mod cloud_version_matchmaker_game_mode; pub use self::cloud_version_matchmaker_game_mode::CloudVersionMatchmakerGameMode; +pub mod cloud_version_matchmaker_game_mode_create_config; +pub use self::cloud_version_matchmaker_game_mode_create_config::CloudVersionMatchmakerGameModeCreateConfig; +pub mod cloud_version_matchmaker_game_mode_find_config; +pub use self::cloud_version_matchmaker_game_mode_find_config::CloudVersionMatchmakerGameModeFindConfig; +pub mod cloud_version_matchmaker_game_mode_identity_requirement; +pub use self::cloud_version_matchmaker_game_mode_identity_requirement::CloudVersionMatchmakerGameModeIdentityRequirement; pub mod cloud_version_matchmaker_game_mode_idle_lobbies_config; pub use self::cloud_version_matchmaker_game_mode_idle_lobbies_config::CloudVersionMatchmakerGameModeIdleLobbiesConfig; +pub mod cloud_version_matchmaker_game_mode_join_config; +pub use self::cloud_version_matchmaker_game_mode_join_config::CloudVersionMatchmakerGameModeJoinConfig; pub mod cloud_version_matchmaker_game_mode_region; pub use self::cloud_version_matchmaker_game_mode_region::CloudVersionMatchmakerGameModeRegion; pub mod cloud_version_matchmaker_game_mode_runtime_docker; pub use self::cloud_version_matchmaker_game_mode_runtime_docker::CloudVersionMatchmakerGameModeRuntimeDocker; pub mod cloud_version_matchmaker_game_mode_runtime_docker_port; pub use self::cloud_version_matchmaker_game_mode_runtime_docker_port::CloudVersionMatchmakerGameModeRuntimeDockerPort; +pub mod cloud_version_matchmaker_game_mode_verification_config; +pub use self::cloud_version_matchmaker_game_mode_verification_config::CloudVersionMatchmakerGameModeVerificationConfig; pub mod cloud_version_matchmaker_lobby_group; pub use self::cloud_version_matchmaker_lobby_group::CloudVersionMatchmakerLobbyGroup; pub mod cloud_version_matchmaker_lobby_group_idle_lobbies_config; @@ -546,6 +556,10 @@ pub mod kv_put_entry; pub use self::kv_put_entry::KvPutEntry; pub mod kv_put_request; pub use self::kv_put_request::KvPutRequest; +pub mod matchmaker_create_lobby_response; +pub use self::matchmaker_create_lobby_response::MatchmakerCreateLobbyResponse; +pub mod matchmaker_custom_lobby_publicity; +pub use self::matchmaker_custom_lobby_publicity::MatchmakerCustomLobbyPublicity; pub mod matchmaker_find_lobby_response; pub use self::matchmaker_find_lobby_response::MatchmakerFindLobbyResponse; pub mod matchmaker_game_mode_info; @@ -570,6 +584,8 @@ pub mod matchmaker_list_lobbies_response; pub use self::matchmaker_list_lobbies_response::MatchmakerListLobbiesResponse; pub mod matchmaker_list_regions_response; pub use self::matchmaker_list_regions_response::MatchmakerListRegionsResponse; +pub mod matchmaker_lobbies_create_request; +pub use self::matchmaker_lobbies_create_request::MatchmakerLobbiesCreateRequest; pub mod matchmaker_lobbies_find_request; pub use self::matchmaker_lobbies_find_request::MatchmakerLobbiesFindRequest; pub mod matchmaker_lobbies_join_request; diff --git a/gen/openapi/internal/spec/openapi.yml b/gen/openapi/internal/spec/openapi.yml index 29beeb0a78..2d3f644c12 100644 --- a/gen/openapi/internal/spec/openapi.yml +++ b/gen/openapi/internal/spec/openapi.yml @@ -8068,6 +8068,7 @@ paths: type: boolean captcha: $ref: '#/components/schemas/CaptchaConfig' + verification_data: {} required: - game_modes /lobbies/join: @@ -8137,8 +8138,83 @@ paths: type: string captcha: $ref: '#/components/schemas/CaptchaConfig' + verification_data: {} required: - lobby_id + /lobbies/create: + post: + description: | + Creates a custom lobby. + operationId: matchmaker_lobbies_create + tags: + - MatchmakerLobbies + parameters: [] + responses: + '200': + description: '' + content: + application/json: + schema: + $ref: '#/components/schemas/MatchmakerCreateLobbyResponse' + '400': + description: '' + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorBody' + '403': + description: '' + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorBody' + '404': + description: '' + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorBody' + '408': + description: '' + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorBody' + '429': + description: '' + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorBody' + '500': + description: '' + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorBody' + servers: + - url: https://matchmaker.api.rivet.gg/v1 + security: *ref_0 + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + game_mode: + type: string + region: + type: string + captcha: + $ref: '#/components/schemas/CaptchaConfig' + publicity: + $ref: '#/components/schemas/MatchmakerCustomLobbyPublicity' + lobby_config: {} + verification_data: {} + required: + - game_mode + - publicity /lobbies/list: get: description: Lists all open lobbies. @@ -10927,6 +11003,8 @@ components: description: A tag given to the game build. image_file: $ref: '#/components/schemas/UploadPrepareFile' + multipart_upload: + type: boolean required: - display_name - image_tag @@ -10942,7 +11020,6 @@ components: format: uuid image_presigned_request: $ref: '#/components/schemas/UploadPresignedRequest' - description: '**Deprecated: use image_presigned_requests instead**' image_presigned_requests: type: array items: @@ -10950,8 +11027,6 @@ components: required: - build_id - upload_id - - image_presigned_request - - image_presigned_requests CloudGamesListGameCdnSitesResponse: type: object properties: @@ -11549,6 +11624,14 @@ components: type: integer docker: $ref: '#/components/schemas/CloudVersionMatchmakerGameModeRuntimeDocker' + listable: + type: boolean + find_config: + $ref: '#/components/schemas/CloudVersionMatchmakerGameModeFindConfig' + join_config: + $ref: '#/components/schemas/CloudVersionMatchmakerGameModeJoinConfig' + create_config: + $ref: '#/components/schemas/CloudVersionMatchmakerGameModeCreateConfig' tier: type: string idle_lobbies: @@ -11623,6 +11706,95 @@ components: required: - min - max + CloudVersionMatchmakerGameModeIdentityRequirement: + type: string + enum: + - none + - guest + - registered + description: >- + The registration requirement for a user when joining/finding/creating a + lobby. "None" allows for connections without an identity. + CloudVersionMatchmakerGameModeVerificationConfig: + type: object + description: >- + Configuration that tells Rivet where to send validation requests and + with what headers. When set, Rivet will send the `verification_data` + property (given by the user in the find/join/create endpoint) to the + given url along with the headers provided and some information about the + requested lobby. The response of this request will determine if the user + can join that lobby or not. + properties: + url: + type: string + headers: + type: object + additionalProperties: + type: string + required: + - url + - headers + CloudVersionMatchmakerGameModeFindConfig: + type: object + description: >- + Configures the requirements and authentication for the /find endpoint. + If this value is not set in the config, the /find endpoint is still + enabled. + properties: + enabled: + type: boolean + description: Sets whether or not the /find endpoint is enabled. + identity_requirement: + $ref: >- + #/components/schemas/CloudVersionMatchmakerGameModeIdentityRequirement + verification_config: + $ref: >- + #/components/schemas/CloudVersionMatchmakerGameModeVerificationConfig + required: + - enabled + - identity_requirement + CloudVersionMatchmakerGameModeJoinConfig: + type: object + description: >- + Configures the requirements and authentication for the /join endpoint. + If this value is not set in the config, the /join endpoint is still + enabled. + properties: + enabled: + type: boolean + description: Sets whether or not the /join endpoint is enabled. + identity_requirement: + $ref: >- + #/components/schemas/CloudVersionMatchmakerGameModeIdentityRequirement + verification_config: + $ref: >- + #/components/schemas/CloudVersionMatchmakerGameModeVerificationConfig + required: + - enabled + - identity_requirement + CloudVersionMatchmakerGameModeCreateConfig: + type: object + description: >- + Configures the requirements and authentication for the /create endpoint. + If this value is not set in the config, the /create endpoint is NOT + enabled. + properties: + identity_requirement: + $ref: >- + #/components/schemas/CloudVersionMatchmakerGameModeIdentityRequirement + verification_config: + $ref: >- + #/components/schemas/CloudVersionMatchmakerGameModeVerificationConfig + enable_public: + type: boolean + enable_private: + type: boolean + max_lobbies_per_identity: + type: integer + required: + - identity_requirement + - enable_public + - enable_private CloudVersionMatchmakerLobbyGroup: type: object description: A game mode. @@ -13014,6 +13186,11 @@ components: server will validate this token with `PlayerConnected.player_token` required: - token + MatchmakerCustomLobbyPublicity: + type: string + enum: + - public + - private MatchmakerFindLobbyResponse: type: object properties: @@ -13044,6 +13221,21 @@ components: - lobby - ports - player + MatchmakerCreateLobbyResponse: + type: object + properties: + lobby: + $ref: '#/components/schemas/MatchmakerJoinLobby' + ports: + type: object + additionalProperties: + $ref: '#/components/schemas/MatchmakerJoinPort' + player: + $ref: '#/components/schemas/MatchmakerJoinPlayer' + required: + - lobby + - ports + - player MatchmakerListLobbiesResponse: type: object properties: diff --git a/gen/openapi/internal/spec_compat/openapi.yml b/gen/openapi/internal/spec_compat/openapi.yml index 9684cdaffa..db7580580d 100644 --- a/gen/openapi/internal/spec_compat/openapi.yml +++ b/gen/openapi/internal/spec_compat/openapi.yml @@ -756,6 +756,8 @@ components: image_tag: description: A tag given to the game build. type: string + multipart_upload: + type: boolean required: - display_name - image_tag @@ -768,7 +770,6 @@ components: type: string image_presigned_request: $ref: '#/components/schemas/UploadPresignedRequest' - description: '**Deprecated: use image_presigned_requests instead**' image_presigned_requests: items: $ref: '#/components/schemas/UploadPresignedRequest' @@ -779,8 +780,6 @@ components: required: - build_id - upload_id - - image_presigned_request - - image_presigned_requests type: object CloudGamesCreateGameCdnSiteRequest: properties: @@ -2357,10 +2356,18 @@ components: CloudVersionMatchmakerGameMode: description: A game mode. properties: + create_config: + $ref: '#/components/schemas/CloudVersionMatchmakerGameModeCreateConfig' docker: $ref: '#/components/schemas/CloudVersionMatchmakerGameModeRuntimeDocker' + find_config: + $ref: '#/components/schemas/CloudVersionMatchmakerGameModeFindConfig' idle_lobbies: $ref: '#/components/schemas/CloudVersionMatchmakerGameModeIdleLobbiesConfig' + join_config: + $ref: '#/components/schemas/CloudVersionMatchmakerGameModeJoinConfig' + listable: + type: boolean max_players: type: integer max_players_direct: @@ -2374,6 +2381,49 @@ components: tier: type: string type: object + CloudVersionMatchmakerGameModeCreateConfig: + description: Configures the requirements and authentication for the /create + endpoint. If this value is not set in the config, the /create endpoint is + NOT enabled. + properties: + enable_private: + type: boolean + enable_public: + type: boolean + identity_requirement: + $ref: '#/components/schemas/CloudVersionMatchmakerGameModeIdentityRequirement' + max_lobbies_per_identity: + type: integer + verification_config: + $ref: '#/components/schemas/CloudVersionMatchmakerGameModeVerificationConfig' + required: + - identity_requirement + - enable_public + - enable_private + type: object + CloudVersionMatchmakerGameModeFindConfig: + description: Configures the requirements and authentication for the /find endpoint. + If this value is not set in the config, the /find endpoint is still enabled. + properties: + enabled: + description: Sets whether or not the /find endpoint is enabled. + type: boolean + identity_requirement: + $ref: '#/components/schemas/CloudVersionMatchmakerGameModeIdentityRequirement' + verification_config: + $ref: '#/components/schemas/CloudVersionMatchmakerGameModeVerificationConfig' + required: + - enabled + - identity_requirement + type: object + CloudVersionMatchmakerGameModeIdentityRequirement: + description: The registration requirement for a user when joining/finding/creating + a lobby. "None" allows for connections without an identity. + enum: + - none + - guest + - registered + type: string CloudVersionMatchmakerGameModeIdleLobbiesConfig: description: Configuration for how many idle lobbies a game version should have. properties: @@ -2385,6 +2435,21 @@ components: - min - max type: object + CloudVersionMatchmakerGameModeJoinConfig: + description: Configures the requirements and authentication for the /join endpoint. + If this value is not set in the config, the /join endpoint is still enabled. + properties: + enabled: + description: Sets whether or not the /join endpoint is enabled. + type: boolean + identity_requirement: + $ref: '#/components/schemas/CloudVersionMatchmakerGameModeIdentityRequirement' + verification_config: + $ref: '#/components/schemas/CloudVersionMatchmakerGameModeVerificationConfig' + required: + - enabled + - identity_requirement + type: object CloudVersionMatchmakerGameModeRegion: description: A game mode region. properties: @@ -2443,6 +2508,24 @@ components: $ref: '#/components/schemas/CloudVersionMatchmakerProxyKind' description: How this port should be proxied. Defaults to 'game-guard`. type: object + CloudVersionMatchmakerGameModeVerificationConfig: + description: Configuration that tells Rivet where to send validation requests + and with what headers. When set, Rivet will send the `verification_data` property + (given by the user in the find/join/create endpoint) to the given url along + with the headers provided and some information about the requested lobby. + The response of this request will determine if the user can join that lobby + or not. + properties: + headers: + additionalProperties: + type: string + type: object + url: + type: string + required: + - url + - headers + type: object CloudVersionMatchmakerLobbyGroup: description: A game mode. properties: @@ -4078,6 +4161,26 @@ components: A `null` value indicates the entry is deleted. Maximum length of 262,144 bytes when encoded.' + MatchmakerCreateLobbyResponse: + properties: + lobby: + $ref: '#/components/schemas/MatchmakerJoinLobby' + player: + $ref: '#/components/schemas/MatchmakerJoinPlayer' + ports: + additionalProperties: + $ref: '#/components/schemas/MatchmakerJoinPort' + type: object + required: + - lobby + - ports + - player + type: object + MatchmakerCustomLobbyPublicity: + enum: + - public + - private + type: string MatchmakerFindLobbyResponse: properties: lobby: @@ -11636,6 +11739,81 @@ paths: - url: https://matchmaker.api.rivet.gg/v1 tags: - MatchmakerLobbies + /lobbies/create: + post: + description: 'Creates a custom lobby. + + ' + operationId: matchmaker_lobbies_create + parameters: [] + requestBody: + content: + application/json: + schema: + properties: + captcha: + $ref: '#/components/schemas/CaptchaConfig' + game_mode: + type: string + lobby_config: {} + publicity: + $ref: '#/components/schemas/MatchmakerCustomLobbyPublicity' + region: + type: string + verification_data: {} + required: + - game_mode + - publicity + type: object + required: true + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/MatchmakerCreateLobbyResponse' + description: '' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorBody' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorBody' + description: '' + '404': + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorBody' + description: '' + '408': + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorBody' + description: '' + '429': + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorBody' + description: '' + '500': + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorBody' + description: '' + security: *id001 + servers: + - url: https://matchmaker.api.rivet.gg/v1 + tags: + - MatchmakerLobbies /lobbies/find: post: description: "Finds a lobby based on the given criteria.\nIf a lobby is not\ @@ -11664,6 +11842,7 @@ paths: items: type: string type: array + verification_data: {} required: - game_modes type: object @@ -11736,6 +11915,7 @@ paths: $ref: '#/components/schemas/CaptchaConfig' lobby_id: type: string + verification_data: {} required: - lobby_id type: object diff --git a/infra/salt/pillar/top.sls b/infra/salt/pillar/top.sls index 9256acf146..d5402cf934 100644 --- a/infra/salt/pillar/top.sls +++ b/infra/salt/pillar/top.sls @@ -18,6 +18,6 @@ base: - clickhouse 'G@roles:minio': - minio - 'G@roles:traefik-cloudflare-proxy': + 'G@roles:cloudflare-proxy': - cloudflare diff --git a/infra/salt/salt/clickhouse/files/clickhouse-server.service b/infra/salt/salt/clickhouse/files/clickhouse-server.service index 62aa5d00aa..4999f0ddb3 100644 --- a/infra/salt/salt/clickhouse/files/clickhouse-server.service +++ b/infra/salt/salt/clickhouse/files/clickhouse-server.service @@ -21,7 +21,7 @@ ExecStart=/var/rivet-nix/result/clickhouse/bin/clickhouse server --config=/etc/c LimitCORE=infinity LimitNOFILE=500000 CapabilityBoundingSet=CAP_NET_ADMIN CAP_IPC_LOCK CAP_SYS_NICE CAP_NET_BIND_SERVICE -{% if pillar['rivet']['deploy']['local']['restrict_service_resources'] %} +{% if 'local' in pillar.rivet.deploy and pillar.rivet.deploy.local.restrict_service_resources %} Nice=10 CPUAffinity=0 {% endif %} diff --git a/infra/salt/salt/clickhouse/init.sls b/infra/salt/salt/clickhouse/init.sls index c23ffdcec3..ab3af39001 100644 --- a/infra/salt/salt/clickhouse/init.sls +++ b/infra/salt/salt/clickhouse/init.sls @@ -1,3 +1,23 @@ +{% if grains['volumes']['ch']['mount'] %} +{% set device = '/dev/disk/by-id/scsi-0Linode_Volume_' ~ grains['rivet']['name'] ~ '-ch' %} + +disk_create_clickhouse: + blockdev.formatted: + - name: {{ device }} + - fs_type: ext4 + +disk_mount_clickhouse: + file.directory: + - name: /var/lib/clickhouse + - makedirs: True + mount.mounted: + - name: /var/lib/clickhouse + - device: {{ device }} + - fstype: ext4 + - require: + - blockdev: disk_create_clickhouse +{% endif %} + create_clickhouse_user: user.present: - name: clickhouse @@ -26,24 +46,16 @@ mkdir_clickhouse: - mode: 700 - require: - user: create_clickhouse_user + {%- if grains['volumes']['ch']['mount'] %} + - mount: disk_mount_clickhouse + {%- endif %} -{% if grains['volumes']['ch']['mount'] %} -{% set device = '/dev/disk/by-id/scsi-0Linode_Volume_' ~ grains['rivet']['name'] ~ '-ch' %} - -disk_create_clickhouse: - blockdev.formatted: - - name: {{ device }} - - fs_type: ext4 - -disk_mount_clickhouse: - mount.mounted: - - name: /var/lib/clickhouse - - device: {{ device }} - - fstype: ext4 - - require: - - blockdev: disk_create_clickhouse - - file: mkdir_clickhouse -{% endif %} +# Remove old config directories with residual files +remove_etc_clickhouse_server_dirs: + file.absent: + - names: + - /etc/clickhouse-server/config.d + - /etc/clickhouse-server/users.d push_etc_clickhouse_server: file.managed: diff --git a/infra/salt/salt/traefik_cloudflare_proxy/files/traefik_cloudflare_proxy.service b/infra/salt/salt/cloudflare_proxy/files/cloudflare-proxy.service similarity index 73% rename from infra/salt/salt/traefik_cloudflare_proxy/files/traefik_cloudflare_proxy.service rename to infra/salt/salt/cloudflare_proxy/files/cloudflare-proxy.service index 4109a13f9a..0947b52340 100644 --- a/infra/salt/salt/traefik_cloudflare_proxy/files/traefik_cloudflare_proxy.service +++ b/infra/salt/salt/cloudflare_proxy/files/cloudflare-proxy.service @@ -4,9 +4,9 @@ After=network-online.target Wants=network-online.target systemd-networkd-wait-online.service [Service] -User=traefik_cloudflare_proxy -Group=traefik_cloudflare_proxy -ExecStart=/usr/bin/traefik --configFile=/etc/traefik_cloudflare_proxy/traefik.toml +User=cloudflare_proxy +Group=cloudflare_proxy +ExecStart=/usr/bin/traefik --configFile=/etc/cloudflare_proxy/traefik.toml PrivateTmp=true PrivateDevices=false ProtectHome=true diff --git a/infra/salt/salt/cloudflare_proxy/files/consul/cloudflare-proxy.hcl b/infra/salt/salt/cloudflare_proxy/files/consul/cloudflare-proxy.hcl new file mode 100644 index 0000000000..b562dd36ce --- /dev/null +++ b/infra/salt/salt/cloudflare_proxy/files/consul/cloudflare-proxy.hcl @@ -0,0 +1,15 @@ +services { + name = "cloudflare-proxy" + tags = ["traefik"] + + port = 9060 + checks = [ + { + name = "Reachable on 9060" + tcp = "127.0.0.1:9060" + interval = "10s" + timeout = "1s" + } + ] +} + diff --git a/infra/salt/salt/traefik_cloudflare_proxy/files/dynamic/common.toml.j2 b/infra/salt/salt/cloudflare_proxy/files/dynamic/common.toml.j2 similarity index 100% rename from infra/salt/salt/traefik_cloudflare_proxy/files/dynamic/common.toml.j2 rename to infra/salt/salt/cloudflare_proxy/files/dynamic/common.toml.j2 diff --git a/infra/salt/salt/traefik_cloudflare_proxy/files/traefik.toml.j2 b/infra/salt/salt/cloudflare_proxy/files/traefik.toml.j2 similarity index 63% rename from infra/salt/salt/traefik_cloudflare_proxy/files/traefik.toml.j2 rename to infra/salt/salt/cloudflare_proxy/files/traefik.toml.j2 index dfb3c3dba4..c6194f5cc7 100644 --- a/infra/salt/salt/traefik_cloudflare_proxy/files/traefik.toml.j2 +++ b/infra/salt/salt/cloudflare_proxy/files/traefik.toml.j2 @@ -4,4 +4,4 @@ [providers] [providers.file] - directory = "/etc/traefik_cloudflare_proxy/dynamic" + directory = "/etc/cloudflare_proxy/dynamic" diff --git a/infra/salt/salt/cloudflare_proxy/init.sls b/infra/salt/salt/cloudflare_proxy/init.sls new file mode 100644 index 0000000000..ffcf9456e2 --- /dev/null +++ b/infra/salt/salt/cloudflare_proxy/init.sls @@ -0,0 +1,72 @@ +create_cloudflare_proxy_user: + user.present: + - name: cloudflare_proxy + - shell: /bin/false + - system: True + - usergroup: True + +create_etc_cloudflare_proxy: + file.directory: + - names: + - /etc/cloudflare_proxy/: {} + - /etc/cloudflare_proxy/dynamic/: {} + - user: cloudflare_proxy + - group: cloudflare_proxy + - mode: 550 + - require: + - user: create_cloudflare_proxy_user + +push_etc_cloudflare_proxy: + file.managed: + - names: + # Static config + - /etc/cloudflare_proxy/traefik.toml: + - source: salt://cloudflare_proxy/files/traefik.toml.j2 + + # Dynamic configs + - /etc/cloudflare_proxy/dynamic/common.toml: + - source: salt://cloudflare_proxy/files/dynamic/common.toml.j2 + + - user: cloudflare_proxy + - group: cloudflare_proxy + - template: jinja + - context: + loki_url: "{{ pillar['rivet']['logging']['loki']['endpoint'] }}" + access_client_id: "{{ pillar['cloudflare']['access']['proxy']['client_id'] }}" + access_client_secret: "{{ pillar['cloudflare']['access']['proxy']['client_secret'] }}" + - mode: 440 + - require: + - file: create_etc_cloudflare_proxy + +push_cloudflare_proxy_service: + file.managed: + - name: /etc/systemd/system/cloudflare-proxy.service + - source: salt://cloudflare_proxy/files/cloudflare-proxy.service + +# Manually restart the Traefik service yourself in order to prevent terminating +# connections needlessly +start_cloudflare_proxy_service: + service.running: + - name: cloudflare-proxy + - enable: True + - require: + - file: push_cloudflare_proxy_service + - file: push_etc_cloudflare_proxy + +{%- if 'consul-client' in grains['roles'] %} +push_etc_consul_cloudflare_proxy_hcl: + file.managed: + - name: /etc/consul.d/cloudflare-proxy.hcl + - source: salt://cloudflare_proxy/files/consul/cloudflare-proxy.hcl + - template: jinja + - require: + - file: create_etc_consul + cmd.run: + - name: consul reload + - require: + - service: start_consul_service + - file: push_etc_consul_cloudflare_proxy_hcl + - onchanges: + - file: push_etc_consul_cloudflare_proxy_hcl +{%- endif %} + diff --git a/infra/salt/salt/cloudflared/files/cloudflared.service b/infra/salt/salt/cloudflared/files/cloudflared.service index 686d901868..c9bd5f7e1a 100644 --- a/infra/salt/salt/cloudflared/files/cloudflared.service +++ b/infra/salt/salt/cloudflared/files/cloudflared.service @@ -8,7 +8,7 @@ Type=notify ExecStart=/var/rivet-nix/result/cloudflared/bin/cloudflared --no-autoupdate --config /etc/cloudflared/config.yml tunnel run Restart=on-failure RestartSec=5s -{% if pillar['rivet']['deploy']['local']['restrict_service_resources'] %} +{% if 'local' in pillar.rivet.deploy and pillar.rivet.deploy.local.restrict_service_resources %} Nice=10 CPUAffinity=0 {% endif %} diff --git a/infra/salt/salt/cockroach/files/cockroach.service.j2 b/infra/salt/salt/cockroach/files/cockroach.service.j2 index 06886385b5..b77136a8bd 100644 --- a/infra/salt/salt/cockroach/files/cockroach.service.j2 +++ b/infra/salt/salt/cockroach/files/cockroach.service.j2 @@ -28,7 +28,7 @@ ExecStart=/usr/local/bin/cockroach start \ TimeoutStopSec=60 Restart=always RestartSec=10 -{% if pillar['rivet']['deploy']['local']['restrict_service_resources'] %} +{% if 'local' in pillar.rivet.deploy and pillar.rivet.deploy.local.restrict_service_resources %} Nice=10 CPUAffinity=0 {% endif %} diff --git a/infra/salt/salt/cockroach/init.sls b/infra/salt/salt/cockroach/init.sls index f4282b3450..d14173a70f 100644 --- a/infra/salt/salt/cockroach/init.sls +++ b/infra/salt/salt/cockroach/init.sls @@ -2,7 +2,7 @@ # cockroach init --insecure --cluster-name rivet-X --host 10.0.8.1:26258 # See https://www.cockroachlabs.com/docs/releases/index.html -{% set version = '23.1.7' %} +{% set version = '22.2.0' %} {% if grains['volumes']['crdb']['mount'] %} {% set device = '/dev/disk/by-id/scsi-0Linode_Volume_' ~ grains['rivet']['name'] ~ '-crdb' %} @@ -13,13 +13,14 @@ disk_create_cockroach: - fs_type: ext4 disk_mount_cockroach: + file.directory: + - name: /var/lib/cockroach mount.mounted: - name: /var/lib/cockroach - device: {{ device }} - fstype: ext4 - require: - blockdev: disk_create_cockroach - - file: mkdir_crdb {% endif %} @@ -67,6 +68,9 @@ mkdir_crdb: - /usr/local/lib/cockroach: [] - require: - user: create_crdb_user + {%- if grains['volumes']['crdb']['mount'] %} + - mount: disk_mount_cockroach + {%- endif %} install_crdb: diff --git a/infra/salt/salt/consul/files/consul.service b/infra/salt/salt/consul/files/consul.service index 9ac93b15d9..cc929ebc64 100644 --- a/infra/salt/salt/consul/files/consul.service +++ b/infra/salt/salt/consul/files/consul.service @@ -24,7 +24,7 @@ KillSignal=SIGTERM LimitNOFILE=65536 Restart=always RestartSec=2 -{% if pillar['rivet']['deploy']['local']['restrict_service_resources'] %} +{% if 'local' in pillar.rivet.deploy and pillar.rivet.deploy.local.restrict_service_resources %} Nice=10 CPUAffinity=0 {% endif %} diff --git a/infra/salt/salt/traefik/files/consul/traefik.hcl.j2 b/infra/salt/salt/ingress_proxy/files/consul/ingress-proxy.hcl.j2 similarity index 87% rename from infra/salt/salt/traefik/files/consul/traefik.hcl.j2 rename to infra/salt/salt/ingress_proxy/files/consul/ingress-proxy.hcl.j2 index aa61b4a163..abfc7d2f6f 100644 --- a/infra/salt/salt/traefik/files/consul/traefik.hcl.j2 +++ b/infra/salt/salt/ingress_proxy/files/consul/ingress-proxy.hcl.j2 @@ -1,5 +1,5 @@ services { - id = "traefik-lb-80" + id = "ingress-proxy-lb-80" name = "{{service_name}}" tags = ["traefik", "lb-80"] @@ -15,7 +15,7 @@ services { } services { - id = "traefik-lb-443" + id = "ingress-proxy-lb-443" name = "{{service_name}}" tags = ["traefik", "lb-443"] @@ -31,7 +31,7 @@ services { } services { - id = "traefik-client" + id = "ingress-proxy-client" name = "{{service_name}}" tags = ["traefik", "api"] diff --git a/infra/salt/salt/traefik/files/dynamic/common.toml.j2 b/infra/salt/salt/ingress_proxy/files/dynamic/common.toml.j2 similarity index 100% rename from infra/salt/salt/traefik/files/dynamic/common.toml.j2 rename to infra/salt/salt/ingress_proxy/files/dynamic/common.toml.j2 diff --git a/infra/salt/salt/traefik/files/dynamic/tls.toml.j2 b/infra/salt/salt/ingress_proxy/files/dynamic/tls.toml.j2 similarity index 53% rename from infra/salt/salt/traefik/files/dynamic/tls.toml.j2 rename to infra/salt/salt/ingress_proxy/files/dynamic/tls.toml.j2 index 87018329cb..b5a536b690 100644 --- a/infra/salt/salt/traefik/files/dynamic/tls.toml.j2 +++ b/infra/salt/salt/ingress_proxy/files/dynamic/tls.toml.j2 @@ -1,12 +1,12 @@ {%- for cert_id in traefik.tls_certs %} [[tls.certificates]] - certFile = "/etc/traefik/tls/{{ cert_id }}_cert.pem" - keyFile = "/etc/traefik/tls/{{ cert_id }}_key.pem" + certFile = "/etc/ingress_proxy/tls/{{ cert_id }}_cert.pem" + keyFile = "/etc/ingress_proxy/tls/{{ cert_id }}_key.pem" {%- endfor %} {%- if traefik.tls_client_cert %} [tls.options.default.clientAuth] - caFiles = ["/etc/traefik/tls/traefik_client.crt"] + caFiles = ["/etc/ingress_proxy/tls/traefik_client.crt"] clientAuthType = "RequireAndVerifyClientCert" {%- endif %} diff --git a/infra/salt/salt/traefik/files/traefik.service b/infra/salt/salt/ingress_proxy/files/ingress-proxy.service similarity index 66% rename from infra/salt/salt/traefik/files/traefik.service rename to infra/salt/salt/ingress_proxy/files/ingress-proxy.service index fe2a885f30..1be388aa25 100644 --- a/infra/salt/salt/traefik/files/traefik.service +++ b/infra/salt/salt/ingress_proxy/files/ingress-proxy.service @@ -1,14 +1,14 @@ # See https://doc.traefik.io/traefik-enterprise/installing/on-premise/#systemd-linux-only [Unit] -Description=Traefik +Description=Traefik Ingress proxy After=network-online.target Wants=network-online.target systemd-networkd-wait-online.service [Service] -User=traefik -Group=traefik -ExecStart=/usr/bin/traefik +User=ingress_proxy +Group=ingress_proxy +ExecStart=/usr/bin/traefik --configFile=/etc/ingress_proxy/traefik.toml PrivateTmp=true PrivateDevices=false ProtectHome=true @@ -19,7 +19,7 @@ LimitNOFILE=32768 AmbientCapabilities=CAP_NET_BIND_SERVICE Restart=always RestartSec=2 -{% if pillar['rivet']['deploy']['local']['restrict_service_resources'] %} +{% if 'local' in pillar.rivet.deploy and pillar.rivet.deploy.local.restrict_service_resources %} Nice=10 CPUAffinity=0 {% endif %} diff --git a/infra/salt/salt/traefik/files/traefik.toml.j2 b/infra/salt/salt/ingress_proxy/files/traefik.toml.j2 similarity index 93% rename from infra/salt/salt/traefik/files/traefik.toml.j2 rename to infra/salt/salt/ingress_proxy/files/traefik.toml.j2 index 6d7b0d9a07..6a92b3eb32 100644 --- a/infra/salt/salt/traefik/files/traefik.toml.j2 +++ b/infra/salt/salt/ingress_proxy/files/traefik.toml.j2 @@ -54,12 +54,12 @@ [log] level = "{{ pillar['rivet']['traefik']['log_level'] }}" - filePath = "/opt/traefik/traefik.log" + filePath = "/opt/ingress_proxy/traefik.log" format = "json" {% if pillar['rivet']['traefik']['access_logs'] %} [accessLog] - filePath = "/opt/traefik/access.log" + filePath = "/opt/ingress_proxy/access.log" format = "json" fields.defaultMode = "keep" fields.headers.defaultMode = "keep" @@ -74,7 +74,7 @@ [providers] [providers.file] - directory = "/etc/traefik/dynamic" + directory = "/etc/ingress_proxy/dynamic" {%- if 'consul-client' in grains['roles'] %} [providers.consulCatalog] diff --git a/infra/salt/salt/ingress_proxy/init.sls b/infra/salt/salt/ingress_proxy/init.sls new file mode 100644 index 0000000000..12f2f7914d --- /dev/null +++ b/infra/salt/salt/ingress_proxy/init.sls @@ -0,0 +1,127 @@ +{% set pool = grains['rivet']['pool_id'] %} +{% if pool == 'ing-px' or pool == 'local' %} + {% set tls_certs = ['cloudflare_rivet_gg'] %} + {% set tls_client_cert = true %} +{% elif pool == 'ing-job' %} + {% set tls_certs = ['letsencrypt_rivet_job'] %} + {% set tls_client_cert = false %} +{% endif %} + +# See on-prem installation instructions: https://doc.traefik.io/traefik-enterprise/installing/on-premise/#systemd-linux-only + +create_ingress_proxy_user: + user.present: + - name: ingress_proxy + - shell: /bin/false + - system: True + - usergroup: True + +create_etc_ingress_proxy: + file.directory: + - names: + - /etc/ingress_proxy/: {} + - /etc/ingress_proxy/dynamic/: {} + - /etc/ingress_proxy/tls/: {} + - /opt/ingress_proxy/: {} + - user: ingress_proxy + - group: ingress_proxy + - mode: 550 + - require: + - user: create_ingress_proxy_user + +push_etc_ingress_proxy: + file.managed: + - names: + # Static config + - /etc/ingress_proxy/traefik.toml: + - source: salt://ingress_proxy/files/traefik.toml.j2 + + # Dynamic configs + - /etc/ingress_proxy/dynamic/common.toml: + - source: salt://ingress_proxy/files/dynamic/common.toml.j2 + - /etc/ingress_proxy/dynamic/tls.toml: + - source: salt://ingress_proxy/files/dynamic/tls.toml.j2 + + # TLS certs + {%- for cert_id in tls_certs %} + - /etc/ingress_proxy/tls/{{ cert_id }}_cert.pem: + - contents: | + {{ pillar['tls']['tls_certs'][cert_id]['cert_pem'] | indent(12) }} + - /etc/ingress_proxy/tls/{{ cert_id }}_key.pem: + - contents: | + {{ pillar['tls']['tls_certs'][cert_id]['key_pem'] | indent(12) }} + {%- endfor %} + + # TLS client cert + {%- if tls_client_cert %} + - /etc/ingress_proxy/tls/traefik_client.crt: + - source: https://developers.cloudflare.com/ssl/static/authenticated_origin_pull_ca.pem + - source_hash: c1a581133a27f5fc98cbb1f32d048925470deab627e6b5f1b586f6df075d8493ec7d08ede04d0f31ec2c2cd74de27ed0df866e3874ad54a9e962695759ba7e5b + {%- endif %} + + - user: ingress_proxy + - group: ingress_proxy + - template: jinja + - context: + provider_http: + endpoint: 'https://route.api.{{ pillar['rivet']['domain']['base'] }}/v1/traefik/config?region={{grains['rivet']['region_id']}}&pool={{grains['rivet']['pool_id']}}&token={{pillar['rivet']['api-route']['token']}}' + {%- if pool == 'ing-px' %} + poll_interval: '2.5s' + {%- else %} + poll_interval: '1s' + {%- endif %} + namespace: {{ pillar['rivet']['namespace'] }} + pool: {{ pool }} + domain: {{ pillar['rivet']['domain'] }} + nebula_ipv4: {{ grains['nebula']['ipv4'] }} + traefik: + tls_certs: {{ tls_certs }} + tls_client_cert: {{ tls_client_cert }} + - mode: 440 + - require: + - file: create_etc_ingress_proxy + +push_ingress_proxy_service: + file.managed: + - name: /etc/systemd/system/ingress-proxy.service + - source: salt://ingress_proxy/files/ingress-proxy.service + - template: jinja + +# Stop and disable the old service under the old name first +stop_traefik_service: + service.dead: + - name: traefik + - enable: False + +# Manually restart the Traefik service yourself in order to prevent terminating +# connections needlessly +start_ingress_proxy_service: + service.running: + - name: ingress-proxy + - enable: True + - require: + - file: install_traefik + - file: push_ingress_proxy_service + - file: push_etc_ingress_proxy + - service: stop_traefik_service + +{%- if 'consul-client' in grains['roles'] %} +push_etc_consul_ingress_proxy_hcl: + file.managed: + - name: /etc/consul.d/ingress-proxy.hcl + - source: salt://ingress_proxy/files/consul/ingress-proxy.hcl.j2 + - template: jinja + - context: + service_name: {{ pool }} + nebula_ipv4: {{ grains['nebula']['ipv4'] }} + - require: + - file: create_etc_consul + cmd.run: + - name: consul reload + - require: + - service: start_consul_service + - file: push_etc_consul_ingress_proxy_hcl + - onchanges: + - file: push_etc_consul_ingress_proxy_hcl +{%- endif %} + diff --git a/infra/salt/salt/minio/files/minio.service b/infra/salt/salt/minio/files/minio.service index 42c5b8ffa7..bd2deb9294 100644 --- a/infra/salt/salt/minio/files/minio.service +++ b/infra/salt/salt/minio/files/minio.service @@ -18,7 +18,7 @@ LimitNOFILE=1048576 TasksMax=infinity TimeoutStopSec=infinity SendSIGKILL=no -{% if pillar['rivet']['deploy']['local']['restrict_service_resources'] %} +{% if 'local' in pillar.rivet.deploy and pillar.rivet.deploy.local.restrict_service_resources %} Nice=10 CPUAffinity=0 {% endif %} diff --git a/infra/salt/salt/nats/files/nats-server.service b/infra/salt/salt/nats/files/nats-server.service index b5e70460ae..e95cd18e2a 100644 --- a/infra/salt/salt/nats/files/nats-server.service +++ b/infra/salt/salt/nats/files/nats-server.service @@ -14,7 +14,7 @@ ExecReload=/bin/kill -s HUP $MAINPID ExecStop=/bin/kill -s SIGINT $MAINPID Restart=always RestartSec=2 -{% if pillar['rivet']['deploy']['local']['restrict_service_resources'] %} +{% if 'local' in pillar.rivet.deploy and pillar.rivet.deploy.local.restrict_service_resources %} Nice=10 CPUAffinity=0 {% endif %} diff --git a/infra/salt/salt/node_exporter/files/node_exporter.service b/infra/salt/salt/node_exporter/files/node_exporter.service index 312919755d..227f0d3262 100644 --- a/infra/salt/salt/node_exporter/files/node_exporter.service +++ b/infra/salt/salt/node_exporter/files/node_exporter.service @@ -10,7 +10,7 @@ Type=simple ExecStart=/usr/bin/node_exporter --collector.cgroups --collector.network_route --collector.systemd Restart=always RestartSec=2 -{% if pillar['rivet']['deploy']['local']['restrict_service_resources'] %} +{% if 'local' in pillar.rivet.deploy and pillar.rivet.deploy.local.restrict_service_resources %} Nice=10 CPUAffinity=0 {% endif %} diff --git a/infra/salt/salt/nomad/files/nomad.service.j2 b/infra/salt/salt/nomad/files/nomad.service.j2 index 7a3b88199e..cb746dc319 100644 --- a/infra/salt/salt/nomad/files/nomad.service.j2 +++ b/infra/salt/salt/nomad/files/nomad.service.j2 @@ -32,7 +32,7 @@ Restart=always RestartSec=2 TasksMax=infinity OOMScoreAdjust=-1000 -{% if pillar['rivet']['deploy']['local']['restrict_service_resources'] %} +{% if 'local' in pillar.rivet.deploy and pillar.rivet.deploy.local.restrict_service_resources %} Nice=10 CPUAffinity=0 {% endif %} diff --git a/infra/salt/salt/nomad/init.sls b/infra/salt/salt/nomad/init.sls index c9ed45b37f..62833c2dd7 100644 --- a/infra/salt/salt/nomad/init.sls +++ b/infra/salt/salt/nomad/init.sls @@ -1,5 +1,5 @@ # https://github.com/hashicorp/nomad/releases -{% set version = '1.6.1' %} +{% set version = '1.6.0' %} {% set create_nomad_user = 'nomad-server' in grains['roles'] %} {% if create_nomad_user %} diff --git a/infra/salt/salt/prometheus/files/prometheus.service.j2 b/infra/salt/salt/prometheus/files/prometheus.service.j2 index c3b826e873..918be473b2 100644 --- a/infra/salt/salt/prometheus/files/prometheus.service.j2 +++ b/infra/salt/salt/prometheus/files/prometheus.service.j2 @@ -17,7 +17,7 @@ ExecStart=/usr/bin/prometheus \ ExecReload=/bin/kill -HUP $MAINPID Restart=always RestartSec=2 -{% if pillar['rivet']['deploy']['local']['restrict_service_resources'] %} +{% if 'local' in pillar.rivet.deploy and pillar.rivet.deploy.local.restrict_service_resources %} Nice=10 CPUAffinity=0 {% endif %} diff --git a/infra/salt/salt/prometheus/init.sls b/infra/salt/salt/prometheus/init.sls index 6a042b2428..0940db8022 100644 --- a/infra/salt/salt/prometheus/init.sls +++ b/infra/salt/salt/prometheus/init.sls @@ -3,23 +3,6 @@ {% set pool = grains['rivet']['pool_id'] %} -create_prometheus_user: - user.present: - - name: prometheus - - shell: /bin/false - - system: True - - usergroup: True - -mkdir_prometheus: - file.directory: - - names: - - /mnt/prometheus: - - user: prometheus - - group: prometheus - - mode: 700 - - require: - - user: create_prometheus_user - {% if grains['volumes']['prm']['mount'] %} {% set device = '/dev/disk/by-id/scsi-0Linode_Volume_' ~ grains['rivet']['name'] ~ '-prm' %} @@ -29,15 +12,37 @@ disk_create_prometheus: - fs_type: ext4 disk_mount_prometheus: + file.directory: + - name: /mnt/prometheus + - makedirs: True mount.mounted: - name: /mnt/prometheus - device: {{device}} - fstype: ext4 - require: - - file: mkdir_prometheus - blockdev: disk_create_prometheus {% endif %} +create_prometheus_user: + user.present: + - name: prometheus + - shell: /bin/false + - system: True + - usergroup: True + +mkdir_prometheus: + file.directory: + - names: + - /mnt/prometheus: + - user: prometheus + - group: prometheus + - mode: 700 + - require: + - user: create_prometheus_user + {%- if grains['volumes']['prm']['mount'] %} + - mount: disk_mount_prometheus + {%- endif %} + install_prometheus: archive.extracted: - name: /opt/prometheus_{{version}}/ diff --git a/infra/salt/salt/redis/files/redis.service.j2 b/infra/salt/salt/redis/files/redis.service.j2 index 281b363660..e743b0caec 100644 --- a/infra/salt/salt/redis/files/redis.service.j2 +++ b/infra/salt/salt/redis/files/redis.service.j2 @@ -14,7 +14,7 @@ ExecStartPre=-/usr/bin/docker stop {{container_name}} ExecStartPre=-/usr/bin/docker rm {{container_name}} ExecStartPre=/usr/bin/docker pull {{image}} ExecStart=/bin/sh -c '/usr/bin/docker run --rm --name {{container_name}} --user "$(id -u redis):$(id -g redis)" -v /etc/redis/{{db}}.conf:/etc/redis/{{db}}.conf {% if persistent %}-v /var/lib/redis/{{db}}/db:/var/lib/redis/{{db}}/db{% endif %} --network host -p "{{port}}:{{port}}" {{image}} /etc/redis/{{db}}.conf' -{% if pillar['rivet']['deploy']['local']['restrict_service_resources'] %} +{% if 'local' in pillar.rivet.deploy and pillar.rivet.deploy.local.restrict_service_resources %} Nice=10 CPUAffinity=0 {% endif %} diff --git a/infra/salt/salt/top.sls b/infra/salt/salt/top.sls index 572811fb94..163aff876a 100644 --- a/infra/salt/salt/top.sls +++ b/infra/salt/salt/top.sls @@ -32,7 +32,9 @@ base: - minio 'G@roles:traefik': - traefik - 'G@roles:traefik-cloudflare-proxy': - - traefik_cloudflare_proxy + 'G@roles:ingress-proxy': + - ingress_proxy + 'G@roles:cloudflare-proxy': + - cloudflare_proxy 'G@roles:docker-plugin-loki': - docker_plugin_loki diff --git a/infra/salt/salt/traefik/init.sls b/infra/salt/salt/traefik/init.sls index 3031c037d5..c545a3c05a 100644 --- a/infra/salt/salt/traefik/init.sls +++ b/infra/salt/salt/traefik/init.sls @@ -1,18 +1,7 @@ # https://github.com/traefik/traefik/releases {% set version = '2.10.4' %} -{% set pool = grains['rivet']['pool_id'] %} -{% if pool == 'ing-px' or pool == 'local' %} - {% set tls_certs = ['cloudflare_rivet_gg'] %} - {% set tls_client_cert = true %} -{% elif pool == 'ing-job' %} - {% set tls_certs = ['letsencrypt_rivet_job'] %} - {% set tls_client_cert = false %} -{% endif %} - -# See on-prem installation instructions: https://doc.traefik.io/traefik-enterprise/installing/on-premise/#systemd-linux-only - -create_traefik_exporter_user: +create_traefik_user: user.present: - name: traefik - shell: /bin/false @@ -34,6 +23,7 @@ install_traefik: - group: traefik - mode: 755 - require: + - user: create_traefik_user - archive: install_traefik cmd.run: - name: traefik version @@ -43,104 +33,17 @@ install_traefik: - onchanges: - file: install_traefik -create_etc_traefik: - file.directory: - - names: - - /etc/traefik/: {} - - /etc/traefik/dynamic/: {} - - /etc/traefik/tls/: {} - - /opt/traefik/: {} - - user: traefik - - group: traefik - - mode: 550 - -push_etc_traefik: - file.managed: - - names: - # Static config - - /etc/traefik/traefik.toml: - - source: salt://traefik/files/traefik.toml.j2 - - # Dynamic configs - - /etc/traefik/dynamic/common.toml: - - source: salt://traefik/files/dynamic/common.toml.j2 - - /etc/traefik/dynamic/tls.toml: - - source: salt://traefik/files/dynamic/tls.toml.j2 - - # TLS certs - {%- for cert_id in tls_certs %} - - /etc/traefik/tls/{{ cert_id }}_cert.pem: - - contents: | - {{ pillar['tls']['tls_certs'][cert_id]['cert_pem'] | indent(12) }} - - /etc/traefik/tls/{{ cert_id }}_key.pem: - - contents: | - {{ pillar['tls']['tls_certs'][cert_id]['key_pem'] | indent(12) }} - {%- endfor %} - - # TLS client cert - {%- if tls_client_cert %} - - /etc/traefik/tls/traefik_client.crt: - - source: https://developers.cloudflare.com/ssl/static/authenticated_origin_pull_ca.pem - - source_hash: c1a581133a27f5fc98cbb1f32d048925470deab627e6b5f1b586f6df075d8493ec7d08ede04d0f31ec2c2cd74de27ed0df866e3874ad54a9e962695759ba7e5b - {%- endif %} - - - user: traefik - - group: traefik - - template: jinja - - context: - provider_http: - endpoint: 'https://route.api.{{ pillar['rivet']['domain']['base'] }}/v1/traefik/config?region={{grains['rivet']['region_id']}}&pool={{grains['rivet']['pool_id']}}&token={{pillar['rivet']['api-route']['token']}}' - {%- if pool == 'ing-px' %} - poll_interval: '2.5s' - {%- else %} - poll_interval: '1s' - {%- endif %} - namespace: {{ pillar['rivet']['namespace'] }} - pool: {{ pool }} - domain: {{ pillar['rivet']['domain'] }} - nebula_ipv4: {{ grains['nebula']['ipv4'] }} - traefik: - tls_certs: {{ tls_certs }} - tls_client_cert: {{ tls_client_cert }} - - mode: 440 - - require: - - file: create_etc_traefik - - -push_traefik_service: - file.managed: - - name: /etc/systemd/system/traefik.service - - source: salt://traefik/files/traefik.service - - template: jinja - -# Manually restart the Traefik service yourself in order to prevent terminating -# connections needlessly -start_traefik_service: - service.running: - - name: traefik - - enable: True - - require: - - file: install_traefik - - file: push_traefik_service - - file: push_etc_traefik - {%- if 'consul-client' in grains['roles'] %} -push_etc_consul_traefik_hcl: - file.managed: +# Delete old Treafik Consul file that was moved +remove_etc_consul_traefik_hcl: + file.absent: - name: /etc/consul.d/traefik.hcl - - source: salt://traefik/files/consul/traefik.hcl.j2 - - template: jinja - - context: - service_name: {{ pool }} - nebula_ipv4: {{ grains['nebula']['ipv4'] }} - - require: - - file: create_etc_consul cmd.run: - name: consul reload - require: - service: start_consul_service - - file: push_etc_consul_traefik_hcl + - file: remove_etc_consul_traefik_hcl - onchanges: - - file: push_etc_consul_traefik_hcl + - file: remove_etc_consul_traefik_hcl {%- endif %} diff --git a/infra/salt/salt/traefik_cloudflare_proxy/init.sls b/infra/salt/salt/traefik_cloudflare_proxy/init.sls deleted file mode 100644 index c6464acfc3..0000000000 --- a/infra/salt/salt/traefik_cloudflare_proxy/init.sls +++ /dev/null @@ -1,54 +0,0 @@ -{% import_json "/srv/salt-context/rivet/secrets.json" as rivet_secrets %} - -create_traefik_cloudflare_proxy_user: - user.present: - - name: traefik_cloudflare_proxy - - shell: /bin/false - - system: True - - usergroup: True - -create_etc_traefik_cloudflare_proxy: - file.directory: - - names: - - /etc/traefik_cloudflare_proxy/: {} - - /etc/traefik_cloudflare_proxy/dynamic/: {} - - user: traefik_cloudflare_proxy - - group: traefik_cloudflare_proxy - - mode: 550 - -push_etc_traefik_cloudflare_proxy: - file.managed: - - names: - # Static config - - /etc/traefik_cloudflare_proxy/traefik.toml: - - source: salt://traefik_cloudflare_proxy/files/traefik.toml.j2 - - # Dynamic configs - - /etc/traefik_cloudflare_proxy/dynamic/common.toml: - - source: salt://traefik_cloudflare_proxy/files/dynamic/common.toml.j2 - - - user: traefik_cloudflare_proxy - - group: traefik_cloudflare_proxy - - template: jinja - - context: - loki_url: "{{ pillar['rivet']['logging']['loki']['endpoint'] }}" - access_client_id: "{{ pillar['cloudflare']['access']['proxy']['client_id'] }}" - access_client_secret: "{{ pillar['cloudflare']['access']['proxy']['client_secret'] }}" - - mode: 440 - - require: - - file: create_etc_traefik_cloudflare_proxy - -push_traefik_cloudflare_proxy_service: - file.managed: - - name: /etc/systemd/system/traefik_cloudflare_proxy.service - - source: salt://traefik_cloudflare_proxy/files/traefik_cloudflare_proxy.service - -# Manually restart the Traefik service yourself in order to prevent terminating -# connections needlessly -start_traefik_cloudflare_proxy_service: - service.running: - - name: traefik_cloudflare_proxy - - enable: True - - require: - - file: push_traefik_cloudflare_proxy_service - - file: push_etc_traefik_cloudflare_proxy diff --git a/infra/salt/salt/traffic_server/files/consul/traffic_server.hcl.j2 b/infra/salt/salt/traffic_server/files/consul/traffic_server.hcl.j2 index 6337cdc181..bae47b1565 100644 --- a/infra/salt/salt/traffic_server/files/consul/traffic_server.hcl.j2 +++ b/infra/salt/salt/traffic_server/files/consul/traffic_server.hcl.j2 @@ -42,22 +42,6 @@ services { # and https://imagekit.io/blog/ultimate-guide-to-http-caching-for-static-assets/ "{{prefix}}.http.middlewares.ats-cdn-cache-control.headers.customResponseHeaders.Cache-Control=public, max-age=604800, immutable", - # MARK: routers.ats-build - # "{{prefix}}.http.routers.ats-build.entryPoints=lb-443", - # "{{prefix}}.http.routers.ats-build.rule=Host(`cdn.{{domain['base']}}`) && PathPrefix(`/build/`)", - # "{{prefix}}.http.routers.ats-build.middlewares=ats-build-auth, ats-build-path, ats-cdn-lfs", - # "{{prefix}}.http.routers.ats-build.tls=true", - - # MARK: middlewares.ats-build-auth - # TODO: Add more secure per-game authentication with https://doc.traefik.io/traefik/middlewares/http/forwardauth/ - # "{{prefix}}.http.middlewares.ats-build-auth.basicAuth.users=job_run_image:$apr1$0peMM8t1$/ST0ckxxbp4AY.SUzkk4E1", - # Without this, we'll receive a `SignatureDoesNotMatch` error - # "{{prefix}}.http.middlewares.ats-build-auth.basicAuth.removeHeader=true", - - # MARK: middlewares.ats-build-path - # "{{prefix}}.http.middlewares.ats-build-path.replacePathRegex.regex=^/build/(.*)", - # "{{prefix}}.http.middlewares.ats-build-path.replacePathRegex.replacement=/s3-cache/{{namespace}}-bucket-build/${1}", - {% for bucket in ["job-log", "team-billing", "lobby-history-export", "nomad-log-export"] %} # MARK: http.routers-{{bucket}} "{{prefix}}.http.routers.ats-{{bucket}}.entryPoints=lb-443", diff --git a/infra/salt/salt/traffic_server/files/trafficserver.service b/infra/salt/salt/traffic_server/files/trafficserver.service index 3cd4a9ba15..f6e3cb85d9 100644 --- a/infra/salt/salt/traffic_server/files/trafficserver.service +++ b/infra/salt/salt/traffic_server/files/trafficserver.service @@ -6,11 +6,11 @@ After=network-online.target Type=simple User=trafficserver Group=trafficserver -EnvironmentFile=-/etc/default/trafficserver +Environment="TM_START=yes" PIDFile=/run/trafficserver/manager.lock ExecStart=/var/rivet-nix/result/traffic_server/bin/traffic_manager $TM_DAEMON_ARGS ExecReload=/var/rivet-nix/result/traffic_server/bin/traffic_manager config reload -{% if pillar['rivet']['deploy']['local']['restrict_service_resources'] %} +{% if 'local' in pillar.rivet.deploy and pillar.rivet.deploy.local.restrict_service_resources %} Nice=10 CPUAffinity=0 {% endif %} diff --git a/infra/salt/salt/traffic_server/init.sls b/infra/salt/salt/traffic_server/init.sls index b7c9eb6cb3..5ce09cc5df 100644 --- a/infra/salt/salt/traffic_server/init.sls +++ b/infra/salt/salt/traffic_server/init.sls @@ -8,7 +8,7 @@ disk_create_traffic_serer: disk_mount_traffic_server: file.directory: - name: /mnt/trafficserver - + - makedirs: True mount.mounted: - name: /mnt/trafficserver - device: {{ device }} @@ -26,31 +26,23 @@ create_trafficserver_user: create_mnt_db_trafficserver: file.directory: - - name: /mnt/trafficserver/db - - user: trafficserver - - group: trafficserver - - mode: 700 - - makedirs: True - {%- if grains['volumes']['ats']['mount'] %} - - require: - - mount: disk_mount_traffic_server - {% endif %} - -create_var_log_trafficserver: - file.directory: - - name: /var/log/trafficserver + - names: + - /mnt/trafficserver/db + - /var/log/trafficserver + - /run/trafficserver - user: trafficserver - group: trafficserver - mode: 700 - makedirs: True - {%- if grains['volumes']['ats']['mount'] %} - require: + - user: create_trafficserver_user + {%- if grains['volumes']['ats']['mount'] %} - mount: disk_mount_traffic_server - {% endif %} + {%- endif %} push_trafficserver_service: file.managed: - - name: /lib/systemd/system/trafficserver.service + - name: /etc/systemd/system/trafficserver.service - source: salt://traffic_server/files/trafficserver.service - template: jinja - onchanges: @@ -70,10 +62,14 @@ push_etc_trafficserver_static: file.recurse: - name: /etc/trafficserver/ - source: salt://traffic_server/files/etc/static/ + - user: trafficserver + - group: trafficserver - file_mode: 644 - dir_mode: 755 # Keep other files, since we'll also be writing files in push_etc_trafficserver_dynamic - clean: False + - require: + - user: create_trafficserver_user push_etc_trafficserver_dynamic: file.managed: @@ -86,8 +82,10 @@ push_etc_trafficserver_dynamic: - source: salt://traffic_server/files/etc/dynamic/s3_auth_v4.config.j2 - /etc/trafficserver/s3_region_map.config: - source: salt://traffic_server/files/etc/dynamic/s3_region_map.config.j2 - - /etc/trafficserver/stored.config: + - /etc/trafficserver/storage.config: - source: salt://traffic_server/files/etc/dynamic/storage.config.j2 + - user: trafficserver + - group: trafficserver - mode: 644 - template: jinja - context: @@ -97,6 +95,9 @@ push_etc_trafficserver_dynamic: s3_access_key_id: {{ pillar['s3']['access']['default']['persistent_access_key_id'] }} s3_secret_access_key: {{ pillar['s3']['access']['default']['persistent_access_key_secret'] }} volume_size_cache: {{ grains['volumes']['ats']['size']|int - 1 }}G + - require: + - file: push_etc_trafficserver_static + - user: create_trafficserver_user reload_traffic_server_config: cmd.run: diff --git a/infra/tests/standalone/main.tf b/infra/tests/standalone/main.tf index 953cac3c70..25906539a4 100644 --- a/infra/tests/standalone/main.tf +++ b/infra/tests/standalone/main.tf @@ -43,19 +43,21 @@ module "server" { inbound_ipv4_cidr = ["0.0.0.0/0"] inbound_ipv6_cidr = ["::/0"] }, + + # TODO: Nebula IPv6 is theoretically supported (https://nebula.defined.net/docs/config/preferred-ranges/#how-nebula-orders-underlay-ip-addresses-it-learns-about), but seems to be problematic { label = "nebula-udp" ports = "4242" protocol = "udp" inbound_ipv4_cidr = ["0.0.0.0/0"] - inbound_ipv6_cidr = ["::/0"] + inbound_ipv6_cidr = [] }, { label = "nebula-tcp" ports = "4242" protocol = "tcp" inbound_ipv4_cidr = ["0.0.0.0/0"] - inbound_ipv6_cidr = ["::/0"] + inbound_ipv6_cidr = [] }, ] } diff --git a/infra/tests/stress-param/job-param.nomad b/infra/tests/stress-param/job-param.nomad index 3701abf2ec..ac234ff8b4 100644 --- a/infra/tests/stress-param/job-param.nomad +++ b/infra/tests/stress-param/job-param.nomad @@ -45,7 +45,7 @@ job "test-param" { } artifact { - source = "https://assets.rivet.gg/graphics/landing.png" + source = "https://assets2.rivet.gg/graphics/landing.png" destination = "local/landing.png" } diff --git a/infra/tf/master_cluster/nebula_lighthouse.tf b/infra/tf/master_cluster/nebula_lighthouse.tf index f65205bde6..5c5e988f99 100644 --- a/infra/tf/master_cluster/nebula_lighthouse.tf +++ b/infra/tf/master_cluster/nebula_lighthouse.tf @@ -25,20 +25,21 @@ module "nebula_lighthouse_server" { ] backup = true + # Nebula does not support IPv6 firewall_inbound = [ { label = "nebula-udp" ports = "4242" protocol = "udp" inbound_ipv4_cidr = ["0.0.0.0/0"] - inbound_ipv6_cidr = ["::/0"] + inbound_ipv6_cidr = [] }, { label = "nebula-tcp" ports = "4242" protocol = "tcp" inbound_ipv4_cidr = ["0.0.0.0/0"] - inbound_ipv6_cidr = ["::/0"] + inbound_ipv6_cidr = [] }, ] } diff --git a/infra/tf/modules/install_nebula/main.tf b/infra/tf/modules/install_nebula/main.tf index ad22969d6f..0066351257 100644 --- a/infra/tf/modules/install_nebula/main.tf +++ b/infra/tf/modules/install_nebula/main.tf @@ -18,6 +18,16 @@ locals { lighthouse = { am_lighthouse = var.is_lighthouse hosts = var.is_lighthouse ? null : sort(var.lighthouse_hosts) + + # Disable IPv6 + remote_allow_list = { + "0.0.0.0/0" = true + "::/0" = false + } + local_allow_list = { + "0.0.0.0/0" = true + "::/0" = false + } } listen = { host = "0.0.0.0" diff --git a/infra/tf/modules/secrets/main.tf b/infra/tf/modules/secrets/main.tf index 6fbccc4dec..4124127005 100644 --- a/infra/tf/modules/secrets/main.tf +++ b/infra/tf/modules/secrets/main.tf @@ -10,6 +10,6 @@ terraform { data "external" "bolt_secret" { for_each = var.keys - program = var.optional ? ["bolt", "secret", "get", "--format=json", "--optional", each.key] : ["bolt", "secret", "get", "--format=json", each.key] + program = ["${path.module}/scripts/get_secret.sh", each.key, var.optional ? "true" : "false"] } diff --git a/infra/tf/modules/secrets/scripts/get_secret.sh b/infra/tf/modules/secrets/scripts/get_secret.sh new file mode 100755 index 0000000000..7558d481ff --- /dev/null +++ b/infra/tf/modules/secrets/scripts/get_secret.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env bash +set -euf + +export BOLT_HEADLESS=1 + +KEY="$1" +OPTIONAL="$2" + +if [ "$OPTIONAL" == "true" ]; then + bolt secret get --format=json --optional "$KEY" +else + bolt secret get --format=json "$KEY" +fi + diff --git a/infra/tf/s3_backblaze/buckets.tf b/infra/tf/s3_backblaze/buckets.tf index 3e9a69c8b2..366bcac749 100644 --- a/infra/tf/s3_backblaze/buckets.tf +++ b/infra/tf/s3_backblaze/buckets.tf @@ -1,6 +1,11 @@ resource "b2_bucket" "bucket" { for_each = var.s3_buckets + lifecycle { + # TODO: Remove this. Fixes an issue with accidentally enabled file locks that can't be disabled. + ignore_changes = ["file_lock_configuration"] + } + bucket_name = each.key bucket_type = "allPrivate" diff --git a/lib/api-helper/build/Cargo.toml b/lib/api-helper/build/Cargo.toml index 48b3040eda..36a4cf56f9 100644 --- a/lib/api-helper/build/Cargo.toml +++ b/lib/api-helper/build/Cargo.toml @@ -37,7 +37,7 @@ serde = { version = "1.0", features = ["derive"] } serde_array_query = { git = "https://github.com/rivet-gg/serde_array_query.git", rev = "b9f8bfad77aea6f01dccc6cb77146b8c5daecaa3" } serde_json = "1.0" thiserror = "1.0" -tokio = { version = "1.21" } +tokio = { version = "1.29" } tracing = "0.1" tracing-subscriber = { version = "0.3", default-features = false, features = ["fmt", "json", "ansi"] } types = { path = "../../types/core" } diff --git a/lib/api-helper/build/src/start.rs b/lib/api-helper/build/src/start.rs index 67c32b0d0e..6c9d67bbee 100644 --- a/lib/api-helper/build/src/start.rs +++ b/lib/api-helper/build/src/start.rs @@ -5,6 +5,8 @@ use hyper::{ Body, Request, Response, Server, }; use std::{convert::Infallible, future::Future, net::SocketAddr, sync::Arc, time::Instant}; +use tokio::sync::Semaphore; +use tokio::time::{sleep, Duration}; use tracing::Instrument; use uuid::Uuid; @@ -66,9 +68,13 @@ where .and_then(|v| v.parse::().ok()) .unwrap(); + // let semaphore = Arc::new(Semaphore::new(8)); + // A `MakeService` that produces a `Service` to handle each connection let health_check_config = Arc::new(health_check_config); let make_service = make_service_fn(move |conn: &AddrStream| { + // let semaphore = semaphore.clone(); + let shared_client = shared_client.clone(); let pools = pools.clone(); let cache = cache.clone(); @@ -79,6 +85,8 @@ where let service = service_fn(move |req: Request| { let start = Instant::now(); + // let semaphore = semaphore.clone(); + let shared_client = shared_client.clone(); let pools = pools.clone(); let cache = cache.clone(); @@ -88,28 +96,71 @@ where let ray_id = Uuid::new_v4(); let req_span = tracing::info_span!("http request", method = %req.method(), uri = %req.uri(), %ray_id); async move { + let sem_start = Instant::now(); + // let _semaphor_acquire = semaphore.acquire().await.unwrap(); + // let semaphor_duration = sem_start.elapsed(); + tracing::info!( method = %req.method(), uri = %req.uri(), headers = ?req.headers(), body_size_hint = ?req.body().size_hint(), remote_addr = %remote_addr, + // semaphor_duration = ?semaphor_duration, "http request meta" ); - let res: Response = - match rivet_health_checks::handle(&*health_check_config, req).await { - Ok(res) => res, - Err(req) => { - let mut response = handle(shared_client, pools, cache, ray_id, req) - .instrument(tracing::info_span!("request_handle")) - .await?; - response - .headers_mut() - .insert("rvt-ray-id", ray_id.to_string().parse()?); - response + let res = tokio::task::Builder::new() + .name("api_helper::handle") + .spawn(async move { + // let res = Response::builder() + // .status(http::StatusCode::OK) + // .body(Body::from("ok"))?; + + let res = match rivet_health_checks::handle(&*health_check_config, req) + .await + { + Ok(res) => res, + Err(req) => { + // Response::builder() + // .status(http::StatusCode::OK) + // .body(Body::from("ok"))? + + let mut response = handle(shared_client, pools, cache, ray_id, req) + .instrument(tracing::info_span!("request_handle")) + .await?; + response + .headers_mut() + .insert("rvt-ray-id", ray_id.to_string().parse()?); + response + } + }; + + Result::, http::Error>::Ok(res) + }); + let res = match res { + Ok(res) => match res.await { + Ok(res) => match res { + Ok(res) => res, + Err(err) => { + tracing::error!(?err, "http error"); + return Err(err); + } + }, + Err(_) => { + tracing::error!("http error"); + return Ok(Response::builder() + .status(http::StatusCode::INTERNAL_SERVER_ERROR) + .body(Body::empty())?); } - }; + }, + Err(err) => { + tracing::error!(?err, "http error"); + return Ok(Response::builder() + .status(http::StatusCode::INTERNAL_SERVER_ERROR) + .body(Body::empty())?); + } + }; if res.status().is_server_error() { tracing::error!(status = ?res.status().as_u16(), "http server error"); diff --git a/lib/bolt/Cargo.lock b/lib/bolt/Cargo.lock index c78a3a3d18..b0f8597311 100644 --- a/lib/bolt/Cargo.lock +++ b/lib/bolt/Cargo.lock @@ -2,6 +2,21 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "addr2line" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4fa78e18c64fce05e902adecd7a5eed15a5e0a3439f7b0e169f0252214865e3" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + [[package]] name = "ahash" version = "0.7.6" @@ -452,6 +467,21 @@ dependencies = [ "zeroize", ] +[[package]] +name = "backtrace" +version = "0.3.68" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4319208da049c43661739c5fade2ba182f09d1dc2299b32298d3a31692b17e12" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + [[package]] name = "base64" version = "0.13.1" @@ -1031,6 +1061,12 @@ dependencies = [ "wasi 0.11.0+wasi-snapshot-preview1", ] +[[package]] +name = "gimli" +version = "0.27.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e" + [[package]] name = "global-error" version = "0.1.5" @@ -1450,6 +1486,15 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" +[[package]] +name = "miniz_oxide" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +dependencies = [ + "adler", +] + [[package]] name = "mio" version = "0.8.8" @@ -1520,6 +1565,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" +[[package]] +name = "object" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8bda667d9f2b5051b8833f59f3bf748b28ef54f850f4fcb389a252aa383866d1" +dependencies = [ + "memchr", +] + [[package]] name = "once_cell" version = "1.18.0" @@ -2048,6 +2102,12 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "rustc-demangle" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" + [[package]] name = "rustc_version" version = "0.4.0" @@ -2499,11 +2559,12 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.28.2" +version = "1.29.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94d7b1cfd2aa4011f2de74c2c4c63665e27a71006b0a192dcd2710272e73dfa2" +checksum = "532826ff75199d5833b9d2c5fe410f29235e25704ee5f0ef599fb51c21f4a4da" dependencies = [ "autocfg", + "backtrace", "bytes", "libc", "mio", diff --git a/lib/bolt/cli/Cargo.toml b/lib/bolt/cli/Cargo.toml index 8e5e0adee7..e4f2c37958 100644 --- a/lib/bolt/cli/Cargo.toml +++ b/lib/bolt/cli/Cargo.toml @@ -13,4 +13,4 @@ clap = { version = "4.3", features = ["derive", "env"] } duct = "0.13" serde_json = "1.0" tempfile = "3.2" -tokio = { version = "1.21", features = ["full"] } +tokio = { version = "1.29", features = ["full"] } diff --git a/lib/bolt/cli/src/commands/config.rs b/lib/bolt/cli/src/commands/config.rs index ce7db62a25..9571fda88f 100644 --- a/lib/bolt/cli/src/commands/config.rs +++ b/lib/bolt/cli/src/commands/config.rs @@ -21,6 +21,12 @@ pub enum SubCommand { /// Adds missing regions from supported cloud providers to default_regions.toml. #[clap(hide(true))] GenerateDefaultRegions, + ServiceDependencies { + #[clap(index = 1)] + svc_name: String, + #[clap(long, short = 'r')] + recursive: bool, + }, } impl SubCommand { @@ -34,6 +40,29 @@ impl SubCommand { tasks::config::set_namespace(&namespace).await?; } Self::GenerateDefaultRegions => tasks::config::generate_default_regions().await?, + Self::ServiceDependencies { + svc_name, + recursive, + } => { + // Build project + let ctx = bolt_core::context::ProjectContextData::new( + std::env::var("BOLT_NAMESPACE").ok(), + ) + .await; + + // Read deps + let deps = if *recursive { + ctx.recursive_dependencies(&[&svc_name]).await + } else { + let svc = ctx.service_with_name(svc_name).await; + svc.dependencies().await + }; + + // Print deps + for dep in deps { + println!("{}", dep.name()); + } + } } Ok(()) diff --git a/lib/bolt/cli/src/commands/db/migrate.rs b/lib/bolt/cli/src/commands/db/migrate.rs index d95808668f..548af74e08 100644 --- a/lib/bolt/cli/src/commands/db/migrate.rs +++ b/lib/bolt/cli/src/commands/db/migrate.rs @@ -21,6 +21,8 @@ pub enum SubCommand { /// /// Helpful when dealing with bugged migrations. Force { service: String, num: usize }, + /// Lists migrations + List, /// Drops the entire database. Drop { service: String }, } @@ -61,6 +63,11 @@ impl SubCommand { Self::Force { service, num } => { tasks::migrate::force(&ctx, &ctx.service_with_name(&service).await, num).await?; } + Self::List => { + for svc in ctx.services_with_migrations().await { + println!("{}", svc.name()); + } + } Self::Drop { service } => { tasks::migrate::drop(&ctx, &ctx.service_with_name(&service).await).await?; } diff --git a/lib/bolt/cli/src/commands/infra.rs b/lib/bolt/cli/src/commands/infra.rs index 1f68472b5d..e9897f2cfd 100644 --- a/lib/bolt/cli/src/commands/infra.rs +++ b/lib/bolt/cli/src/commands/infra.rs @@ -8,16 +8,23 @@ use clap::Parser; #[derive(Parser)] pub enum SubCommand { /// Prints out the plan used to provision the Rivet cluster. - Plan, + Plan { + #[clap(long)] + start_at: Option, + }, /// Provisions all infrastructure required for the Rivet cluster. Up { #[clap(long, short = 'y')] yes: bool, + #[clap(long)] + start_at: Option, }, /// Destroys all provisioned infrastructure. Destroy { #[clap(long, short = 'y')] yes: bool, + #[clap(long)] + start_at: Option, }, /// Manages infrastructure migrations. #[clap(hide(true))] @@ -35,16 +42,24 @@ pub enum MigrateSubCommand { impl SubCommand { pub async fn execute(self, ctx: ProjectContext) -> Result<()> { match self { - Self::Plan => { - let plan = tasks::infra::build_plan(&ctx)?; - println!("{plan:#?}"); + Self::Plan { start_at } => { + let plan = tasks::infra::build_plan(&ctx, start_at)?; + for step in plan { + println!("{}: {:?}", step.name_id, step.kind); + } } - Self::Up { yes: auto_approve } => { - let plan = tasks::infra::build_plan(&ctx)?; + Self::Up { + yes: auto_approve, + start_at, + } => { + let plan = tasks::infra::build_plan(&ctx, start_at)?; tasks::infra::execute_plan(&ctx, &plan, ExecutePlanOpts { auto_approve }).await?; } - Self::Destroy { yes: auto_approve } => { - let plan = tasks::infra::build_plan(&ctx)?; + Self::Destroy { + yes: auto_approve, + start_at, + } => { + let plan = tasks::infra::build_plan(&ctx, start_at)?; tasks::infra::destroy_plan(&ctx, &plan, ExecutePlanOpts { auto_approve }).await?; } Self::Migrate { command } => match command { diff --git a/lib/bolt/cli/src/commands/init.rs b/lib/bolt/cli/src/commands/init.rs index ae0a69179a..a94c2b334a 100644 --- a/lib/bolt/cli/src/commands/init.rs +++ b/lib/bolt/cli/src/commands/init.rs @@ -26,7 +26,7 @@ impl InitOpts { let ctx = context::ProjectContextData::new(Some(self.namespace.clone())).await; // Apply infra - let plan = tasks::infra::build_plan(&ctx)?; + let plan = tasks::infra::build_plan(&ctx, None)?; tasks::infra::execute_plan( &ctx, &plan, diff --git a/lib/bolt/cli/src/main.rs b/lib/bolt/cli/src/main.rs index 454d5466b2..4a45be3b52 100644 --- a/lib/bolt/cli/src/main.rs +++ b/lib/bolt/cli/src/main.rs @@ -134,6 +134,10 @@ async fn main() -> Result { fn prompt_prod() -> Result<()> { use std::io::Write; + if std::env::var("BOLT_HEADLESS").ok() == Some("1".to_string()) { + return Ok(()); + } + let mut input = String::new(); print!("Are you sure you want to run this command in prod? (yes) "); diff --git a/lib/bolt/core/Cargo.toml b/lib/bolt/core/Cargo.toml index 491a0cddae..ae063eda33 100644 --- a/lib/bolt/core/Cargo.toml +++ b/lib/bolt/core/Cargo.toml @@ -34,7 +34,7 @@ serde = { version ="1.0", features = ["derive"] } serde_json = "1.0" tempfile = "3.2" thiserror = "1.0" -tokio = { version = "1.21", features = ["full"] } +tokio = { version = "1.29", features = ["full"] } toml = "0.7" toml_edit = "0.19" types = { path = "../../types/core" } diff --git a/lib/bolt/core/src/context/project.rs b/lib/bolt/core/src/context/project.rs index ac469f523e..12c4c7777f 100644 --- a/lib/bolt/core/src/context/project.rs +++ b/lib/bolt/core/src/context/project.rs @@ -112,7 +112,7 @@ impl ProjectContextData { // Assign references to all services after we're done for svc in &ctx.svc_ctxs { - *svc.project.write().await = Arc::downgrade(&ctx); + svc.set_project(Arc::downgrade(&ctx)).await; } ctx @@ -172,6 +172,7 @@ impl ProjectContextData { // Load the service let svc_ctx = context::service::ServiceContextData::from_path( Weak::new(), + &svc_ctxs_map, &workspace_path, &worker_path, ) @@ -218,6 +219,7 @@ impl ProjectContextData { // Load the service let svc_ctx = context::service::ServiceContextData::from_path( Weak::new(), + &svc_ctxs_map, workspace_path, &entry.path(), ) @@ -439,10 +441,11 @@ impl ProjectContextData { impl ProjectContextData { /// Origin used for building links to the Hub. pub fn origin_hub(&self) -> String { - self.ns().dns.hub_origin.clone().map_or_else( - || self.ns().dns.domain.main.clone(), - |x| format!("https://hub.{x}"), - ) + self.ns() + .dns + .hub_origin + .clone() + .unwrap_or_else(|| format!("https://hub.{}", self.ns().dns.domain.main.clone())) } pub fn domain_main(&self) -> String { self.ns().dns.domain.main.clone() diff --git a/lib/bolt/core/src/context/service.rs b/lib/bolt/core/src/context/service.rs index 95a8977a84..5a13fca489 100644 --- a/lib/bolt/core/src/context/service.rs +++ b/lib/bolt/core/src/context/service.rs @@ -1,12 +1,12 @@ +use anyhow::{bail, ensure, Context, Result}; +use async_recursion::async_recursion; +use s3_util::aws_sdk_s3; use std::{ collections::HashMap, hash::{Hash, Hasher}, path::{Path, PathBuf}, sync::{Arc, Weak}, }; - -use anyhow::{bail, ensure, Context, Result}; -use s3_util::aws_sdk_s3; use tempfile::NamedTempFile; use tokio::{fs, process::Command, sync::RwLock}; @@ -25,7 +25,9 @@ use super::BuildOptimization; pub type ServiceContext = Arc; pub struct ServiceContextData { - pub(in crate::context) project: RwLock>, + project: RwLock>, + /// If this is overriding a service from an additional root, then this will be specified. + overridden_service: Option, config: config::service::ServiceConfig, path: PathBuf, workspace_path: PathBuf, @@ -45,6 +47,18 @@ impl Hash for ServiceContextData { } impl ServiceContextData { + /// Sets the refernece to the project once the project context is finished initiating. + #[async_recursion] + pub(in crate::context) async fn set_project( + &self, + project: Weak, + ) { + *self.project.write().await = project.clone(); + if let Some(overridden_service) = &self.overridden_service { + overridden_service.set_project(project.clone()).await; + } + } + pub async fn project(&self) -> ProjectContext { self.project .read() @@ -69,6 +83,7 @@ impl ServiceContextData { impl ServiceContextData { pub async fn from_path( project: Weak, + svc_ctxs_map: &HashMap, workspace_path: &Path, path: &Path, ) -> Option { @@ -92,8 +107,12 @@ impl ServiceContextData { Err(_) => None, }; + // Read overridden service + let overridden_service = svc_ctxs_map.get(&config.service.name).cloned(); + Some(Arc::new(ServiceContextData::new( project, + overridden_service, config, workspace_path, path, @@ -103,6 +122,7 @@ impl ServiceContextData { fn new( project: Weak, + overridden_service: Option, config: config::service::ServiceConfig, workspace_path: &Path, path: &Path, @@ -111,6 +131,7 @@ impl ServiceContextData { // Build context let ctx = ServiceContextData { project: RwLock::new(project), + overridden_service, config, path: path.to_owned(), workspace_path: workspace_path.to_owned(), @@ -324,7 +345,7 @@ impl ServiceContextData { impl ServiceContextData { pub fn enable_tokio_console(&self) -> bool { // TODO: This seems to have a significant performance impact - false + true } } @@ -332,16 +353,32 @@ impl ServiceContextData { #[derive(Debug, Clone)] pub enum ServiceBuildPlan { /// Build exists locally. - ExistingLocalBuild { output_path: PathBuf }, + ExistingLocalBuild { + /// Absolute path to the executable on the host system. + exec_path: PathBuf, + }, /// Build exists on S3 server. - ExistingUploadedBuild { build_key: String }, + ExistingUploadedBuild { + build_key: String, + + /// Path to the executable in the archive. + exec_path: String, + }, /// Build the service locally. - BuildLocally { output_path: PathBuf }, + BuildLocally { + /// Absolute path to the executable on the host system. + exec_path: PathBuf, + }, /// Build the service and upload to S3. - BuildAndUpload { build_key: String }, + BuildAndUpload { + build_key: String, + + /// Path to the executable in the archive. + exec_path: String, + }, /// Run a Docker container. Docker { image_tag: String }, @@ -369,36 +406,52 @@ impl ServiceContextData { .await; if force_build { - return Ok(ServiceBuildPlan::BuildLocally { output_path }); + return Ok(ServiceBuildPlan::BuildLocally { + exec_path: output_path, + }); } // Check if there's an existing build we can use let build_exists = tokio::fs::metadata(&output_path).await.is_ok(); if build_exists { - return Ok(ServiceBuildPlan::ExistingLocalBuild { output_path }); + return Ok(ServiceBuildPlan::ExistingLocalBuild { + exec_path: output_path, + }); } // Default to building - Ok(ServiceBuildPlan::BuildLocally { output_path }) + Ok(ServiceBuildPlan::BuildLocally { + exec_path: output_path, + }) } // Build and upload to S3 config::ns::ClusterKind::Distributed { .. } => { // Derive the build key let key = self.s3_build_key(build_context).await?; + let exec_path = self.cargo_name().expect("no cargo name").to_string(); if force_build { - return Ok(ServiceBuildPlan::BuildAndUpload { build_key: key }); + return Ok(ServiceBuildPlan::BuildAndUpload { + build_key: key, + exec_path, + }); } // Check if there's an existing build we can use let s3_client = project_ctx.s3_client_service_builds().await?; let build_exists = s3::check_exists_cached(&project_ctx, &s3_client, &key).await?; if build_exists { - return Ok(ServiceBuildPlan::ExistingUploadedBuild { build_key: key }); + return Ok(ServiceBuildPlan::ExistingUploadedBuild { + build_key: key, + exec_path, + }); } // Default to building - Ok(ServiceBuildPlan::BuildAndUpload { build_key: key }) + Ok(ServiceBuildPlan::BuildAndUpload { + build_key: key, + exec_path, + }) } } } @@ -406,6 +459,7 @@ impl ServiceContextData { // Dependencies impl ServiceContextData { + #[async_recursion] pub async fn dependencies(&self) -> Vec { let project = self.project().await; @@ -425,33 +479,7 @@ impl ServiceContextData { } } - // TODO: Add dev dependencies if building for tests - // Add operation dependencies from Cargo.toml - if let Some(cargo) = &self.cargo { - let svc_path = self.path(); - let svcs = cargo - .dependencies - .iter() - .filter_map(|(_, x)| { - if let config::service::CargoDependency::Path { path } = x { - Some(path) - } else { - None - } - }) - .filter_map(|path| { - let absolute_path = svc_path.join(path); - all_svcs - .iter() - .filter(|x| x.path() == absolute_path) - .next() - .cloned() - }); - - dep_ctxs.extend(svcs); - } - - // Check that these are services you can explicitly depend on + // Check that these are services you can explicitly depend on in the Service.toml for dep in &dep_ctxs { if !self.config().service.test_only && dep.config().service.test_only { panic!( @@ -473,6 +501,46 @@ impl ServiceContextData { } } + // TODO: Add dev dependencies if building for tests + // Add operation dependencies from Cargo.toml + // + // You cannot depend on these services from the Service.toml, only as a Cargo dependency + if let Some(cargo) = &self.cargo { + let svcs = cargo + .dependencies + .iter() + .filter_map(|(name, dep)| { + if let config::service::CargoDependency::Path { .. } = dep { + Some(name) + } else { + None + } + }) + .filter_map(|name| { + all_svcs + .iter() + .filter(|x| x.name() == *name) + .next() + .cloned() + }); + // TOOD: Use the path to find the service instead of the name. This is difficult with multiple roots. + // .filter_map(|path| { + // let absolute_path = svc_path.join(path); + // all_svcs + // .iter() + // .filter(|x| x.path() == absolute_path) + // .next() + // .cloned() + // }); + + dep_ctxs.extend(svcs); + } + + // Inherit dependencies from the service that was overridden. + if let Some(overriden_svc) = &self.overridden_service { + dep_ctxs.extend(overriden_svc.dependencies().await); + } + dep_ctxs } @@ -691,7 +759,7 @@ impl ServiceContextData { env.push(( "TOKIO_WORKER_THREADS".into(), match ns_service_config.resources.cpu { - config::ns::CpuResources::CpuCores(cores) => cores.max(2), + config::ns::CpuResources::CpuCores(cores) => cores.max(cores), config::ns::CpuResources::Cpu(_) => 2, } .to_string(), @@ -719,7 +787,7 @@ impl ServiceContextData { env.push(("TOKIO_CONSOLE_ENABLE".into(), "1".into())); env.push(( "TOKIO_CONSOLE_BIND".into(), - r#"0.0.0.0:{{env "NOMAD_PORT_tokio_console"}}"#.into(), + r#"0.0.0.0:${NOMAD_PORT_tokio-console}"#.into(), )); } @@ -1219,7 +1287,7 @@ impl ServiceContextData { } ); - let service = project_ctx + let mut service = project_ctx .ns() .services .get(&self.name()) @@ -1235,7 +1303,7 @@ impl ServiceContextData { }, }, config::ns::ClusterKind::Distributed { .. } => config::ns::Service { - count: if is_singleton { 1 } else { 2 }, + count: 2, resources: config::ns::ServiceResources { cpu: config::ns::CpuResources::Cpu(250), memory: 256, @@ -1244,8 +1312,9 @@ impl ServiceContextData { }, }); + // Force single count if singleton if is_singleton { - assert_eq!(service.count, 1) + service.count = 1; } service diff --git a/lib/bolt/core/src/dep/cargo/cli.rs b/lib/bolt/core/src/dep/cargo/cli.rs index 638147008e..b17ae8681e 100644 --- a/lib/bolt/core/src/dep/cargo/cli.rs +++ b/lib/bolt/core/src/dep/cargo/cli.rs @@ -116,7 +116,7 @@ pub async fn build<'a, T: AsRef>(ctx: &ProjectContext, opts: BuildOpts<'a, cmd.arg("--rm") .arg("--interactive") .arg("--tty") - .arg("clux/muslrust:1.65.0-stable"); + .arg("clux/muslrust:1.71.1-stable"); cmd.arg("sh").arg("-c").arg(indoc::formatdoc!( r#" # HACK: Link musl-g++ diff --git a/lib/bolt/core/src/dep/nomad/gen.rs b/lib/bolt/core/src/dep/nomad/gen.rs index b7b52ace76..a6c7f972a3 100644 --- a/lib/bolt/core/src/dep/nomad/gen.rs +++ b/lib/bolt/core/src/dep/nomad/gen.rs @@ -8,7 +8,7 @@ use crate::{ ns::LoggingProvider, service::{ServiceDomain, ServiceKind, ServiceRouter}, }, - context::{BuildContext, ProjectContext, RunContext, ServiceContext}, + context::{BuildContext, ProjectContext, RunContext, S3Provider, ServiceContext}, dep::nomad::job_schema::*, }; @@ -25,11 +25,13 @@ pub enum ExecServiceDriver { }, UploadedBinaryArtifact { artifact_key: String, + /// Path to the executable within the archive. + exec_path: String, args: Vec, }, LocalBinaryArtifact { - /// Path relative to the project root. - path: PathBuf, + /// Path to the executable relative to the project root. + exec_path: PathBuf, args: Vec, }, } @@ -183,32 +185,32 @@ pub async fn gen_svc(region_id: &str, exec_ctx: &ExecServiceContext) -> Job { name: Some("svc".into()), // TODO: Add autoscaling count: Some(ns_service_config.count as i64), - update: if enable_update { - Some( - // Wait for services to be healthy before progressing deploy - if has_health { - Update { - max_parallel: Some(1), - health_check: Some("checks".to_owned()), - min_healthy_time: Some(chrono::secs(10)), - healthy_deadline: Some(chrono::min(5)), - progress_deadline: Some(chrono::min(10)), - auto_revert: Some(true), - canary: Some(0), - stagger: Some(chrono::secs(30)), - ..Default::default() - } - } else { - // Just monitor the task status - Update { - health_check: Some("task_states".into()), - ..Default::default() - } - }, - ) - } else { - None - }, + // update: if enable_update { + // Some( + // // Wait for services to be healthy before progressing deploy + // if has_health { + // Update { + // max_parallel: Some(1), + // health_check: Some("checks".to_owned()), + // min_healthy_time: Some(chrono::secs(10)), + // healthy_deadline: Some(chrono::min(5)), + // progress_deadline: Some(chrono::min(10)), + // auto_revert: Some(true), + // canary: Some(0), + // stagger: Some(chrono::secs(30)), + // ..Default::default() + // } + // } else { + // // Just monitor the task status + // Update { + // health_check: Some("task_states".into()), + // ..Default::default() + // } + // }, + // ) + // } else { + // None + // }, reschedule_policy: Some(ReschedulePolicy { delay: Some(chrono::secs(30)), delay_function: Some("constant".into()), @@ -268,15 +270,15 @@ pub async fn gen_svc(region_id: &str, exec_ctx: &ExecServiceContext) -> Job { let mut checks = Vec::new(); // Require a healthy health check before booting - let interval = chrono::secs(15); - let on_update = "require_healthy"; + let interval = chrono::secs(5); + let on_update = "ignore"; checks.push(Check { name: Some("Health Server Liveness".into()), check_type: Some("http".into()), port_label: Some("health".into()), path: Some("/health/liveness".into()), - interval: Some(chrono::secs(15)), + interval: Some(chrono::secs(5)), timeout: Some(chrono::secs(5)), on_update: Some(on_update.into()), // This indicates the runtime might @@ -286,13 +288,20 @@ pub async fn gen_svc(region_id: &str, exec_ctx: &ExecServiceContext) -> Job { // // Ignore in staging since we have // `on_update` set to `ignore`. - check_restart: Some(CheckRestart { - limit: Some(3), - ..Default::default() - }), + // check_restart: Some(CheckRestart { + // limit: Some(3), + // ..Default::default() + // }), ..Default::default() }); + checks.push(build_conn_check( + "Cockroach", + "/health/crdb/db-user", + interval, + on_update, + )); + checks.push(build_conn_check( "Nats Connection", "/health/nats", @@ -425,19 +434,19 @@ pub async fn gen_svc(region_id: &str, exec_ctx: &ExecServiceContext) -> Job { "logging": nomad_loki_plugin_config(&project_ctx, &svc_ctx).await.unwrap(), }) } - ExecServiceDriver::LocalBinaryArtifact { path, args } => { + ExecServiceDriver::LocalBinaryArtifact { exec_path, args } => { json!({ "image": "alpine:3.18", "args": args, - "command": Path::new("/var/rivet/backend").join(path), + "command": Path::new("/var/rivet/backend").join(exec_path), "auth": nomad_docker_io_auth(&project_ctx).await.unwrap(), "logging": nomad_loki_plugin_config(&project_ctx, &svc_ctx).await.unwrap(), }) } - ExecServiceDriver::UploadedBinaryArtifact { args, .. } => { + ExecServiceDriver::UploadedBinaryArtifact { exec_path, args, .. } => { json!({ "image": "alpine:3.18", - "command": format!("${{NOMAD_TASK_DIR}}/build/{}", svc_ctx.name()), + "command": format!("${{NOMAD_TASK_DIR}}/build/{exec_path}"), "args": args, "auth": nomad_docker_io_auth(&project_ctx).await.unwrap(), "logging": nomad_loki_plugin_config(&project_ctx, &svc_ctx).await.unwrap(), @@ -469,15 +478,28 @@ pub async fn gen_svc(region_id: &str, exec_ctx: &ExecServiceContext) -> Job { let s3_config = project_ctx.s3_config(default_provider).await.unwrap(); let s3_creds = project_ctx.s3_credentials(default_provider).await.unwrap(); + // The getter source is not a standard URL, so we have to hardcode it + // ourselves. + // + // Using the region in the domain causes it to throw an invalid URL error. + let getter_source = match default_provider { + S3Provider::Aws => { + format!("s3::https://s3.amazonaws.com/{bucket}/{artifact_key}") + } + S3Provider::Backblaze => { + format!( + "s3::{endpoint}/{bucket}/{key}", + endpoint = s3_config.endpoint_external, + key = urlencoding::encode(artifact_key), + ) + } + _ => todo!(), + }; + Some(json!([ { "GetterMode": "dir", - "GetterSource": format!( - "s3::{endpoint}/{bucket}/{key}", - endpoint = s3_config.endpoint_internal, - bucket = bucket, - key = urlencoding::encode(artifact_key), - ), + "GetterSource": getter_source, "GetterOptions": { "region": s3_config.region, "aws_access_key_id": s3_creds.access_key_id, diff --git a/lib/bolt/core/src/dep/salt/cli.rs b/lib/bolt/core/src/dep/salt/cli.rs index 2c2cc8fa55..b11518fa78 100644 --- a/lib/bolt/core/src/dep/salt/cli.rs +++ b/lib/bolt/core/src/dep/salt/cli.rs @@ -31,7 +31,19 @@ pub async fn apply( let mut event = utils::telemetry::build_event(ctx, "bolt_salt_apply").await?; event.insert_prop("filter", filter)?; event.insert_prop("sls", &opts.sls)?; - utils::telemetry::capture_event(ctx, event).await?; + utils::telemetry::capture_event(ctx, event)?; + + // Install rsync + if let config::ns::ClusterKind::Distributed { .. } = ctx.ns().cluster.kind { + eprintln!(); + rivet_term::status::progress("Installing rsync on Salt Master", ""); + tasks::ssh::pool( + &ctx, + "salt_master", + Some("if ! which rsync; then apt update -y && apt install -y rsync; fi"), + ) + .await?; + } // Write Salt configs eprintln!(); @@ -59,19 +71,22 @@ pub async fn apply( } config::ns::ClusterKind::Distributed { .. } => { tokio::try_join!( - // /srv/salt - async { rsync_dir(ctx, &ctx.salt_path().join("salt"), "/srv/salt").await }, - // /srv/pillar - async { rsync_dir(ctx, &ctx.salt_path().join("pillar"), "/srv/pillar").await }, - // /srv/rivet-nix async { + // /srv/salt + rsync_dir(ctx, &ctx.salt_path().join("salt"), "/srv/salt").await?; + + // /srv/salt/nix/files/source rsync_dir( ctx, - &ctx.salt_path().join("pillar"), + &ctx.path().join("infra").join("nix"), "/srv/salt/nix/files/source", ) - .await + .await?; + + Ok(()) }, + // /srv/pillar + async { rsync_dir(ctx, &ctx.salt_path().join("pillar"), "/srv/pillar").await }, // /srv/salt-context async { let tmp_dir = tempfile::TempDir::new()?; diff --git a/lib/bolt/core/src/dep/salt/secrets.rs b/lib/bolt/core/src/dep/salt/secrets.rs index 89ae47c0a6..816161efb1 100644 --- a/lib/bolt/core/src/dep/salt/secrets.rs +++ b/lib/bolt/core/src/dep/salt/secrets.rs @@ -29,13 +29,15 @@ pub async fn build_secrets(ctx: &ProjectContext) -> Result { }, }); - secrets["minio"] = json!({ - "users": { - "root": { - "password": ctx.read_secret(&["minio", "users", "root", "password"]).await?, + if ctx.ns().s3.providers.minio.is_some() { + secrets["minio"] = json!({ + "users": { + "root": { + "password": ctx.read_secret(&["minio", "users", "root", "password"]).await?, + }, }, - }, - }); + }); + } if let (Some(client_id), Some(client_secret)) = ( ctx.read_secret_opt(&["cloudflare", "access", "proxy", "client_id"]) diff --git a/lib/bolt/core/src/dep/terraform/cli.rs b/lib/bolt/core/src/dep/terraform/cli.rs index 44b03e35a7..0534aa6b1f 100644 --- a/lib/bolt/core/src/dep/terraform/cli.rs +++ b/lib/bolt/core/src/dep/terraform/cli.rs @@ -100,7 +100,7 @@ pub async fn apply( ) -> Result<()> { let mut event = utils::telemetry::build_event(ctx, "bolt_terraform_apply").await?; event.insert_prop("plan_id", plan_id)?; - utils::telemetry::capture_event(ctx, event).await?; + utils::telemetry::capture_event(ctx, event)?; let mut cmd = build_command(ctx, plan_id).await; cmd.arg("apply") @@ -117,7 +117,7 @@ pub async fn apply( pub async fn destroy(ctx: &ProjectContext, plan_id: &str, varfile_path: &Path) -> Result<()> { let mut event = utils::telemetry::build_event(ctx, "bolt_terraform_destroy").await?; event.insert_prop("plan_id", plan_id)?; - utils::telemetry::capture_event(ctx, event).await?; + utils::telemetry::capture_event(ctx, event)?; let mut cmd = build_command(&ctx, plan_id).await; cmd.arg("destroy") diff --git a/lib/bolt/core/src/dep/terraform/pools.rs b/lib/bolt/core/src/dep/terraform/pools.rs index f6c563938f..bf40951553 100644 --- a/lib/bolt/core/src/dep/terraform/pools.rs +++ b/lib/bolt/core/src/dep/terraform/pools.rs @@ -186,18 +186,8 @@ pub async fn build_pools(ctx: &ProjectContext) -> Result> ); let mut svc_roles = vec!["docker", "nomad-client", "consul-client"]; - // Add logging roles - if ctx.ns().logging.is_some() - && ctx - .read_secret_opt(&["cloudflare", "access", "proxy", "client_id"]) - .await? - .is_some() - && ctx - .read_secret_opt(&["cloudflare", "access", "proxy", "client_secret"]) - .await? - .is_some() - { - svc_roles.extend(["traefik-cloudflare-proxy", "docker-plugin-loki"]); + if ctx.ns().logging.is_some() { + svc_roles.extend(["traefik", "cloudflare-proxy", "docker-plugin-loki"]); } pools.insert( "svc".into(), @@ -469,7 +459,7 @@ pub async fn build_pools(ctx: &ProjectContext) -> Result> pools.insert( "ing-px".into(), PoolBuilder::default() - .roles(vec!["traefik", "consul-client"]) + .roles(vec!["traefik", "ingress-proxy", "consul-client"]) .vpc(true) .local_mode(PoolLocalMode::Locally) .tunnels(hashmap! { @@ -549,7 +539,7 @@ pub async fn build_pools(ctx: &ProjectContext) -> Result> pools.insert( "ing-job".into(), PoolBuilder::default() - .roles(vec!["traefik"]) + .roles(vec!["traefik", "ingress-proxy"]) .vpc(false) .local_mode(PoolLocalMode::Keep) .tunnels(hashmap! { @@ -659,7 +649,7 @@ pub async fn build_pools(ctx: &ProjectContext) -> Result> }, FirewallRule { label: "nomad-dynamic-udp".into(), - ports: "20000-25999".into(), + ports: "20000-31999".into(), protocol: "udp".into(), inbound_ipv4_cidr: vec!["0.0.0.0/0".into()], inbound_ipv6_cidr: vec!["::/0".into()], diff --git a/lib/bolt/core/src/tasks/api.rs b/lib/bolt/core/src/tasks/api.rs index 772ade07ee..812586cfae 100644 --- a/lib/bolt/core/src/tasks/api.rs +++ b/lib/bolt/core/src/tasks/api.rs @@ -34,7 +34,7 @@ pub async fn convert_team(project_ctx: &ProjectContext, team_id: String) -> Resu bail!( "failed to convert team ({}):\n{:#?}", response.status().as_u16(), - response.json().await? + response.json::().await? ); } diff --git a/lib/bolt/core/src/tasks/config/generate.rs b/lib/bolt/core/src/tasks/config/generate.rs index ce98108084..2d015e1a93 100644 --- a/lib/bolt/core/src/tasks/config/generate.rs +++ b/lib/bolt/core/src/tasks/config/generate.rs @@ -431,7 +431,7 @@ pub async fn generate(project_path: &Path, ns_id: &str) -> Result<()> { let mut event = utils::telemetry::build_event(&ctx, "bolt_config_generate").await?; event.insert_prop("ns_id", ns_id)?; - utils::telemetry::capture_event(&ctx, event).await?; + utils::telemetry::capture_event(&ctx, event)?; eprintln!(); rivet_term::status::success( diff --git a/lib/bolt/core/src/tasks/infra/migrate/break_infra_terraform_monolith.rs b/lib/bolt/core/src/tasks/infra/migrate/break_infra_terraform_monolith.rs index 6c98b9444b..4f40a56016 100644 --- a/lib/bolt/core/src/tasks/infra/migrate/break_infra_terraform_monolith.rs +++ b/lib/bolt/core/src/tasks/infra/migrate/break_infra_terraform_monolith.rs @@ -21,10 +21,10 @@ pub async fn run(ctx: &ProjectContext) -> Result<()> { crate::tasks::gen::generate_project(&ctx).await; migrate_nebula(ctx).await?; migrate_master_cluster(ctx).await?; - // migrate_pools(ctx).await?; - // migrate_dns(ctx).await?; - // migrate_cloudflare_workers(ctx).await?; - // migrate_cloudflare_tunnels(ctx).await?; + migrate_pools(ctx).await?; + migrate_dns(ctx).await?; + migrate_cloudflare_workers(ctx).await?; + migrate_cloudflare_tunnels(ctx).await?; migrate_s3(ctx).await?; Ok(()) } @@ -429,14 +429,14 @@ async fn migrate_dns(ctx: &ProjectContext) -> Result<()> { ) .await?; - copy_resource( - ctx, - &src_infra, - (None, "managed", "cloudflare_certificate_pack", "rivet_game"), - &mut dst, - (None, "managed", "cloudflare_certificate_pack", "rivet_game"), - ) - .await?; + // copy_resource( + // ctx, + // &src_infra, + // (None, "managed", "cloudflare_certificate_pack", "rivet_game"), + // &mut dst, + // (None, "managed", "cloudflare_certificate_pack", "rivet_game"), + // ) + // .await?; copy_resource( ctx, diff --git a/lib/bolt/core/src/tasks/infra/mod.rs b/lib/bolt/core/src/tasks/infra/mod.rs index 33df4a785d..bb9f529988 100644 --- a/lib/bolt/core/src/tasks/infra/mod.rs +++ b/lib/bolt/core/src/tasks/infra/mod.rs @@ -16,7 +16,13 @@ pub struct ExecutePlanOpts { } #[derive(Debug, Clone)] -pub enum PlanStep { +pub struct PlanStep { + pub name_id: &'static str, + pub kind: PlanStepKind, +} + +#[derive(Debug, Clone)] +pub enum PlanStepKind { Terraform { plan_id: String, @@ -38,10 +44,10 @@ pub enum PlanStep { Up, } -impl PlanStep { +impl PlanStepKind { async fn execute(&self, ctx: ProjectContext, opts: &ExecutePlanOpts) -> Result<()> { match self { - PlanStep::Terraform { plan_id, .. } => { + PlanStepKind::Terraform { plan_id, .. } => { let varfile_path = ctx.gen_tf_env_path(); let mut cmd = terraform::cli::build_command(&ctx, plan_id).await; @@ -55,7 +61,7 @@ impl PlanStep { terraform::output::clear_cache(&ctx, &plan_id).await; } - PlanStep::Salt { + PlanStepKind::Salt { filter, sls, config_opts, @@ -70,10 +76,10 @@ impl PlanStep { salt::cli::apply_all(&ctx, &apply_opts, config_opts).await?; } } - PlanStep::Migrate => { + PlanStepKind::Migrate => { tasks::migrate::up_all(&ctx).await?; } - PlanStep::Up => { + PlanStepKind::Up => { tasks::up::up_all( &ctx, tasks::up::UpOpts { @@ -90,7 +96,7 @@ impl PlanStep { async fn destroy(&self, ctx: ProjectContext, opts: &ExecutePlanOpts) -> Result<()> { match self { - PlanStep::Terraform { + PlanStepKind::Terraform { plan_id, needs_destroy, } => { @@ -111,7 +117,7 @@ impl PlanStep { terraform::output::clear_cache(&ctx, &plan_id).await; } - PlanStep::Salt { .. } | PlanStep::Migrate | PlanStep::Up => { + PlanStepKind::Salt { .. } | PlanStepKind::Migrate | PlanStepKind::Up => { // Do nothing } } @@ -120,70 +126,97 @@ impl PlanStep { } } -pub fn build_plan(ctx: &ProjectContext) -> Result> { +pub fn build_plan(ctx: &ProjectContext, start_at: Option) -> Result> { let mut plan = Vec::new(); // TLS - plan.push(PlanStep::Terraform { - plan_id: "tls".into(), - needs_destroy: true, + plan.push(PlanStep { + name_id: "tf-tls", + kind: PlanStepKind::Terraform { + plan_id: "tls".into(), + needs_destroy: true, + }, }); // Nebula - plan.push(PlanStep::Terraform { - plan_id: "nebula".into(), - needs_destroy: false, + plan.push(PlanStep { + name_id: "tf-nebula", + kind: PlanStepKind::Terraform { + plan_id: "nebula".into(), + needs_destroy: false, + }, }); // Master match ctx.ns().cluster.kind { ClusterKind::SingleNode { .. } => { - plan.push(PlanStep::Terraform { - plan_id: "master_local".into(), - needs_destroy: false, + plan.push(PlanStep { + name_id: "tf-master-local", + kind: PlanStepKind::Terraform { + plan_id: "master_local".into(), + needs_destroy: false, + }, }); } ClusterKind::Distributed { .. } => { - plan.push(PlanStep::Terraform { - plan_id: "master_cluster".into(), - needs_destroy: true, + plan.push(PlanStep { + name_id: "tf-master-cluster", + kind: PlanStepKind::Terraform { + plan_id: "master_cluster".into(), + needs_destroy: true, + }, }); } } // Pools - plan.push(PlanStep::Terraform { - plan_id: "pools".into(), - needs_destroy: true, + plan.push(PlanStep { + name_id: "tf-pools", + kind: PlanStepKind::Terraform { + plan_id: "pools".into(), + needs_destroy: true, + }, }); // DNS - plan.push(PlanStep::Terraform { - plan_id: "dns".into(), - needs_destroy: true, + plan.push(PlanStep { + name_id: "tf-dns", + kind: PlanStepKind::Terraform { + plan_id: "dns".into(), + needs_destroy: true, + }, }); // Cloudflare - plan.push(PlanStep::Terraform { - plan_id: "cloudflare_workers".into(), - needs_destroy: true, + plan.push(PlanStep { + name_id: "tf-cf-workers", + kind: PlanStepKind::Terraform { + plan_id: "cloudflare_workers".into(), + needs_destroy: true, + }, }); if let config::ns::DnsProvider::Cloudflare { access: Some(_), .. } = ctx.ns().dns.provider { - plan.push(PlanStep::Terraform { - plan_id: "cloudflare_tunnels".into(), - needs_destroy: true, + plan.push(PlanStep { + name_id: "tf-cf-tunnels", + kind: PlanStepKind::Terraform { + plan_id: "cloudflare_tunnels".into(), + needs_destroy: true, + }, }); } // Grafana if ctx.ns().grafana.is_some() { - plan.push(PlanStep::Terraform { - plan_id: "grafana".into(), - needs_destroy: true, + plan.push(PlanStep { + name_id: "tf-grafana", + kind: PlanStepKind::Terraform { + plan_id: "grafana".into(), + needs_destroy: true, + }, }); } @@ -191,55 +224,89 @@ pub fn build_plan(ctx: &ProjectContext) -> Result> { let s3_providers = &ctx.ns().s3.providers; if s3_providers.minio.is_some() { // Install Minio for s3_minio Terraform plan - plan.push(PlanStep::Salt { - filter: Some("G@roles:minio".into()), - sls: None, - config_opts: salt::config::BuildOpts { skip_s3: true }, + plan.push(PlanStep { + name_id: "salt-minio", + kind: PlanStepKind::Salt { + filter: Some("G@roles:minio".into()), + sls: None, + config_opts: salt::config::BuildOpts { skip_s3: true }, + }, }); - plan.push(PlanStep::Terraform { - plan_id: "s3_minio".into(), - needs_destroy: false, + plan.push(PlanStep { + name_id: "tf-s3-minio", + kind: PlanStepKind::Terraform { + plan_id: "s3_minio".into(), + needs_destroy: false, + }, }); } if s3_providers.backblaze.is_some() { - plan.push(PlanStep::Terraform { - plan_id: "s3_backblaze".into(), - needs_destroy: true, + plan.push(PlanStep { + name_id: "tf-s3-backblaze", + kind: PlanStepKind::Terraform { + plan_id: "s3_backblaze".into(), + needs_destroy: true, + }, }); } if s3_providers.aws.is_some() { - plan.push(PlanStep::Terraform { - plan_id: "s3_aws".into(), - needs_destroy: true, + plan.push(PlanStep { + name_id: "tf-s3-aws", + kind: PlanStepKind::Terraform { + plan_id: "s3_aws".into(), + needs_destroy: true, + }, }); } // Apply the rest of the Salt configs - plan.push(PlanStep::Salt { - filter: None, - sls: None, - config_opts: Default::default(), + plan.push(PlanStep { + name_id: "salt", + kind: PlanStepKind::Salt { + filter: None, + sls: None, + config_opts: Default::default(), + }, }); - plan.push(PlanStep::Terraform { - plan_id: "nomad".into(), - needs_destroy: false, + plan.push(PlanStep { + name_id: "tf-nomad", + kind: PlanStepKind::Terraform { + plan_id: "nomad".into(), + needs_destroy: false, + }, }); - plan.push(PlanStep::Migrate); + plan.push(PlanStep { + name_id: "migrate", + kind: PlanStepKind::Migrate, + }); - plan.push(PlanStep::Up); + plan.push(PlanStep { + name_id: "up", + kind: PlanStepKind::Up, + }); + + // Start at the specified step + if let Some(start_at) = start_at { + let idx = plan + .iter() + .position(|x| x.name_id == start_at) + .ok_or_else(|| anyhow!("invalid start_at value: {}", start_at))?; + + plan = plan[idx..].to_vec(); + } Ok(plan) } /// List all of the Terraform plans in use for the generated plan. pub fn all_terraform_plans(ctx: &ProjectContext) -> Result> { - let plan_ids = build_plan(ctx)? + let plan_ids = build_plan(ctx, None)? .into_iter() .flat_map(|x| { - if let PlanStep::Terraform { plan_id, .. } = x { + if let PlanStepKind::Terraform { plan_id, .. } = x.kind { Some(plan_id) } else { None @@ -260,8 +327,11 @@ pub async fn execute_plan( for (i, step) in plan.iter().enumerate() { eprintln!(); eprintln!(); - rivet_term::status::info("Executing", format!("({}/{}) {step:?}", i + 1, plan.len())); - step.execute(ctx.clone(), &opts).await?; + rivet_term::status::info( + "Executing", + format!("({}/{}) {}", i + 1, plan.len(), step.name_id), + ); + step.kind.execute(ctx.clone(), &opts).await?; } Ok(()) @@ -277,8 +347,11 @@ pub async fn destroy_plan( for (i, step) in plan.iter().enumerate().rev() { eprintln!(); eprintln!(); - rivet_term::status::info("Destroying", format!("({}/{}) {step:?}", i + 1, plan.len())); - step.destroy(ctx.clone(), &opts).await?; + rivet_term::status::info( + "Destroying", + format!("({}/{}) {}", i + 1, plan.len(), step.name_id), + ); + step.kind.destroy(ctx.clone(), &opts).await?; } Ok(()) diff --git a/lib/bolt/core/src/tasks/up.rs b/lib/bolt/core/src/tasks/up.rs index 833a65354a..fa37e0d46c 100644 --- a/lib/bolt/core/src/tasks/up.rs +++ b/lib/bolt/core/src/tasks/up.rs @@ -65,7 +65,7 @@ pub async fn up_services>( opts: UpOpts, ) -> Result> { let event = utils::telemetry::build_event(ctx, "bolt_up").await?; - utils::telemetry::capture_event(ctx, event).await?; + utils::telemetry::capture_event(ctx, event)?; // let run_context = RunContext::Service; let build_context = BuildContext::Bin { @@ -260,16 +260,21 @@ pub async fn up_services>( svc_ctx: svc_ctx.clone().clone(), build_context, driver: match &build_plan { - ServiceBuildPlan::ExistingLocalBuild { output_path } - | ServiceBuildPlan::BuildLocally { output_path } => { - derive_local_build_driver(svc_ctx, output_path.clone()).await + ServiceBuildPlan::ExistingLocalBuild { exec_path } + | ServiceBuildPlan::BuildLocally { exec_path } => { + derive_local_build_driver(svc_ctx, exec_path.clone()).await } ServiceBuildPlan::ExistingUploadedBuild { build_key: artifact_key, + exec_path, } | ServiceBuildPlan::BuildAndUpload { build_key: artifact_key, - } => derive_uploaded_svc_driver(svc_ctx, artifact_key.clone()).await, + exec_path, + } => { + derive_uploaded_svc_driver(svc_ctx, artifact_key.clone(), exec_path.clone()) + .await + } ServiceBuildPlan::Docker { image_tag } => ExecServiceDriver::Docker { image: image_tag.clone(), force_pull: false, @@ -395,12 +400,12 @@ async fn build_svc(svc_ctx: &ServiceContext, optimization: BuildOptimization) { async fn derive_local_build_driver( svc_ctx: &ServiceContext, - output_path: PathBuf, + exec_path: PathBuf, ) -> ExecServiceDriver { match &svc_ctx.config().runtime { RuntimeKind::Rust {} => ExecServiceDriver::LocalBinaryArtifact { // Convert path to be relative to the project root - path: output_path + exec_path: exec_path .strip_prefix(svc_ctx.project().await.path()) .expect("rust binary path not inside of project dir") .to_owned(), @@ -419,10 +424,12 @@ async fn derive_local_build_driver( async fn derive_uploaded_svc_driver( svc_ctx: &ServiceContext, artifact_key: String, + exec_path: String, ) -> ExecServiceDriver { match &svc_ctx.config().runtime { RuntimeKind::Rust {} => ExecServiceDriver::UploadedBinaryArtifact { artifact_key, + exec_path, args: Vec::new(), }, RuntimeKind::CRDB { .. } diff --git a/lib/bolt/core/src/utils/telemetry.rs b/lib/bolt/core/src/utils/telemetry.rs index 899e53d487..f2f868a2fb 100644 --- a/lib/bolt/core/src/utils/telemetry.rs +++ b/lib/bolt/core/src/utils/telemetry.rs @@ -92,9 +92,14 @@ pub async fn build_event(ctx: &ProjectContext, name: &str) -> Result Result<()> { +pub fn capture_event(ctx: &ProjectContext, event: async_posthog::Event) -> Result<()> { if !ctx.ns().rivet.telemetry.disable { - build_client().capture(event).await?; + tokio::spawn(async move { + match build_client().capture(event).await { + Ok(_) => {} + Err(err) => println!("Failed to capture event: {err:?}"), + } + }); } Ok(()) diff --git a/lib/cache/build/Cargo.toml b/lib/cache/build/Cargo.toml index 36ab1b569e..a84d4a99b0 100644 --- a/lib/cache/build/Cargo.toml +++ b/lib/cache/build/Cargo.toml @@ -15,7 +15,7 @@ rivet-pools = { path = "../../pools" } rivet-util = { path = "../../util/core" } serde = { version = "1.0", features = ["derive"] } thiserror = "1.0" -tokio = { version = "1.21", features = ["full"] } +tokio = { version = "1.29", features = ["full"] } tracing = "0.1" types = { path = "../../types/core" } uuid = { version = "1", features = ["v4"] } diff --git a/lib/chirp/client/Cargo.toml b/lib/chirp/client/Cargo.toml index f58f4dac4b..692b5e6f98 100644 --- a/lib/chirp/client/Cargo.toml +++ b/lib/chirp/client/Cargo.toml @@ -19,7 +19,7 @@ rivet-pools = { path = "../../pools" } rivet-util = { path = "../../util/core" } serde = { version = "1.0", features = ["derive"] } thiserror = "1.0" -tokio = { version = "1.21", features = ["full"] } +tokio = { version = "1.29", features = ["full"] } tokio-util = "0.6" tracing = "0.1" types = { path = "../../types/core" } diff --git a/lib/chirp/client/src/client.rs b/lib/chirp/client/src/client.rs index f6cd7ac023..09a79e8a8b 100644 --- a/lib/chirp/client/src/client.rs +++ b/lib/chirp/client/src/client.rs @@ -65,12 +65,12 @@ impl SharedClient { redis_cache: RedisPool, region: String, ) -> SharedClientHandle { - let spawn_res = tokio::task::Builder::new() - .name("chirp_client::metrics_update_update") - .spawn(metrics::start_update_uptime()); - if let Err(err) = spawn_res { - tracing::error!(?err, "failed to spawn user_presence_touch task"); - } + // let spawn_res = tokio::task::Builder::new() + // .name("chirp_client::metrics_update_update") + // .spawn(metrics::start_update_uptime()); + // if let Err(err) = spawn_res { + // tracing::error!(?err, "failed to spawn user_presence_touch task"); + // } Arc::new(SharedClient { nats, @@ -553,6 +553,12 @@ impl Client { .map_err(|x| ClientError::CreateSubscription(x.into()))?; // Manually publish message + tracing::trace!( + ?subject, + ?reply, + req_len = req_buf.len(), + "publishing rpc call to nats" + ); self.nats .publish_with_reply_and_headers( subject.clone(), @@ -768,86 +774,86 @@ impl Client { // Write message to Redis stream let span = self.perf().start(M::PERF_LABEL_WRITE_STREAM).await; - let mut backoff = rivet_util::Backoff::default_infinite(); - loop { - // Ignore for infinite backoff - backoff.tick().await; + // let mut backoff = rivet_util::Backoff::default_infinite(); + // loop { + // // Ignore for infinite backoff + // backoff.tick().await; - let mut conn = self.redis_chirp.clone(); - - let mut pipe = redis::pipe(); - pipe.atomic(); + let mut conn = self.redis_chirp.clone(); - // Write to stream - let topic_key = redis_keys::message_topic(M::NAME); - pipe.xadd_maxlen( - &topic_key, - redis::streams::StreamMaxlen::Approx(8192), - "*", - &[("m", &message_buf)], - ) - .ignore(); + let mut pipe = redis::pipe(); + pipe.atomic(); - // Write tails for all permuted parameters - for wildcard_parameters in &permuted_wildcard_parameters { - // Write tail - if let Some(ttl) = M::TAIL_TTL { - // Write single tail message + // Write to stream + let topic_key = redis_keys::message_topic(M::NAME); + pipe.xadd_maxlen( + &topic_key, + redis::streams::StreamMaxlen::Approx(8192), + "*", + &[("m", &message_buf)], + ) + .ignore(); + + // Write tails for all permuted parameters + for wildcard_parameters in &permuted_wildcard_parameters { + // Write tail + if let Some(ttl) = M::TAIL_TTL { + // Write single tail message + + let tail_key = redis_keys::message_tail::(wildcard_parameters); + + // Save message + pipe.hset( + &tail_key, + redis_keys::message_tail::REQUEST_ID, + req_id.to_string(), + ) + .ignore(); + pipe.hset(&tail_key, redis_keys::message_tail::TS, ts) + .ignore(); + pipe.hset(&tail_key, redis_keys::message_tail::BODY, message_buf) + .ignore(); - let tail_key = redis_keys::message_tail::(wildcard_parameters); + // Automatically expire + pipe.expire(&tail_key, ttl as usize).ignore(); + + // Write history + if M::HISTORY { + let history_key = redis_keys::message_history::(wildcard_parameters); + + // Remove old entries 10% of the time. + // + // This is a slow operation, so we perform this + // sparingly. + if rand::thread_rng().gen_bool(0.1) { + pipe.cmd("ZREMRANGEBYSCORE") + .arg(&history_key) + .arg("-inf") + .arg(rivet_util::timestamp::now() - ttl * 1000) + .ignore(); + } // Save message - pipe.hset( - &tail_key, - redis_keys::message_tail::REQUEST_ID, - req_id.to_string(), - ) - .ignore(); - pipe.hset(&tail_key, redis_keys::message_tail::TS, ts) - .ignore(); - pipe.hset(&tail_key, redis_keys::message_tail::BODY, message_buf) - .ignore(); + pipe.zadd(&history_key, message_buf, ts).ignore(); // Automatically expire - pipe.expire(&tail_key, ttl as usize).ignore(); - - // Write history - if M::HISTORY { - let history_key = redis_keys::message_history::(wildcard_parameters); - - // Remove old entries 10% of the time. - // - // This is a slow operation, so we perform this - // sparingly. - if rand::thread_rng().gen_bool(0.1) { - pipe.cmd("ZREMRANGEBYSCORE") - .arg(&history_key) - .arg("-inf") - .arg(rivet_util::timestamp::now() - ttl * 1000) - .ignore(); - } - - // Save message - pipe.zadd(&history_key, message_buf, ts).ignore(); - - // Automatically expire - pipe.expire(&history_key, ttl as usize).ignore(); - } else { - } + pipe.expire(&history_key, ttl as usize).ignore(); + } else { } } + } - // Write to Redis - match pipe.query_async::<_, ()>(&mut conn).await { - Ok(_) => { - tracing::debug!("write to redis stream succeeded"); - break; - } - Err(err) => { - tracing::error!(?err, "failed to write to redis"); - } + // Write to Redis + match pipe.query_async::<_, ()>(&mut conn).await { + Ok(_) => { + tracing::debug!("write to redis stream succeeded"); + // break; + } + Err(err) => { + tracing::error!(?err, "failed to write to redis"); } } + // } span.end(); } @@ -863,34 +869,39 @@ impl Client { // // Infinite backoff since we want to wait until the service reboots. let span = self.perf().start(M::PERF_LABEL_PUBLISH).await; - let mut backoff = rivet_util::Backoff::default_infinite(); - loop { - // Ignore for infinite backoff - backoff.tick().await; - - let nats_subject = nats_subject.to_owned(); - let message_buf = message_buf.to_vec(); - - if let Err(err) = self - .nats - .publish(nats_subject.clone(), message_buf.into()) - .await - { - tracing::warn!(?err, "publish message failed, trying again"); - continue; - } - - // TODO: Most messages don't need to be flushed immediately. We - // should add an option to enable high performance message - // publishing to enable flushing immediately after publishing. - // if let Err(err) = self.nats.flush().await { - // tracing::error!(?err, "flush message failed, the message probably sent"); - // break; - // } - - tracing::debug!("publish nats message succeeded"); - break; + // let mut backoff = rivet_util::Backoff::default_infinite(); + // loop { + // // Ignore for infinite backoff + // backoff.tick().await; + + let nats_subject = nats_subject.to_owned(); + let message_buf = message_buf.to_vec(); + + tracing::trace!( + ?nats_subject, + message_len = message_buf.len(), + "publishing message to nats" + ); + if let Err(err) = self + .nats + .publish(nats_subject.clone(), message_buf.into()) + .await + { + tracing::warn!(?err, "publish message failed, trying again"); + // continue; } + + // // TODO: Most messages don't need to be flushed immediately. We + // // should add an option to enable high performance message + // // publishing to enable flushing immediately after publishing. + // // if let Err(err) = self.nats.flush().await { + // // tracing::error!(?err, "flush message failed, the message probably sent"); + // // break; + // // } + + // tracing::debug!("publish nats message succeeded"); + // break; + // } span.end(); } diff --git a/lib/chirp/client/src/message.rs b/lib/chirp/client/src/message.rs index 92381f6848..bbe2df5205 100644 --- a/lib/chirp/client/src/message.rs +++ b/lib/chirp/client/src/message.rs @@ -22,6 +22,10 @@ pub fn serialize_message_params(parameters: &[impl AsRef], join: &str) -> S .map(|x| { if x == "*" { x.to_string() + } else if x.is_empty() { + // Provide a null value since NATS requires a valid subject + // TODO: Find a better null placeholder that doesn't conflict with manual value + "__NULL__".to_string() } else { urlencoding::encode(x).to_string() } @@ -35,11 +39,15 @@ where M: Message, S: AsRef, { - format!( - "chirp.msg.{}.{}", - M::NAME, - serialize_message_params(parameters, ".") - ) + if parameters.is_empty() { + format!("chirp.msg.{}", M::NAME) + } else { + format!( + "chirp.msg.{}.{}", + M::NAME, + serialize_message_params(parameters, ".") + ) + } } /// A message received from a Chirp subscription. diff --git a/lib/chirp/perf/Cargo.toml b/lib/chirp/perf/Cargo.toml index b4482c78b0..45a2e10feb 100644 --- a/lib/chirp/perf/Cargo.toml +++ b/lib/chirp/perf/Cargo.toml @@ -12,7 +12,7 @@ types = { path = "../../types/core" } rivet-metrics = { path = "../../metrics" } rivet-pools = { path = "../../pools" } thiserror = "1.0" -tokio = { version = "1.21", features = ["full", "tracing"] } +tokio = { version = "1.29", features = ["full", "tracing"] } tracing = "0.1" [dependencies.uuid] diff --git a/lib/chirp/worker-attributes/src/lib.rs b/lib/chirp/worker-attributes/src/lib.rs index 094d3b58d5..b5073f216e 100644 --- a/lib/chirp/worker-attributes/src/lib.rs +++ b/lib/chirp/worker-attributes/src/lib.rs @@ -97,48 +97,58 @@ pub fn worker(attr: TokenStream, item: TokenStream) -> TokenStream { // Extract the inner request type let ty = match &*pat.ty { - syn::Type::Path(path) => { - let final_segment = path.path.segments.last().unwrap(); - if final_segment.ident != "OperationContext" { - return error( - final_segment.ident.span(), - "argument must be a `OperationContext`", - ); + syn::Type::Reference(syn::TypeReference { + elem: inner_type, + mutability, + .. + }) => { + if let Some(mutability) = mutability { + return error(mutability.span(), "context cannot be mutable"); } - // Read the generic type - match &final_segment.arguments { - syn::PathArguments::AngleBracketed(args) => { - if args.args.len() != 1 { + match &**inner_type { + syn::Type::Path(path) => { + let final_segment = path.path.segments.last().unwrap(); + if final_segment.ident != "OperationContext" { return error( - final_segment.span(), - "must have exactly 1 generic argument", + final_segment.ident.span(), + "argument must be a `OperationContext`", ); } - // Match the correct generic type - match &args.args[0] { - syn::GenericArgument::Type(ty) => ty, - arg => { - return error(arg.span(), "generic argument must be a type"); + // Read the generic type + match &final_segment.arguments { + syn::PathArguments::AngleBracketed(args) => { + if args.args.len() != 1 { + return error( + final_segment.span(), + "must have exactly 1 generic argument", + ); + } + + // Match the correct generic type + match &args.args[0] { + syn::GenericArgument::Type(ty) => ty, + arg => { + return error( + arg.span(), + "generic argument must be a type", + ); + } + } } + _ => return error(final_segment.span(), "invalid generic args"), } } - _ => { - return error(final_segment.span(), "invalid generic args"); - } + _ => return error(pat.ty.span(), "unsupported type"), } } - _ => { - return error(pat.ty.span(), "unsupported type"); - } + _ => return error(pat.ty.span(), "unsupported type, must be a reference"), }; (ident, ty) } - _ => { - return error(input.sig.inputs[0].span(), "invalid function argument"); - } + _ => return error(input.sig.inputs[0].span(), "invalid function argument"), }; // Derive res type @@ -178,9 +188,7 @@ pub fn worker(attr: TokenStream, item: TokenStream) -> TokenStream { } } } - _ => { - return error(final_segment.span(), "invalid generic args"); - } + _ => return error(final_segment.span(), "invalid generic args"), } } _ => return error(ty.span(), "invalid return type"), diff --git a/lib/chirp/worker-attributes/tests/test.rs b/lib/chirp/worker-attributes/tests/test.rs index d5824fc945..cf0a554e4b 100644 --- a/lib/chirp/worker-attributes/tests/test.rs +++ b/lib/chirp/worker-attributes/tests/test.rs @@ -7,7 +7,7 @@ struct TestRequest {} struct TestResponse {} #[chirp_worker_attributes::worker] -async fn worker(ctx: OperationContext) -> GlobalResult { +async fn worker(ctx: &OperationContext) -> GlobalResult { tracing::info!(body = ?req, "hello, world!"); Ok(TestResponse {}) diff --git a/lib/chirp/worker-attributes/tests/test_err.rs b/lib/chirp/worker-attributes/tests/test_err.rs index daf1ff9075..8f5d8d3c18 100644 --- a/lib/chirp/worker-attributes/tests/test_err.rs +++ b/lib/chirp/worker-attributes/tests/test_err.rs @@ -13,7 +13,7 @@ enum TestError { } #[chirp_worker_attributes::worker] -async fn worker(ctx: OperationContext) -> GlobalResult { +async fn worker(ctx: &OperationContext) -> GlobalResult { tracing::info!(body = ?req, "hello, world!"); do_something()?; diff --git a/lib/chirp/worker/Cargo.toml b/lib/chirp/worker/Cargo.toml index 06e1211535..9f82ce0771 100644 --- a/lib/chirp/worker/Cargo.toml +++ b/lib/chirp/worker/Cargo.toml @@ -32,7 +32,7 @@ rivet-runtime = { path = "../../runtime" } rivet-util = { path = "../../util/core" } serde_json = "1.0" thiserror = "1.0" -tokio = { version = "1.21", features = ["full", "tracing"] } +tokio = { version = "1.29", features = ["full", "tracing"] } tracing = "0.1" types = { path = "../../types/core" } tracing-subscriber = { version = "0.3", optional = true, default-features = false, features = ["fmt", "json", "ansi"] } # Used with attribute diff --git a/lib/chirp/worker/src/manager.rs b/lib/chirp/worker/src/manager.rs index 1c7227ba69..340a507936 100644 --- a/lib/chirp/worker/src/manager.rs +++ b/lib/chirp/worker/src/manager.rs @@ -1,6 +1,6 @@ use chirp_metrics as metrics; use futures_util::StreamExt; -use global_error::{GlobalResult, GlobalError}; +use global_error::{GlobalError, GlobalResult}; use prost::Message; use redis::{self, AsyncCommands}; use rivet_connection::Connection; @@ -276,7 +276,7 @@ where .arg(pending_retry_time.as_millis() as i64) .arg("-") .arg("+") - .arg(16usize) + .arg(1usize) .query_async::<_, redis::streams::StreamPendingCountReply>(redis_chirp_conn) .await { @@ -451,7 +451,7 @@ where let read_options = redis::streams::StreamReadOptions::default() .group(&group, &consumer) .block(30_000) - .count(16); + .count(1); let res = match redis_chirp_conn .xread_options::<_, _, redis::streams::StreamReadReply>(keys, &[">"], &read_options) .await @@ -857,36 +857,42 @@ where self: Arc, req: &Request, ) -> GlobalResult { - // Will retry 4 times. This will take a maximum of 15 seconds. - let mut backoff = rivet_util::Backoff::new(5, Some(4), 1_000, 1_000); - loop { - let res = self - .worker - .handle(req.op_ctx()) - .instrument(tracing::info_span!("handle", name = %W::NAME)) - .await; - - // Attempt to retry the request with backoff - if matches!( - res, - Err(GlobalError::Internal { - retry_immediately: true, - .. - }) - ) { - tracing::info!("ticking request retry backoff"); - - if backoff.tick().await { - tracing::warn!("retry request failed too many times"); - return res; - } else { - tracing::info!("retrying request"); - } - } else { - // Return result immediately - return res; - } - } + self.worker + .handle(req.op_ctx()) + .instrument(tracing::info_span!("handle", name = %W::NAME)) + .await + + // // TODO: Add back + // // Will retry 4 times. This will take a maximum of 15 seconds. + // let mut backoff = rivet_util::Backoff::new(5, Some(4), 1_000, 1_000); + // loop { + // let res = self + // .worker + // .handle(req.op_ctx()) + // .instrument(tracing::info_span!("handle", name = %W::NAME)) + // .await; + + // // Attempt to retry the request with backoff + // if matches!( + // res, + // Err(GlobalError::Internal { + // retry_immediately: true, + // .. + // }) + // ) { + // tracing::info!("ticking request retry backoff"); + + // if backoff.tick().await { + // tracing::warn!("retry request failed too many times"); + // return res; + // } else { + // tracing::info!("retrying request"); + // } + // } else { + // // Return result immediately + // return res; + // } + // } } #[tracing::instrument(level = "trace", skip_all)] @@ -1028,11 +1034,11 @@ where #[tracing::instrument] async fn consumer_ack(self: Arc, msg_meta: RedisMessageMeta) { let mut backoff = rivet_util::Backoff::default(); - loop { - if backoff.tick().await { - tracing::error!("acking stream message failed too many times, aborting"); - return; - } + // loop { + // if backoff.tick().await { + // tracing::error!("acking stream message failed too many times, aborting"); + // return; + // } // Acknowledge the messages let mut redis_chirp = self.redis_chirp.clone(); @@ -1042,13 +1048,13 @@ where { Ok(_) => { tracing::info!(?msg_meta, "acknowledged stream message"); - break; + // break; } Err(err) => { tracing::error!(?err, "failed to ack message"); } } - } + // } } } diff --git a/lib/chirp/worker/src/test.rs b/lib/chirp/worker/src/test.rs index a6fe9b9502..18cca88a9e 100644 --- a/lib/chirp/worker/src/test.rs +++ b/lib/chirp/worker/src/test.rs @@ -74,8 +74,4 @@ impl TestCtx { pub async fn redis_user_presence(&self) -> Result { self.op_ctx.redis_user_presence().await } - - pub async fn redis_search(&self) -> Result { - self.op_ctx.redis_search().await - } } diff --git a/lib/connection/src/lib.rs b/lib/connection/src/lib.rs index 24633a1598..588f50390f 100644 --- a/lib/connection/src/lib.rs +++ b/lib/connection/src/lib.rs @@ -86,10 +86,6 @@ impl Connection { self.pools.redis("redis-user-presence") } - pub async fn redis_search(&self) -> Result { - self.pools.redis("redis-search") - } - pub fn perf(&self) -> &chirp_perf::PerfCtx { self.client.perf() } diff --git a/lib/convert/src/convert/identity.rs b/lib/convert/src/convert/identity.rs index 540ea97b9a..bb0d6f87f1 100644 --- a/lib/convert/src/convert/identity.rs +++ b/lib/convert/src/convert/identity.rs @@ -293,14 +293,12 @@ pub fn presence( public_metadata: game_activity .public_metadata .as_ref() - .map(|s| serde_json::from_str(s)) - .transpose()?, + .and_then(|s| serde_json::from_str(s).ok()), mutual_metadata: if is_mutual_following { game_activity .friend_metadata .as_ref() - .map(|s| serde_json::from_str(s)) - .transpose()? + .and_then(|s| serde_json::from_str(s).ok()) } else { None }, diff --git a/lib/convert/src/fetch/identity.rs b/lib/convert/src/fetch/identity.rs index 3146b3998c..38d58766f1 100644 --- a/lib/convert/src/fetch/identity.rs +++ b/lib/convert/src/fetch/identity.rs @@ -275,42 +275,48 @@ async fn games( } async fn teams(ctx: &OperationContext<()>, user_ids: Vec) -> GlobalResult { - let user_teams_res = op!([ctx] user_team_list { - user_ids: user_ids, - }) - .await?; - - let team_ids = user_teams_res - .users - .iter() - .map(|user| { - user.teams - .iter() - .map(|t| Ok(internal_unwrap_owned!(t.team_id))) - .collect::>>() - }) - .collect::>>()? - .into_iter() - .flatten() - .collect::>(); - - let (teams_res, dev_teams_res) = tokio::try_join!( - op!([ctx] team_get { - team_ids: team_ids.clone(), - }), - op!([ctx] team_dev_get { - team_ids: team_ids.clone(), - }), - )?; - - // TODO: hide all closed teams - let teams = teams_res.teams.clone(); - - Ok(TeamsCtx { - user_teams: user_teams_res, - teams, - dev_teams: dev_teams_res, - }) + return Ok(TeamsCtx { + user_teams: user::team_list::Response { users: vec![] }, + teams: vec![], + dev_teams: team_dev::get::Response { teams: vec![] }, + }); + + // let user_teams_res = op!([ctx] user_team_list { + // user_ids: user_ids, + // }) + // .await?; + + // let team_ids = user_teams_res + // .users + // .iter() + // .map(|user| { + // user.teams + // .iter() + // .map(|t| Ok(internal_unwrap_owned!(t.team_id))) + // .collect::>>() + // }) + // .collect::>>()? + // .into_iter() + // .flatten() + // .collect::>(); + + // let (teams_res, dev_teams_res) = tokio::try_join!( + // op!([ctx] team_get { + // team_ids: team_ids.clone(), + // }), + // op!([ctx] team_dev_get { + // team_ids: team_ids.clone(), + // }), + // )?; + + // // TODO: hide all closed teams + // let teams = teams_res.teams.clone(); + + // Ok(TeamsCtx { + // user_teams: user_teams_res, + // teams, + // dev_teams: dev_teams_res, + // }) } async fn follows( @@ -334,23 +340,24 @@ pub async fn mutual_follows( current_user_id: Uuid, raw_user_ids: Vec, ) -> GlobalResult { - // Converts to hashmap to remove duplicate queries - let queries = raw_user_ids - .clone() - .into_iter() - .flat_map(|user_id| [(current_user_id, user_id), (user_id, current_user_id)]) - .collect::>() - .into_iter() - .map(|(user_a_id, user_b_id)| user_follow::get::request::Query { - follower_user_id: Some(user_a_id.into()), - following_user_id: Some(user_b_id.into()), - }) - .collect::>(); - - op!([ctx] user_follow_get { - queries: queries, - }) - .await + return Ok(user_follow::get::Response { follows: vec![] }); + // // Converts to hashmap to remove duplicate queries + // let queries = raw_user_ids + // .clone() + // .into_iter() + // .flat_map(|user_id| [(current_user_id, user_id), (user_id, current_user_id)]) + // .collect::>() + // .into_iter() + // .map(|(user_a_id, user_b_id)| user_follow::get::request::Query { + // follower_user_id: Some(user_a_id.into()), + // following_user_id: Some(user_b_id.into()), + // }) + // .collect::>(); + + // op!([ctx] user_follow_get { + // queries: queries, + // }) + // .await } async fn linked_accounts( diff --git a/lib/convert/src/impls/cloud/version/matchmaker/game_mode.rs b/lib/convert/src/impls/cloud/version/matchmaker/game_mode.rs index 9d1c45412f..7372030317 100644 --- a/lib/convert/src/impls/cloud/version/matchmaker/game_mode.rs +++ b/lib/convert/src/impls/cloud/version/matchmaker/game_mode.rs @@ -4,7 +4,7 @@ use proto::backend::{self, pkg::*}; use rivet_api::models; use rivet_operation::prelude::*; -use crate::{ApiInto, ApiTryFrom, ApiTryInto}; +use crate::{ApiFrom, ApiInto, ApiTryFrom, ApiTryInto}; pub fn game_mode_to_proto( name_id: String, @@ -139,8 +139,25 @@ pub fn game_mode_to_proto( max_players_normal: max_players_normal.try_into()?, max_players_direct: max_players_direct.try_into()?, max_players_party: max_players_party.try_into()?, + listable: game_mode.listable.unwrap_or(true), runtime, + + find_config: game_mode + .find_config + .clone() + .map(|x| ApiTryInto::try_into(*x)) + .transpose()?, + join_config: game_mode + .join_config + .clone() + .map(|x| ApiTryInto::try_into(*x)) + .transpose()?, + create_config: game_mode + .create_config + .clone() + .map(|x| ApiTryInto::try_into(*x)) + .transpose()?, }) } @@ -234,9 +251,26 @@ pub fn game_mode_to_openapi( max_players: Some(value.max_players_normal.try_into()?), max_players_direct: Some(value.max_players_direct.try_into()?), max_players_party: Some(value.max_players_party.try_into()?), + listable: Some(value.listable), docker: Some(Box::new(docker)), + find_config: value + .find_config + .map(ApiTryInto::try_into) + .transpose()? + .map(Box::new), + join_config: value + .join_config + .map(ApiTryInto::try_into) + .transpose()? + .map(Box::new), + create_config: value + .create_config + .map(ApiTryInto::try_into) + .transpose()? + .map(Box::new), + // Overrides idle_lobbies: None, tier: None, @@ -344,3 +378,204 @@ impl ApiTryFrom }) } } + +impl ApiFrom + for backend::matchmaker::IdentityRequirement +{ + fn api_from( + value: models::CloudVersionMatchmakerGameModeIdentityRequirement, + ) -> backend::matchmaker::IdentityRequirement { + match value { + models::CloudVersionMatchmakerGameModeIdentityRequirement::None => { + backend::matchmaker::IdentityRequirement::None + } + models::CloudVersionMatchmakerGameModeIdentityRequirement::Guest => { + backend::matchmaker::IdentityRequirement::Guest + } + models::CloudVersionMatchmakerGameModeIdentityRequirement::Registered => { + backend::matchmaker::IdentityRequirement::Registered + } + } + } +} + +impl ApiFrom + for models::CloudVersionMatchmakerGameModeIdentityRequirement +{ + fn api_from(value: backend::matchmaker::IdentityRequirement) -> Self { + match value { + backend::matchmaker::IdentityRequirement::None => { + models::CloudVersionMatchmakerGameModeIdentityRequirement::None + } + backend::matchmaker::IdentityRequirement::Guest => { + models::CloudVersionMatchmakerGameModeIdentityRequirement::Guest + } + backend::matchmaker::IdentityRequirement::Registered => { + models::CloudVersionMatchmakerGameModeIdentityRequirement::Registered + } + } + } +} + +impl ApiTryFrom + for backend::matchmaker::VerificationConfig +{ + type Error = GlobalError; + + fn try_from( + value: models::CloudVersionMatchmakerGameModeVerificationConfig, + ) -> GlobalResult { + Ok(backend::matchmaker::VerificationConfig { + url: value.url, + headers: value.headers, + }) + } +} + +impl ApiTryFrom + for models::CloudVersionMatchmakerGameModeVerificationConfig +{ + type Error = GlobalError; + + fn try_from(value: backend::matchmaker::VerificationConfig) -> GlobalResult { + Ok(models::CloudVersionMatchmakerGameModeVerificationConfig { + url: value.url, + headers: value.headers, + }) + } +} + +impl ApiTryFrom + for backend::matchmaker::FindConfig +{ + type Error = GlobalError; + + fn try_from(value: models::CloudVersionMatchmakerGameModeFindConfig) -> GlobalResult { + Ok(backend::matchmaker::FindConfig { + enabled: value.enabled, + identity_requirement: ApiInto::::api_into( + value.identity_requirement, + ) as i32, + verification_config: value + .verification_config + .map(|x| ApiTryInto::try_into(*x)) + .transpose()?, + }) + } +} + +impl ApiTryFrom + for models::CloudVersionMatchmakerGameModeFindConfig +{ + type Error = GlobalError; + + fn try_from(value: backend::matchmaker::FindConfig) -> GlobalResult { + Ok(models::CloudVersionMatchmakerGameModeFindConfig { + enabled: value.enabled, + identity_requirement: internal_unwrap_owned!( + backend::matchmaker::IdentityRequirement::from_i32(value.identity_requirement), + "invalid identity requirement variant" + ) + .api_into(), + verification_config: value + .verification_config + .map(ApiTryInto::try_into) + .transpose()? + .map(Box::new), + }) + } +} + +impl ApiTryFrom + for backend::matchmaker::JoinConfig +{ + type Error = GlobalError; + + fn try_from(value: models::CloudVersionMatchmakerGameModeJoinConfig) -> GlobalResult { + Ok(backend::matchmaker::JoinConfig { + enabled: value.enabled, + identity_requirement: ApiInto::::api_into( + value.identity_requirement, + ) as i32, + verification_config: value + .verification_config + .map(|x| ApiTryInto::try_into(*x)) + .transpose()?, + }) + } +} + +impl ApiTryFrom + for models::CloudVersionMatchmakerGameModeJoinConfig +{ + type Error = GlobalError; + + fn try_from(value: backend::matchmaker::JoinConfig) -> GlobalResult { + Ok(models::CloudVersionMatchmakerGameModeJoinConfig { + enabled: value.enabled, + identity_requirement: internal_unwrap_owned!( + backend::matchmaker::IdentityRequirement::from_i32(value.identity_requirement), + "invalid identity requirement variant" + ) + .api_into(), + verification_config: value + .verification_config + .map(ApiTryInto::try_into) + .transpose()? + .map(Box::new), + }) + } +} + +impl ApiTryFrom + for backend::matchmaker::CreateConfig +{ + type Error = GlobalError; + + fn try_from(value: models::CloudVersionMatchmakerGameModeCreateConfig) -> GlobalResult { + if let Some(max_lobbies_per_identity) = value.max_lobbies_per_identity { + assert_with!( + max_lobbies_per_identity >= 0, + MATCHMAKER_INVALID_VERSION_CONFIG, + error = "`create_config.max_lobbies_per_identity` out of bounds" + ); + } + + Ok(backend::matchmaker::CreateConfig { + identity_requirement: ApiInto::::api_into( + value.identity_requirement, + ) as i32, + verification_config: value + .verification_config + .map(|x| ApiTryInto::try_into(*x)) + .transpose()?, + enable_public: value.enable_public, + enable_private: value.enable_private, + max_lobbies_per_identity: value.max_lobbies_per_identity.map(ApiTryInto::try_into).transpose()?, + }) + } +} + +impl ApiTryFrom + for models::CloudVersionMatchmakerGameModeCreateConfig +{ + type Error = GlobalError; + + fn try_from(value: backend::matchmaker::CreateConfig) -> GlobalResult { + Ok(models::CloudVersionMatchmakerGameModeCreateConfig { + identity_requirement: internal_unwrap_owned!( + backend::matchmaker::IdentityRequirement::from_i32(value.identity_requirement), + "invalid identity requirement variant" + ) + .api_into(), + verification_config: value + .verification_config + .map(ApiTryInto::try_into) + .transpose()? + .map(Box::new), + enable_public: value.enable_public, + enable_private: value.enable_private, + max_lobbies_per_identity: value.max_lobbies_per_identity.map(ApiTryInto::try_into).transpose()?, + }) + } +} \ No newline at end of file diff --git a/lib/convert/src/impls/cloud/version/matchmaker/lobby_group.rs b/lib/convert/src/impls/cloud/version/matchmaker/lobby_group.rs index 6c30784ae0..78b6b8657e 100644 --- a/lib/convert/src/impls/cloud/version/matchmaker/lobby_group.rs +++ b/lib/convert/src/impls/cloud/version/matchmaker/lobby_group.rs @@ -35,8 +35,13 @@ impl ApiTryFrom for backend::matchmake max_players_normal: value.max_players_normal as u32, max_players_direct: value.max_players_direct as u32, max_players_party: value.max_players_party as u32, + listable: true, runtime: Some((*value.runtime).try_into()?), + + find_config: None, + join_config: None, + create_config: None, }) } } diff --git a/lib/convert/src/impls/cloud/version/mod.rs b/lib/convert/src/impls/cloud/version/mod.rs index b351ccb732..a824be04e3 100644 --- a/lib/convert/src/impls/cloud/version/mod.rs +++ b/lib/convert/src/impls/cloud/version/mod.rs @@ -33,7 +33,8 @@ pub async fn config_to_proto( }, kv: value.kv.map(|_| backend::kv::VersionConfig {}), identity: value.identity.map(|x| (*x).try_into()).transpose()?, - module: todo!(), + // TODO: + module: None, }) } diff --git a/lib/convert/src/impls/mod.rs b/lib/convert/src/impls/mod.rs index 91c5b8dfca..4405cfe668 100644 --- a/lib/convert/src/impls/mod.rs +++ b/lib/convert/src/impls/mod.rs @@ -43,4 +43,20 @@ mod num { std::convert::TryInto::try_into(v) } } + + impl ApiTryFrom for i32 { + type Error = std::num::TryFromIntError; + + fn try_from(v: u64) -> Result { + std::convert::TryInto::try_into(v) + } + } + + impl ApiTryFrom for u64 { + type Error = std::num::TryFromIntError; + + fn try_from(v: i32) -> Result { + std::convert::TryInto::try_into(v) + } + } } diff --git a/lib/health-checks/Cargo.toml b/lib/health-checks/Cargo.toml index 44a400cea8..886a1e5303 100644 --- a/lib/health-checks/Cargo.toml +++ b/lib/health-checks/Cargo.toml @@ -12,7 +12,7 @@ rivet-pools = { path = "../pools" } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" thiserror = "1.0" -tokio = { version = "1.21", features = ["tracing"] } +tokio = { version = "1.29", features = ["tracing"] } tracing = "0.1" uuid = { version = "1", features = ["v4"] } diff --git a/lib/nomad-util/Cargo.toml b/lib/nomad-util/Cargo.toml index 4cc94c4770..4da6abae79 100644 --- a/lib/nomad-util/Cargo.toml +++ b/lib/nomad-util/Cargo.toml @@ -15,6 +15,6 @@ rivet-pools = { path = "../pools" } serde = { version = "1.0", features = ["derive"] } serde_json = { version = "1.0", features = ["raw_value"] } thiserror = "1.0" -tokio = { version = "1.21", features = ["full"] } +tokio = { version = "1.29", features = ["full"] } tracing = "0.1" diff --git a/lib/operation/core/Cargo.toml b/lib/operation/core/Cargo.toml index fb40076ee6..0cc3195145 100644 --- a/lib/operation/core/Cargo.toml +++ b/lib/operation/core/Cargo.toml @@ -23,6 +23,6 @@ rivet-pools = { path = "../../pools" } rivet-util = { path = "../../util/core" } serde_json = "1.0" thiserror = "1.0" -tokio = { version = "1.21", features = ["full", "tracing"] } +tokio = { version = "1.29", features = ["full", "tracing"] } tracing = "0.1" types = { path = "../../types/core" } diff --git a/lib/operation/core/src/lib.rs b/lib/operation/core/src/lib.rs index 05dad6afd8..cd28ffb480 100644 --- a/lib/operation/core/src/lib.rs +++ b/lib/operation/core/src/lib.rs @@ -90,7 +90,12 @@ where // TODO: Throw dedicated "timed out" error here // Process the request - let res = tokio::time::timeout(O::TIMEOUT, O::handle(self.wrap::(body)?)).await?; + let req_op_ctx = self.wrap::(body)?; + let timeout_fut = tokio::time::timeout(O::TIMEOUT, O::handle(req_op_ctx)); + let res = tokio::task::Builder::new() + .name("operation::handle") + .spawn(timeout_fut)? + .await??; // Record metrics { @@ -123,17 +128,18 @@ where .observe(dt); } - // Submit perf - let chirp = self.conn.chirp().clone(); - tokio::task::Builder::new().name("operation::perf").spawn( - async move { - // HACK: Force submit performance metrics after delay in order to ensure - // all spans have ended appropriately - tokio::time::sleep(Duration::from_secs(5)).await; - chirp.perf().submit().await; - } - .instrument(tracing::info_span!("operation_perf")), - )?; + // TODO: Add back + // // Submit perf + // let chirp = self.conn.chirp().clone(); + // tokio::task::Builder::new().name("operation::perf").spawn( + // async move { + // // HACK: Force submit performance metrics after delay in order to ensure + // // all spans have ended appropriately + // tokio::time::sleep(Duration::from_secs(5)).await; + // chirp.perf().submit().await; + // } + // .instrument(tracing::info_span!("operation_perf")), + // )?; res } @@ -285,10 +291,6 @@ where self.conn.redis_user_presence().await } - pub async fn redis_search(&self) -> Result { - self.conn.redis_search().await - } - pub fn perf(&self) -> &chirp_perf::PerfCtx { self.conn.perf() } diff --git a/lib/pools/Cargo.toml b/lib/pools/Cargo.toml index 74e89cc618..1800a2f206 100644 --- a/lib/pools/Cargo.toml +++ b/lib/pools/Cargo.toml @@ -13,20 +13,19 @@ lazy_static = "1.4" rand = "0.8" rivet-metrics = { path = "../metrics" } thiserror = "1.0" -tokio = { version = "1.21", features = ["tracing"] } +tokio = { version = "1.29", features = ["tracing"] } tokio-util = "0.6" tracing = "0.1" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false features = [ - "runtime-tokio-native-tls", + "runtime-tokio", "postgres", "macros", "uuid", "json", - "tls", ] [dependencies.redis] diff --git a/lib/pools/src/lib.rs b/lib/pools/src/lib.rs index c24645495b..1e280184df 100644 --- a/lib/pools/src/lib.rs +++ b/lib/pools/src/lib.rs @@ -75,7 +75,7 @@ async fn nats_from_env(client_name: String) -> Result, Error> { async move { match event { async_nats::Event::Connected => { - tracing::debug!(?server_addrs, "nats reconnected"); + tracing::info!(?server_addrs, "nats reconnected"); } async_nats::Event::Disconnected => { tracing::error!(?server_addrs, "nats disconnected"); @@ -100,12 +100,12 @@ async fn nats_from_env(client_name: String) -> Result, Error> { // NATS has built in backoff with jitter (with max of 4s), so // once the connection is established, we never have to worry // about disconnections that aren't handled by NATS. - tracing::debug!(?server_addrs, "nats connecting"); + tracing::info!(?server_addrs, "nats connecting"); let conn = options .connect(&server_addrs[..]) .await .map_err(Error::BuildNats)?; - tracing::debug!(?server_addrs, "nats connected"); + tracing::info!(?server_addrs, "nats connected"); Ok(Some(conn)) } else { @@ -120,40 +120,53 @@ fn crdb_from_env(client_name: String) -> Result, Error if let Some(svc_name_screaming) = key.strip_prefix("CRDB_URL_") { let svc_name = svc_name_screaming.to_lowercase().replace("_", "-"); - tracing::debug!(%url, "crdb creating connection"); + tracing::info!(%url, "crdb creating connection"); let client_name = client_name.clone(); let pool = sqlx::postgres::PgPoolOptions::new() // The default connection timeout is too high .acquire_timeout(Duration::from_secs(15)) + .max_lifetime(Duration::from_secs(60 * 5)) // Remove connections after a while in order to reduce load // on CRDB after bursts .idle_timeout(Some(Duration::from_secs(60))) // Open a connection // immediately on startup - .min_connections(1) + .min_connections(0) // Raise the cap, since this is effectively the amount of // simultaneous requests we can handle. See // https://www.cockroachlabs.com/docs/stable/connection-pooling.html - .max_connections(512) + .max_connections(20_000) // Speeds up requests at the expense of potential // failures // .test_before_acquire(false) - .after_connect({ - let url = url.clone(); - move |conn, _| { - let client_name = client_name.clone(); - let url = url.clone(); - Box::pin(async move { - tracing::debug!(%url, "crdb connected"); - sqlx::query("SET application_name = $1;") - .bind(&client_name) - .execute(conn) - .await?; - Ok(()) - }) - } - }) + // .after_connect(|conn, _meta| { + // Box::pin(async move { + // tracing::info!("pg connected"); + // Ok(()) + // }) + // }) + // .after_release(|conn, meta| { + // Box::pin(async move { + // tracing::info!("pg released"); + // Ok(false) + // }) + // }) + // .after_connect({ + // let url = url.clone(); + // move |conn, _| { + // let client_name = client_name.clone(); + // let url = url.clone(); + // Box::pin(async move { + // tracing::info!(%url, "crdb connected"); + // sqlx::query("SET application_name = $1;") + // .bind(&client_name) + // .execute(conn) + // .await?; + // Ok(()) + // }) + // } + // }) .connect_lazy(&url) .map_err(Error::BuildSqlx)?; @@ -177,13 +190,13 @@ async fn redis_from_env() -> Result, Error> { let pool = if let Some(existing) = existing_pools.get(&url) { existing.clone() } else { - tracing::debug!(%url, "redis connecting"); + tracing::info!(%url, "redis connecting"); let conn = redis::Client::open(url.as_str()) .map_err(Error::BuildRedis)? .get_tokio_connection_manager() .await .map_err(Error::BuildRedis)?; - tracing::debug!(%url, "redis connected"); + tracing::info!(%url, "redis connected"); conn }; diff --git a/lib/pools/src/pools.rs b/lib/pools/src/pools.rs index 619f30f265..a8d20f7ea8 100644 --- a/lib/pools/src/pools.rs +++ b/lib/pools/src/pools.rs @@ -100,6 +100,17 @@ impl PoolsInner { async fn record_metrics(&self) { use crate::metrics::*; + let mut dbs = self + .crdb_map() + .clone() + .into_iter() + .map(|(k, v)| (k, v.size(), v.num_idle())) + .filter(|x| x.1 > 0) + .collect::>(); + dbs.sort_by_key(|(_, size, _)| *size); + dbs.reverse(); + tracing::info!(?dbs, "db metrics"); + // CRDB for (db_name, pool) in self.crdb_map() { let label = &[db_name.as_str()]; diff --git a/lib/runtime/Cargo.toml b/lib/runtime/Cargo.toml index 1b36d438e9..0989f3febd 100644 --- a/lib/runtime/Cargo.toml +++ b/lib/runtime/Cargo.toml @@ -10,7 +10,7 @@ console-subscriber = "0.1" lazy_static = "1.4" rivet-metrics = { path = "../metrics" } thiserror = "1.0" -tokio = { version = "1.21", features = ["full", "tracing"] } +tokio = { version = "1.29", features = ["full", "tracing"] } tracing = "0.1" tracing-subscriber = { version = "0.3", default-features = false, features = ["fmt", "json", "ansi"] } # Used with attribute diff --git a/lib/s3-util/Cargo.toml b/lib/s3-util/Cargo.toml index 79bd355205..1ae703da3a 100644 --- a/lib/s3-util/Cargo.toml +++ b/lib/s3-util/Cargo.toml @@ -13,5 +13,5 @@ aws-smithy-types = { version = "0.52" } http = "0.2" thiserror = "1.0" tracing = "0.1" -tokio = { version = "1.21" } +tokio = { version = "1.29" } diff --git a/lib/util/core/Cargo.toml b/lib/util/core/Cargo.toml index 6896abdaf1..4c1804f180 100644 --- a/lib/util/core/Cargo.toml +++ b/lib/util/core/Cargo.toml @@ -24,7 +24,7 @@ rivet-util-macros = { path = "../macros" } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" thiserror = "1.0" -tokio = { version = "1.21", default-features = false, features = ["time", "sync", "fs", "parking_lot", "test-util", "macros"] } +tokio = { version = "1.29", default-features = false, features = ["time", "sync", "fs", "parking_lot", "test-util", "macros"] } types = { path = "../../types/core" } uuid = { version = "1", features = ["v4", "serde"] } diff --git a/lib/util/core/src/route.rs b/lib/util/core/src/route.rs index b526b17b44..02edb064e7 100644 --- a/lib/util/core/src/route.rs +++ b/lib/util/core/src/route.rs @@ -39,7 +39,7 @@ pub fn user_avatar(avatar_id: &str, upload_id: Option, file_name: Option<& file_name ) } else { - format!("https://assets.rivet.gg/avatars/{}.png", avatar_id) + format!("https://assets2.rivet.gg/avatars/{}.png", avatar_id) } } @@ -96,7 +96,7 @@ pub fn identity_game_link(link_token: &str) -> String { } pub fn cloud_device_link(link_token: &str) -> String { - format!("{}/developer/devices/link/{}", origin_hub(), link_token) + format!("{}/devices/link/{}", origin_hub(), link_token) } pub fn team_billing(team_id: Uuid) -> String { diff --git a/proto/backend/matchmaker.proto b/proto/backend/matchmaker.proto index d92e33a3d6..89b0b00bfa 100644 --- a/proto/backend/matchmaker.proto +++ b/proto/backend/matchmaker.proto @@ -41,8 +41,13 @@ message LobbyGroup { uint32 max_players_normal = 102; uint32 max_players_direct = 103; uint32 max_players_party = 104; + bool listable = 105; LobbyRuntime runtime = 201; + + optional FindConfig find_config = 301; + optional JoinConfig join_config = 302; + optional CreateConfig create_config = 303; } message LobbyRuntime { @@ -102,6 +107,39 @@ message LobbyRuntime { }; } +enum IdentityRequirement { + NONE = 0; + GUEST = 1; + REGISTERED = 2; +} + +message VerificationConfig { + string url = 1; + map headers = 2; +} + +message FindConfig { + bool enabled = 1; + IdentityRequirement identity_requirement = 2; + optional VerificationConfig verification_config = 3; +} + +message JoinConfig { + bool enabled = 1; + IdentityRequirement identity_requirement = 2; + optional VerificationConfig verification_config = 3; +} + +message CreateConfig { + IdentityRequirement identity_requirement = 1; + optional VerificationConfig verification_config = 2; + + bool enable_public = 3; + bool enable_private = 4; + + optional uint64 max_lobbies_per_identity = 5; +} + // MARK: Game Version Config Context // Context required to publish a new version. message VersionConfigCtx { @@ -148,6 +186,11 @@ message LobbyRuntimeMeta { // MARK: Lobby State message Lobby { + enum Publicity { + PUBLIC = 0; + PRIVATE = 1; + } + reserved 10; rivet.common.Uuid lobby_id = 1; @@ -161,6 +204,9 @@ message Lobby { bool is_closed = 11; rivet.common.Uuid namespace_id = 9; optional rivet.common.Uuid create_ray_id = 12; + optional rivet.common.Uuid creator_user_id = 15; + bool is_custom = 16; + Publicity publicity = 17; uint32 max_players_normal = 101; uint32 max_players_direct = 102; diff --git a/proto/backend/matchmaker/query.proto b/proto/backend/matchmaker/query.proto index c104d5b717..56c2f11ca9 100644 --- a/proto/backend/matchmaker/query.proto +++ b/proto/backend/matchmaker/query.proto @@ -23,4 +23,3 @@ message AutoCreate { rivet.common.Uuid lobby_group_id = 1; rivet.common.Uuid region_id = 2; } - diff --git a/proto/backend/net.proto b/proto/backend/net.proto index 869936d49f..060ce92c4b 100644 --- a/proto/backend/net.proto +++ b/proto/backend/net.proto @@ -13,3 +13,15 @@ message IpInfo { double longitude = 3; } +enum HttpMethod { + GET = 0; + POST = 1; + PUT = 2; + DELETE = 3; +} + +message ExternalRequestConfig { + string url = 1; + HttpMethod method = 2; + map headers = 3; +} diff --git a/shell.nix b/shell.nix index fbcc93de4a..a6d47230d0 100644 --- a/shell.nix +++ b/shell.nix @@ -46,7 +46,7 @@ in redis # For the redis-cli # Runtimes - nodejs-slim # Required for Fern + nodejs # Required for Fern # Compilers clang diff --git a/svc/Cargo.lock b/svc/Cargo.lock index 77caa4870a..f5d8f90198 100644 --- a/svc/Cargo.lock +++ b/svc/Cargo.lock @@ -2,6 +2,15 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "addr2line" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4fa78e18c64fce05e902adecd7a5eed15a5e0a3439f7b0e169f0252214865e3" +dependencies = [ + "gimli", +] + [[package]] name = "adler" version = "1.0.2" @@ -26,6 +35,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" dependencies = [ "cfg-if", + "getrandom", "once_cell", "version_check", ] @@ -41,9 +51,9 @@ dependencies = [ [[package]] name = "allocator-api2" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56fc6cf8dc8c4158eed8649f9b8b0ea1518eb62b544fe9490d66fa0b349eafe9" +checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" [[package]] name = "analytics-worker" @@ -80,9 +90,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.71" +version = "1.0.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8" +checksum = "3b13c32d80ecc7ab747b80c3784bce54ee8a7a0cc4fbda9bf4cda2cf6fe90854" [[package]] name = "api-admin" @@ -662,6 +672,7 @@ dependencies = [ "game-get", "game-namespace-get", "game-namespace-resolve-url", + "game-user-get", "http", "hyper", "job-run-get", @@ -693,10 +704,12 @@ dependencies = [ "serde_json", "thiserror", "token-create", + "token-revoke", "tokio", "tracing", "tracing-subscriber", "url", + "user-identity-get", "uuid", ] @@ -907,7 +920,7 @@ dependencies = [ "bytes", "futures", "http", - "itoa 1.0.6", + "itoa 1.0.9", "memchr", "nkeys", "nuid", @@ -922,7 +935,7 @@ dependencies = [ "serde_nanos", "serde_repr", "thiserror", - "time 0.3.22", + "time 0.3.25", "tokio", "tokio-retry", "tracing", @@ -935,7 +948,7 @@ version = "0.24.0-ALPHA.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8cdefe54cd7867d937c0a507d2a3a830af410044282cd3e4002b5b7860e1892e" dependencies = [ - "rustls 0.21.2", + "rustls 0.21.6", "tokio", "webpki 0.22.0", ] @@ -955,13 +968,13 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.68" +version = "0.1.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842" +checksum = "cc6dde6e4ed435a4c1ee4e73592f5ba9da2151af10076cc04858746af9352d09" dependencies = [ "proc-macro2", "quote", - "syn 2.0.18", + "syn 2.0.28", ] [[package]] @@ -972,9 +985,9 @@ checksum = "2ce4f10ea3abcd6617873bae9f91d1c5332b4a778bd9ce34d0cd517474c1de82" [[package]] name = "atoi" -version = "1.0.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7c57d12312ff59c811c0643f4d80830505833c9ffaebd193d819392b265be8e" +checksum = "f28d99ec8bfea296261ca1af174f24225171fea9664ba9003cbebee704810528" dependencies = [ "num-traits", ] @@ -1038,7 +1051,7 @@ dependencies = [ "aws-types", "bytes", "bytes-utils", - "fastrand", + "fastrand 1.9.0", "http", "http-body", "tokio-stream", @@ -1077,7 +1090,7 @@ dependencies = [ "percent-encoding", "regex", "sha2 0.10.7", - "time 0.3.22", + "time 0.3.25", "tracing", ] @@ -1137,7 +1150,7 @@ dependencies = [ "aws-smithy-http-tower 0.41.0", "aws-smithy-types 0.41.0", "bytes", - "fastrand", + "fastrand 1.9.0", "http", "http-body", "hyper", @@ -1161,7 +1174,7 @@ dependencies = [ "aws-smithy-http-tower 0.52.0", "aws-smithy-types 0.52.0", "bytes", - "fastrand", + "fastrand 1.9.0", "http", "http-body", "hyper", @@ -1274,10 +1287,10 @@ version = "0.41.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c7f957a2250cc0fa4ccf155e00aeac9a81f600df7cd4ecc910c75030e6534f5" dependencies = [ - "itoa 1.0.6", + "itoa 1.0.9", "num-integer", "ryu", - "time 0.3.22", + "time 0.3.25", ] [[package]] @@ -1287,10 +1300,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "987b1e37febb9bd409ca0846e82d35299e572ad8279bc404778caeb5fc05ad56" dependencies = [ "base64-simd", - "itoa 1.0.6", + "itoa 1.0.9", "num-integer", "ryu", - "time 0.3.22", + "time 0.3.25", ] [[package]] @@ -1320,19 +1333,19 @@ dependencies = [ [[package]] name = "axum" -version = "0.6.18" +version = "0.6.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8175979259124331c1d7bf6586ee7e0da434155e4b2d48ec2c8386281d8df39" +checksum = "3b829e4e32b91e643de6eafe82b1d90675f5874230191a4ffbc1b336dec4d6bf" dependencies = [ "async-trait", "axum-core", - "bitflags", + "bitflags 1.3.2", "bytes", "futures-util", "http", "http-body", "hyper", - "itoa 1.0.6", + "itoa 1.0.9", "matchit", "memchr", "mime", @@ -1363,6 +1376,21 @@ dependencies = [ "tower-service", ] +[[package]] +name = "backtrace" +version = "0.3.68" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4319208da049c43661739c5fade2ba182f09d1dc2299b32298d3a31692b17e12" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + [[package]] name = "base64" version = "0.13.1" @@ -1395,9 +1423,9 @@ dependencies = [ [[package]] name = "base64ct" -version = "1.1.1" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6b4d9b1225d28d360ec6a231d65af1fd99a2a095154c8040689617290569c5c" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" [[package]] name = "bcrypt" @@ -1423,6 +1451,15 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitflags" +version = "2.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42" +dependencies = [ + "serde", +] + [[package]] name = "block-buffer" version = "0.9.0" @@ -1458,15 +1495,15 @@ dependencies = [ "heck 0.3.3", "serde", "serde_json", - "toml 0.7.4", + "toml 0.7.6", "uuid", ] [[package]] name = "bstr" -version = "1.5.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a246e68bb43f6cd9db24bea052a53e40405417c5fb372e3d1a8a7f770a564ef5" +checksum = "6798148dccfbff0fae41c7574d2fa8f1ef3492fba0face179de5d8d447d67b05" dependencies = [ "memchr", ] @@ -1622,9 +1659,12 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.79" +version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" +checksum = "305fe645edc1442a0fa8b6726ba61d422798d37a52e12eaecf4b022ebbb88f01" +dependencies = [ + "libc", +] [[package]] name = "cdn-namespace-auth-user-remove" @@ -2259,7 +2299,7 @@ version = "0.1.0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.18", + "syn 2.0.28", ] [[package]] @@ -2544,9 +2584,9 @@ dependencies = [ [[package]] name = "console-subscriber" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57ab2224a0311582eb03adba4caaf18644f7b1f10a760803a803b9b605187fc7" +checksum = "d4cf42660ac07fcebed809cfe561dd8730bcd35b075215e6479c516bcd0d11cb" dependencies = [ "console-api", "crossbeam-channel", @@ -2582,6 +2622,12 @@ version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d6f2aa4d0537bcc1c74df8755072bd31c1ef1a3a1b85a68e8404a8c353b7b8b" +[[package]] +name = "const-oid" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "795bc6e66a8e340f075fcf6227e417a2dc976b92b91f3cdc778bb858778b6747" + [[package]] name = "core-foundation" version = "0.9.3" @@ -2600,18 +2646,33 @@ checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" [[package]] name = "cpufeatures" -version = "0.2.8" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03e69e28e9f7f77debdedbaafa2866e1de9ba56df55a8bd7cfc724c25a09987c" +checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" dependencies = [ "libc", ] +[[package]] +name = "crc" +version = "3.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86ec7a15cbe22e59248fc7eadb1907dab5ba09372595da4d73dd805ed4417dfe" +dependencies = [ + "crc-catalog", +] + +[[package]] +name = "crc-catalog" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cace84e55f07e7301bae1c519df89cdad8cc3cd868413d3fdbdeca9ff3db484" + [[package]] name = "crc32c" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dfea2db42e9927a3845fb268a10a72faed6d416065f77873f05e411457c363e" +checksum = "d8f48d60e5b4d2c53d5c2b1d8a58c849a70ae5e5509b08a48d047e3b65714a74" dependencies = [ "rustc_version", ] @@ -2671,7 +2732,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "626ae34994d3d8d668f4269922248239db4ae42d538b14c398b74a52208e8086" dependencies = [ "csv-core", - "itoa 1.0.6", + "itoa 1.0.9", "ryu", "serde", ] @@ -2738,9 +2799,9 @@ dependencies = [ [[package]] name = "darling" -version = "0.20.1" +version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0558d22a7b463ed0241e993f76f09f30b126687447751a8638587b864e4b3944" +checksum = "0209d94da627ab5605dcccf08bb18afa5009cfbef48d8a8b7d7bdbc79be25c5e" dependencies = [ "darling_core", "darling_macro", @@ -2748,27 +2809,27 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.20.1" +version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab8bfa2e259f8ee1ce5e97824a3c55ec4404a0d772ca7fa96bf19f0752a046eb" +checksum = "177e3443818124b357d8e76f53be906d60937f0d3a90773a664fa63fa253e621" dependencies = [ "fnv", "ident_case", "proc-macro2", "quote", "strsim", - "syn 2.0.18", + "syn 2.0.28", ] [[package]] name = "darling_macro" -version = "0.20.1" +version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29a358ff9f12ec09c3e61fef9b5a9902623a695a46a917b07f269bff1445611a" +checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5" dependencies = [ "darling_core", "quote", - "syn 2.0.18", + "syn 2.0.28", ] [[package]] @@ -2797,47 +2858,48 @@ version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "79b71cca7d95d7681a4b3b9cdf63c8dbc3730d0584c2c74e31416d64a90493f4" dependencies = [ - "const-oid", + "const-oid 0.6.2", ] [[package]] -name = "digest" -version = "0.9.0" +name = "der" +version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +checksum = "0c7ed52955ce76b1554f509074bb357d3fb8ac9b51288a65a3fd480d1dfba946" dependencies = [ - "generic-array", + "const-oid 0.9.4", + "pem-rfc7468 0.7.0", + "zeroize", ] [[package]] -name = "digest" -version = "0.10.7" +name = "deranged" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +checksum = "7684a49fb1af197853ef7b2ee694bc1f5b4179556f1e5710e1760c5db6f5e929" dependencies = [ - "block-buffer 0.10.4", - "crypto-common", - "subtle", + "serde", ] [[package]] -name = "dirs" -version = "4.0.0" +name = "digest" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" dependencies = [ - "dirs-sys", + "generic-array", ] [[package]] -name = "dirs-sys" -version = "0.3.7" +name = "digest" +version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ - "libc", - "redox_users", - "winapi", + "block-buffer 0.10.4", + "const-oid 0.9.4", + "crypto-common", + "subtle", ] [[package]] @@ -2852,7 +2914,7 @@ version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "91cff35c70bba8a626e3185d8cd48cc11b5437e1a5bcd15b9b5fa3c64b6dfee7" dependencies = [ - "signature", + "signature 1.6.4", ] [[package]] @@ -2869,9 +2931,12 @@ dependencies = [ [[package]] name = "either" -version = "1.8.1" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" +dependencies = [ + "serde", +] [[package]] name = "email-address-parser" @@ -2945,24 +3010,30 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + [[package]] name = "erased-serde" -version = "0.3.25" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f2b0c2380453a92ea8b6c8e5f64ecaafccddde8ceab55ff7a8ac1029f894569" +checksum = "da96524cc884f6558f1769b6c46686af2fe8e8b4cd253bd5a3cdba8181b8e070" dependencies = [ "serde", ] [[package]] name = "errno" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" +checksum = "6b30f669a7961ef1631673d2766cc92f52d64f7ef354d4fe0ddfd30ed52f0f4f" dependencies = [ "errno-dragonfly", "libc", - "windows-sys 0.48.0", + "windows-sys", ] [[package]] @@ -2975,12 +3046,52 @@ dependencies = [ "libc", ] +[[package]] +name = "etcetera" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "136d1b5283a1ab77bd9257427ffd09d8667ced0570b6f938942bc7568ed5b943" +dependencies = [ + "cfg-if", + "home", + "windows-sys", +] + [[package]] name = "event-listener" version = "2.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" +[[package]] +name = "external-request-validate" +version = "0.0.1" +dependencies = [ + "chirp-client", + "chirp-worker", + "chrono", + "http", + "prost 0.10.4", + "reqwest", + "rivet-operation", + "serde", + "serde_json", + "sqlx", +] + +[[package]] +name = "external-worker" +version = "0.0.1" +dependencies = [ + "chirp-client", + "chirp-worker", + "chrono", + "reqwest", + "rivet-health-checks", + "rivet-metrics", + "rivet-runtime", +] + [[package]] name = "faker-build" version = "0.0.1" @@ -3166,6 +3277,12 @@ dependencies = [ "instant", ] +[[package]] +name = "fastrand" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764" + [[package]] name = "fcm" version = "0.9.2" @@ -3196,6 +3313,18 @@ dependencies = [ "miniz_oxide", ] +[[package]] +name = "flume" +version = "0.10.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1657b4441c3403d9f7b3409e47575237dac27b1b5726df654a6ecbf92f0f7577" +dependencies = [ + "futures-core", + "futures-sink", + "pin-project", + "spin 0.9.8", +] + [[package]] name = "fnv" version = "1.0.7" @@ -3288,13 +3417,13 @@ dependencies = [ [[package]] name = "futures-intrusive" -version = "0.4.2" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a604f7a68fbf8103337523b1fadc8ade7361ee3f112f7c680ad179651616aed5" +checksum = "1d930c203dd0b6ff06e0201a4a2fe9149b43c684fd4420555b26d21b1a02956f" dependencies = [ "futures-core", "lock_api", - "parking_lot 0.11.2", + "parking_lot", ] [[package]] @@ -3311,7 +3440,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ "proc-macro2", "quote", - "syn 2.0.18", + "syn 2.0.28", ] [[package]] @@ -3754,6 +3883,7 @@ version = "0.0.1" dependencies = [ "chirp-client", "chirp-worker", + "external-request-validate", "faker-game", "game-version-get", "game-version-list", @@ -3792,6 +3922,12 @@ dependencies = [ "wasi 0.11.0+wasi-snapshot-preview1", ] +[[package]] +name = "gimli" +version = "0.27.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e" + [[package]] name = "global-error" version = "0.1.5" @@ -3818,9 +3954,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.19" +version = "0.3.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d357c7ae988e7d2182f7d7871d0b963962420b0678b0997ce7de72001aeab782" +checksum = "97ec8491ebaf99c8eaa73058b045fe58073cd6be7f596ac993ced0b0a0c01049" dependencies = [ "bytes", "fnv", @@ -3828,7 +3964,7 @@ dependencies = [ "futures-sink", "futures-util", "http", - "indexmap", + "indexmap 1.9.3", "slab", "tokio", "tokio-util 0.7.8", @@ -3883,7 +4019,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3e372db8e5c0d213e0cd0b9be18be2aca3d44cf2fe30a9d46a65581cd454584" dependencies = [ "base64 0.13.1", - "bitflags", + "bitflags 1.3.2", "bytes", "headers-core", "http", @@ -3921,18 +4057,9 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" -dependencies = [ - "libc", -] - -[[package]] -name = "hermit-abi" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" +checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" [[package]] name = "hex" @@ -3958,6 +4085,15 @@ dependencies = [ "digest 0.10.7", ] +[[package]] +name = "home" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb" +dependencies = [ + "windows-sys", +] + [[package]] name = "http" version = "0.2.9" @@ -3966,7 +4102,7 @@ checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" dependencies = [ "bytes", "fnv", - "itoa 1.0.6", + "itoa 1.0.9", ] [[package]] @@ -4000,9 +4136,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.14.26" +version = "0.14.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab302d72a6f11a3b910431ff93aae7e773078c769f0a3ef15fb9ec692ed147d4" +checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" dependencies = [ "bytes", "futures-channel", @@ -4013,7 +4149,7 @@ dependencies = [ "http-body", "httparse", "httpdate", - "itoa 1.0.6", + "itoa 1.0.9", "pin-project-lite", "socket2", "tokio", @@ -4057,13 +4193,14 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.24.0" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0646026eb1b3eea4cd9ba47912ea5ce9cc07713d105b1a14698f4e6433d348b7" +checksum = "8d78e1e73ec14cf7375674f74d7dde185c8206fd9dea6fb6295e8a98098aaa97" dependencies = [ + "futures-util", "http", "hyper", - "rustls 0.21.2", + "rustls 0.21.6", "tokio", "tokio-rustls 0.24.1", ] @@ -4203,6 +4340,16 @@ dependencies = [ "serde", ] +[[package]] +name = "indexmap" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d" +dependencies = [ + "equivalent", + "hashbrown 0.14.0", +] + [[package]] name = "indoc" version = "1.0.9" @@ -4227,17 +4374,6 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "io-lifetimes" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" -dependencies = [ - "hermit-abi 0.3.1", - "libc", - "windows-sys 0.48.0", -] - [[package]] name = "ip-info" version = "0.0.1" @@ -4255,9 +4391,9 @@ dependencies = [ [[package]] name = "ipnet" -version = "2.7.2" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12b6ee2129af8d4fb011108c73d99a1b83a85977f23b82460c0ae2e25bb4b57f" +checksum = "28b29a3cd74f0f4598934efe3aeba42bae0eb4680554128851ebbecb02af14e6" [[package]] name = "itertools" @@ -4276,9 +4412,9 @@ checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" [[package]] name = "itoa" -version = "1.0.6" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" +checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" [[package]] name = "job-gc" @@ -4576,12 +4712,32 @@ name = "lazy_static" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +dependencies = [ + "spin 0.5.2", +] [[package]] name = "libc" -version = "0.2.146" +version = "0.2.147" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" + +[[package]] +name = "libm" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7012b1bbb0719e1097c47611d3898568c546d597c2e74d66f6087edd5233ff4" + +[[package]] +name = "libsqlite3-sys" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f92be4933c13fd498862a9e02a3055f8a8d9c039ce33db97306fd5a6caa7f29b" +checksum = "afc22eff61b133b115c6e8c74e818c628d6d5e7a502afea6f64dee076dd94326" +dependencies = [ + "cc", + "pkg-config", + "vcpkg", +] [[package]] name = "linked-hash-map" @@ -4591,9 +4747,9 @@ checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" [[package]] name = "linux-raw-sys" -version = "0.3.8" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" +checksum = "57bcfdad1b858c2db7c38303a6d2ad4dfaf5eb53dfeb0910128b2c26d6158503" [[package]] name = "lock_api" @@ -4637,14 +4793,14 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" dependencies = [ - "regex-automata", + "regex-automata 0.1.10", ] [[package]] name = "matchit" -version = "0.7.0" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b87248edafb776e59e6ee64a79086f65890d3510f2c656c000bf2a7e8a0aea40" +checksum = "ed1202b2a6f884ae56f04cff409ab315c5ce26b5e58d7412e484f01fd52f52ef" [[package]] name = "md-5" @@ -4700,7 +4856,7 @@ checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" dependencies = [ "libc", "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.48.0", + "windows-sys", ] [[package]] @@ -4997,6 +5153,18 @@ dependencies = [ "sqlx", ] +[[package]] +name = "mm-lobby-list-for-user-id" +version = "0.0.1" +dependencies = [ + "chirp-client", + "chirp-worker", + "faker-mm-lobby", + "prost 0.10.4", + "rivet-operation", + "sqlx", +] + [[package]] name = "mm-lobby-player-count" version = "0.0.1" @@ -5069,6 +5237,7 @@ dependencies = [ "faker-game-version", "faker-mm-lobby", "faker-region", + "faker-user", "game-get", "game-namespace-get", "game-namespace-version-set", @@ -5090,6 +5259,7 @@ dependencies = [ "nomad-util", "redis-util", "region-get", + "region-list", "reqwest", "rivet-health-checks", "rivet-metrics", @@ -5105,6 +5275,7 @@ dependencies = [ "upload-complete", "upload-get", "upload-prepare", + "user-identity-create", ] [[package]] @@ -5416,6 +5587,23 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-bigint-dig" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc84195820f291c7697304f3cbdadd1cb7199c0efc917ff5eafd71225c136151" +dependencies = [ + "byteorder", + "lazy_static", + "libm", + "num-integer", + "num-iter", + "num-traits", + "rand", + "smallvec", + "zeroize", +] + [[package]] name = "num-integer" version = "0.1.45" @@ -5426,25 +5614,46 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-iter" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + [[package]] name = "num-traits" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2" dependencies = [ "autocfg", + "libm", ] [[package]] name = "num_cpus" -version = "1.15.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ - "hermit-abi 0.2.6", + "hermit-abi", "libc", ] +[[package]] +name = "object" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8bda667d9f2b5051b8833f59f3bf748b28ef54f850f4fcb389a252aa383866d1" +dependencies = [ + "memchr", +] + [[package]] name = "once_cell" version = "1.18.0" @@ -5459,11 +5668,11 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] name = "openssl" -version = "0.10.55" +version = "0.10.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "345df152bc43501c5eb9e4654ff05f794effb78d4efe3d53abc158baddc0703d" +checksum = "729b745ad4a5575dd06a3e1af1414bd330ee561c01b3899eb584baeaa8def17e" dependencies = [ - "bitflags", + "bitflags 1.3.2", "cfg-if", "foreign-types", "libc", @@ -5480,7 +5689,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.18", + "syn 2.0.28", ] [[package]] @@ -5491,9 +5700,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.90" +version = "0.9.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "374533b0e45f3a7ced10fcaeccca020e66656bc03dac384f852e4e5a7a8104a6" +checksum = "866b5f16f90776b9bb8dc1e1802ac6f0513de3a7a7465867bfbc563dc737faac" dependencies = [ "cc", "libc", @@ -5513,17 +5722,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" -[[package]] -name = "parking_lot" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" -dependencies = [ - "instant", - "lock_api", - "parking_lot_core 0.8.6", -] - [[package]] name = "parking_lot" version = "0.12.1" @@ -5531,21 +5729,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" dependencies = [ "lock_api", - "parking_lot_core 0.9.8", -] - -[[package]] -name = "parking_lot_core" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" -dependencies = [ - "cfg-if", - "instant", - "libc", - "redox_syscall 0.2.16", - "smallvec", - "winapi", + "parking_lot_core", ] [[package]] @@ -5556,16 +5740,16 @@ checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.3.5", + "redox_syscall", "smallvec", "windows-targets", ] [[package]] name = "paste" -version = "1.0.12" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f746c4065a8fa3fe23974dd82f15431cc8d40779821001404d10d2e79ca7d79" +checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" [[package]] name = "pem" @@ -5578,9 +5762,18 @@ dependencies = [ [[package]] name = "pem-rfc7468" -version = "0.2.4" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f22eb0e3c593294a99e9ff4b24cf6b752d43f193aa4415fe5077c159996d497" +dependencies = [ + "base64ct", +] + +[[package]] +name = "pem-rfc7468" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84e93a3b1cc0510b03020f33f21e62acdde3dcaef432edc95bea377fbd4c2cd4" +checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" dependencies = [ "base64ct", ] @@ -5603,9 +5796,9 @@ dependencies = [ [[package]] name = "pest" -version = "2.6.1" +version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16833386b02953ca926d19f64af613b9bf742c48dcd5e09b32fbfc9740bf84e2" +checksum = "1acb4a4365a13f749a93f1a094a7805e5cfa0955373a9de860d962eaa3a5fe5a" dependencies = [ "thiserror", "ucd-trie", @@ -5613,9 +5806,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.6.1" +version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7763190f9406839f99e5197afee8c9e759969f7dbfa40ad3b8dbee8757b745b5" +checksum = "666d00490d4ac815001da55838c500eafb0320019bbaa44444137c48b443a853" dependencies = [ "pest", "pest_generator", @@ -5623,22 +5816,22 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.6.1" +version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "249061b22e99973da1f5f5f1410284419e283bb60b79255bf5f42a94b66a2e00" +checksum = "68ca01446f50dbda87c1786af8770d535423fa8a53aec03b8f4e3d7eb10e0929" dependencies = [ "pest", "pest_meta", "proc-macro2", "quote", - "syn 2.0.18", + "syn 2.0.28", ] [[package]] name = "pest_meta" -version = "2.6.1" +version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "457c310cfc9cf3f22bc58901cc7f0d3410ac5d6298e432a4f9a6138565cb6df6" +checksum = "56af0a30af74d0445c0bf6d9d051c979b516a1a5af790d251daee76005420a48" dependencies = [ "once_cell", "pest", @@ -5652,34 +5845,34 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4dd7d28ee937e54fe3080c91faa1c3a46c06de6252988a7f4592ba2310ef22a4" dependencies = [ "fixedbitset", - "indexmap", + "indexmap 1.9.3", ] [[package]] name = "pin-project" -version = "1.1.0" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c95a7476719eab1e366eaf73d0260af3021184f18177925b07f54b30089ceead" +checksum = "fda4ed1c6c173e3fc7a83629421152e01d7b1f9b7f65fb301e490e8cfc656422" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.0" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39407670928234ebc5e6e580247dd567ad73a3578460c5990f9503df207e8f07" +checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" dependencies = [ "proc-macro2", "quote", - "syn 2.0.18", + "syn 2.0.28", ] [[package]] name = "pin-project-lite" -version = "0.2.9" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" +checksum = "2c516611246607d0c04186886dbb3a754368ef82c79e9827a802c6d836dd111c" [[package]] name = "pin-utils" @@ -5687,18 +5880,39 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "pkcs1" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" +dependencies = [ + "der 0.7.7", + "pkcs8 0.10.2", + "spki 0.7.2", +] + [[package]] name = "pkcs8" version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee3ef9b64d26bad0536099c816c6734379e45bbd5f14798def6809e5cc350447" dependencies = [ - "der", - "pem-rfc7468", - "spki", + "der 0.4.5", + "pem-rfc7468 0.2.3", + "spki 0.4.1", "zeroize", ] +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der 0.7.7", + "spki 0.7.2", +] + [[package]] name = "pkg-config" version = "0.3.27" @@ -5799,9 +6013,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.60" +version = "1.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dec2b086b7a862cf4de201096214fa870344cf922b2b30c167badb3af3195406" +checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" dependencies = [ "unicode-ident", ] @@ -5828,7 +6042,7 @@ dependencies = [ "fnv", "lazy_static", "memchr", - "parking_lot 0.12.1", + "parking_lot", "protobuf", "thiserror", ] @@ -5951,9 +6165,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.28" +version = "1.0.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9ab9c7eadfd8df19006f1cf1a4aed13540ed5cbc047010ece5826e10825488" +checksum = "50f3b39ccfb720540debaa0164757101c08ecb8d326b15358ce76a62c7e85965" dependencies = [ "proc-macro2", ] @@ -6006,7 +6220,7 @@ dependencies = [ "combine", "futures", "futures-util", - "itoa 1.0.6", + "itoa 1.0.9", "native-tls", "percent-encoding", "pin-project-lite", @@ -6027,44 +6241,25 @@ dependencies = [ "regex", ] -[[package]] -name = "redox_syscall" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" -dependencies = [ - "bitflags", -] - [[package]] name = "redox_syscall" version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" dependencies = [ - "bitflags", -] - -[[package]] -name = "redox_users" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" -dependencies = [ - "getrandom", - "redox_syscall 0.2.16", - "thiserror", + "bitflags 1.3.2", ] [[package]] name = "regex" -version = "1.8.4" +version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0ab3ca65655bb1e41f2a8c8cd662eb4fb035e67c3f78da1d61dffe89d07300f" +checksum = "81bc1d4caf89fac26a70747fe603c130093b53c773888797a6329091246d651a" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.7.2", + "regex-automata 0.3.6", + "regex-syntax 0.7.4", ] [[package]] @@ -6076,6 +6271,17 @@ dependencies = [ "regex-syntax 0.6.29", ] +[[package]] +name = "regex-automata" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fed1ceff11a1dddaee50c9dc8e4938bd106e9d89ae372f192311e7da498e3b69" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax 0.7.4", +] + [[package]] name = "regex-syntax" version = "0.6.29" @@ -6084,9 +6290,9 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.7.2" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78" +checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2" [[package]] name = "region-get" @@ -6158,7 +6364,7 @@ dependencies = [ "http", "http-body", "hyper", - "hyper-rustls 0.24.0", + "hyper-rustls 0.24.1", "hyper-tls", "ipnet", "js-sys", @@ -6169,7 +6375,7 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite", - "rustls 0.21.2", + "rustls 0.21.6", "rustls-pemfile", "serde", "serde_json", @@ -6197,7 +6403,7 @@ dependencies = [ "cc", "libc", "once_cell", - "spin", + "spin 0.5.2", "untrusted", "web-sys", "winapi", @@ -6570,7 +6776,7 @@ version = "0.1.0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.18", + "syn 2.0.28", ] [[package]] @@ -6744,9 +6950,16 @@ name = "rivet-util-mm" version = "0.1.0" dependencies = [ "bit-vec", + "chirp-client", + "http", + "mm-lobby-list-for-user-id", + "region-get", + "rivet-operation", "rivet-util", "serde", + "serde_json", "strum", + "user-identity-get", "uuid", ] @@ -6781,6 +6994,34 @@ dependencies = [ "uuid", ] +[[package]] +name = "rsa" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ab43bb47d23c1a631b4b680199a45255dce26fa9ab2fa902581f624ff13e6a8" +dependencies = [ + "byteorder", + "const-oid 0.9.4", + "digest 0.10.7", + "num-bigint-dig", + "num-integer", + "num-iter", + "num-traits", + "pkcs1", + "pkcs8 0.10.2", + "rand_core 0.6.4", + "signature 2.1.0", + "spki 0.7.2", + "subtle", + "zeroize", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" + [[package]] name = "rustc_version" version = "0.4.0" @@ -6792,16 +7033,15 @@ dependencies = [ [[package]] name = "rustix" -version = "0.37.20" +version = "0.38.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b96e891d04aa506a6d1f318d2771bcb1c7dfda84e126660ace067c9b474bb2c0" +checksum = "172891ebdceb05aa0005f533a6cbfca599ddd7d966f6f5d4d9b2e70478e70399" dependencies = [ - "bitflags", + "bitflags 2.3.3", "errno", - "io-lifetimes", "libc", "linux-raw-sys", - "windows-sys 0.48.0", + "windows-sys", ] [[package]] @@ -6831,9 +7071,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.21.2" +version = "0.21.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e32ca28af694bc1bbf399c33a516dbdf1c90090b8ab23c2bc24f834aa2247f5f" +checksum = "1d1feddffcfcc0b33f5c6ce9a29e341e4cd59c3f78e7ee45f4a40c038b1d6cbb" dependencies = [ "log", "ring", @@ -6867,18 +7107,18 @@ dependencies = [ [[package]] name = "rustls-pemfile" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d194b56d58803a43635bdc398cd17e383d6f71f9182b9a192c127ca42494a59b" +checksum = "2d3987094b1d07b653b7dfdc3f70ce9a1da9c51ac18c1b06b662e4f9a0e9f4b2" dependencies = [ "base64 0.21.2", ] [[package]] name = "rustls-webpki" -version = "0.100.1" +version = "0.101.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6207cd5ed3d8dca7816f8f3725513a34609c0c765bf652b8c3cb4cfd87db46b" +checksum = "513722fd73ad80a71f72b61009ea1b584bcfa1483ca93949c8f290298837fa59" dependencies = [ "ring", "untrusted", @@ -6886,15 +7126,15 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.12" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f3208ce4d8448b3f3e7d168a73f5e0c43a61e32930de3bceeccedb388b6bf06" +checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" [[package]] name = "ryu" -version = "1.0.13" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" +checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" [[package]] name = "s3-util" @@ -6912,11 +7152,11 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.21" +version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "713cfb06c7059f3588fb8044c0fad1d09e3c01d225e25b9220dbfdcf16dbb1b3" +checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88" dependencies = [ - "windows-sys 0.42.0", + "windows-sys", ] [[package]] @@ -6931,9 +7171,9 @@ dependencies = [ [[package]] name = "scopeguard" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "sct" @@ -6969,11 +7209,11 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.9.1" +version = "2.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fc758eb7bffce5b308734e9b0c1468893cae9ff70ebf13e7090be8dcbcc83a8" +checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" dependencies = [ - "bitflags", + "bitflags 1.3.2", "core-foundation", "core-foundation-sys", "libc", @@ -6982,9 +7222,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.9.0" +version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f51d0c0d83bec45f16480d0ce0058397a69e48fcdc52d1dc8855fb68acbd31a7" +checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" dependencies = [ "core-foundation-sys", "libc", @@ -6992,15 +7232,15 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed" +checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918" [[package]] name = "serde" -version = "1.0.164" +version = "1.0.183" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e8c8cf938e98f769bc164923b06dce91cea1751522f46f8466461af04c9027d" +checksum = "32ac8da02677876d532745a130fc9d8e6edfa81a269b107c5b00829b91d8eb3c" dependencies = [ "serde_derive", ] @@ -7016,13 +7256,13 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.164" +version = "1.0.183" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9735b638ccc51c28bf6914d90a2e9725b377144fc612c49a611fddd1b631d68" +checksum = "aafe972d60b0b9bee71a91b92fee2d4fb3c9d7e8f6b179aa99f27203d99a4816" dependencies = [ "proc-macro2", "quote", - "syn 2.0.18", + "syn 2.0.28", ] [[package]] @@ -7038,11 +7278,11 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.97" +version = "1.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdf3bf93142acad5821c99197022e170842cdbc1c30482b98750c688c640842a" +checksum = "076066c5f1078eac5b722a31827a8832fe108bed65dfa75e233c89f8206e976c" dependencies = [ - "itoa 1.0.6", + "itoa 1.0.9", "ryu", "serde", ] @@ -7058,20 +7298,20 @@ dependencies = [ [[package]] name = "serde_repr" -version = "0.1.12" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcec881020c684085e55a25f7fd888954d56609ef363479dc5a1305eb0d40cab" +checksum = "8725e1dfadb3a50f7e5ce0b1a540466f6ed3fe7a0fca2ac2b8b831d31316bd00" dependencies = [ "proc-macro2", "quote", - "syn 2.0.18", + "syn 2.0.28", ] [[package]] name = "serde_spanned" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93107647184f6027e3b7dcb2e11034cf95ffa1e3a682c67951963ac69c1c007d" +checksum = "96426c9936fd7a0124915f9185ea1d20aa9445cc9821142f0a73bc9207a2e186" dependencies = [ "serde", ] @@ -7083,7 +7323,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" dependencies = [ "form_urlencoded", - "itoa 1.0.6", + "itoa 1.0.9", "ryu", "serde", ] @@ -7097,11 +7337,11 @@ dependencies = [ "base64 0.13.1", "chrono", "hex", - "indexmap", + "indexmap 1.9.3", "serde", "serde_json", "serde_with_macros", - "time 0.3.22", + "time 0.3.25", ] [[package]] @@ -7113,7 +7353,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.18", + "syn 2.0.28", ] [[package]] @@ -7190,9 +7430,9 @@ version = "0.23.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5dfecc059e81632eef1dd9b79e22fc28b8fe69b30d3357512a77a0ad8ee3c782" dependencies = [ - "pkcs8", + "pkcs8 0.7.6", "rand_core 0.6.4", - "signature", + "signature 1.6.4", "zeroize", ] @@ -7202,6 +7442,16 @@ version = "1.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" +[[package]] +name = "signature" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e1788eed21689f9cf370582dfc467ef36ed9c707f073528ddafa8d83e3b8500" +dependencies = [ + "digest 0.10.7", + "rand_core 0.6.4", +] + [[package]] name = "simd-abstraction" version = "0.7.1" @@ -7220,7 +7470,7 @@ dependencies = [ "num-bigint", "num-traits", "thiserror", - "time 0.3.22", + "time 0.3.25", ] [[package]] @@ -7234,9 +7484,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" +checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" [[package]] name = "socket2" @@ -7254,13 +7504,32 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api", +] + [[package]] name = "spki" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c01a0c15da1b0b0e1494112e7af814a678fec9bd157881b49beac661e9b6f32" dependencies = [ - "der", + "der 0.4.5", +] + +[[package]] +name = "spki" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d1e996ef02c474957d681f1b05213dfb0abab947b446a62d37770b23500184a" +dependencies = [ + "base64ct", + "der 0.7.7", ] [[package]] @@ -7276,94 +7545,203 @@ dependencies = [ [[package]] name = "sqlx" -version = "0.6.3" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8de3b03a925878ed54a954f621e64bf55a3c1bd29652d0d1a17830405350188" +checksum = "8e58421b6bc416714d5115a2ca953718f6c621a51b68e4f4922aea5a4391a721" dependencies = [ "sqlx-core", "sqlx-macros", + "sqlx-mysql", + "sqlx-postgres", + "sqlx-sqlite", ] [[package]] name = "sqlx-core" -version = "0.6.3" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa8241483a83a3f33aa5fff7e7d9def398ff9990b2752b6c6112b83c6d246029" +checksum = "dd4cef4251aabbae751a3710927945901ee1d97ee96d757f6880ebb9a79bfd53" dependencies = [ - "ahash 0.7.6", + "ahash 0.8.3", "atoi", - "base64 0.13.1", "bit-vec", - "bitflags", "byteorder", "bytes", + "crc", "crossbeam-queue", - "dirs", "dotenvy", "either", "event-listener", "futures-channel", "futures-core", "futures-intrusive", + "futures-io", "futures-util", "hashlink", "hex", - "hkdf", - "hmac", - "indexmap", - "itoa 1.0.6", - "libc", + "indexmap 2.0.0", "log", - "md-5", "memchr", "once_cell", "paste", "percent-encoding", - "rand", "serde", "serde_json", - "sha1 0.10.5", "sha2 0.10.7", "smallvec", "sqlformat", - "sqlx-rt", - "stringprep", "thiserror", + "tokio", "tokio-stream", + "tracing", "url", "uuid", - "whoami", ] [[package]] name = "sqlx-macros" -version = "0.6.3" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "208e3165167afd7f3881b16c1ef3f2af69fa75980897aac8874a0696516d12c2" +dependencies = [ + "proc-macro2", + "quote", + "sqlx-core", + "sqlx-macros-core", + "syn 1.0.109", +] + +[[package]] +name = "sqlx-macros-core" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9966e64ae989e7e575b19d7265cb79d7fc3cbbdf179835cb0d716f294c2049c9" +checksum = "8a4a8336d278c62231d87f24e8a7a74898156e34c1c18942857be2acb29c7dfc" dependencies = [ "dotenvy", "either", "heck 0.4.1", + "hex", "once_cell", "proc-macro2", "quote", + "serde", "serde_json", + "sha2 0.10.7", "sqlx-core", - "sqlx-rt", + "sqlx-mysql", + "sqlx-postgres", + "sqlx-sqlite", "syn 1.0.109", + "tempfile", + "tokio", "url", ] [[package]] -name = "sqlx-rt" -version = "0.6.3" +name = "sqlx-mysql" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "804d3f245f894e61b1e6263c84b23ca675d96753b5abfd5cc8597d86806e8024" +checksum = "8ca69bf415b93b60b80dc8fda3cb4ef52b2336614d8da2de5456cc942a110482" dependencies = [ - "native-tls", + "atoi", + "base64 0.21.2", + "bitflags 2.3.3", + "byteorder", + "bytes", + "crc", + "digest 0.10.7", + "dotenvy", + "either", + "futures-channel", + "futures-core", + "futures-io", + "futures-util", + "generic-array", + "hex", + "hkdf", + "hmac", + "itoa 1.0.9", + "log", + "md-5", + "memchr", "once_cell", - "tokio", - "tokio-native-tls", + "percent-encoding", + "rand", + "rsa", + "serde", + "sha1 0.10.5", + "sha2 0.10.7", + "smallvec", + "sqlx-core", + "stringprep", + "thiserror", + "tracing", + "uuid", + "whoami", +] + +[[package]] +name = "sqlx-postgres" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0db2df1b8731c3651e204629dd55e52adbae0462fa1bdcbed56a2302c18181e" +dependencies = [ + "atoi", + "base64 0.21.2", + "bit-vec", + "bitflags 2.3.3", + "byteorder", + "crc", + "dotenvy", + "etcetera", + "futures-channel", + "futures-core", + "futures-io", + "futures-util", + "hex", + "hkdf", + "hmac", + "home", + "itoa 1.0.9", + "log", + "md-5", + "memchr", + "once_cell", + "rand", + "serde", + "serde_json", + "sha1 0.10.5", + "sha2 0.10.7", + "smallvec", + "sqlx-core", + "stringprep", + "thiserror", + "tracing", + "uuid", + "whoami", +] + +[[package]] +name = "sqlx-sqlite" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4c21bf34c7cae5b283efb3ac1bcc7670df7561124dc2f8bdc0b59be40f79a2" +dependencies = [ + "atoi", + "flume", + "futures-channel", + "futures-core", + "futures-executor", + "futures-intrusive", + "futures-util", + "libsqlite3-sys", + "log", + "percent-encoding", + "serde", + "sqlx-core", + "tracing", + "url", + "uuid", ] [[package]] @@ -7374,9 +7752,9 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] name = "stringprep" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ee348cb74b87454fff4b551cbf727025810a004f88aeacae7f85b87f4e9a1c1" +checksum = "db3737bde7edce97102e0e2b15365bf7a20bfdb5f60f4f9e8d7004258a51a8da" dependencies = [ "unicode-bidi", "unicode-normalization", @@ -7429,9 +7807,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.18" +version = "2.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32d41677bcbe24c20c52e7c70b0d8db04134c5d1066bf98662e2871ad200ea3e" +checksum = "04361975b3f5e348b2189d8dc55bc942f278b2d482a6a0365de5bdd62d351567" dependencies = [ "proc-macro2", "quote", @@ -7811,36 +8189,35 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.6.0" +version = "3.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31c0432476357e58790aaa47a8efb0c5138f137343f3b5f23bd36a27e3b0a6d6" +checksum = "dc02fddf48964c42031a0b3fe0428320ecf3a73c401040fc0096f97794310651" dependencies = [ - "autocfg", "cfg-if", - "fastrand", - "redox_syscall 0.3.5", + "fastrand 2.0.0", + "redox_syscall", "rustix", - "windows-sys 0.48.0", + "windows-sys", ] [[package]] name = "thiserror" -version = "1.0.40" +version = "1.0.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" +checksum = "611040a08a0439f8248d1990b111c95baa9c704c805fa1f62104b39655fd7f90" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.40" +version = "1.0.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" +checksum = "090198534930841fab3a5d1bb637cde49e339654e606195f8d9c76eeb081dc96" dependencies = [ "proc-macro2", "quote", - "syn 2.0.18", + "syn 2.0.28", ] [[package]] @@ -7876,11 +8253,12 @@ dependencies = [ [[package]] name = "time" -version = "0.3.22" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea9e1b3cf1243ae005d9e74085d4d542f3125458f3a81af210d901dcd7411efd" +checksum = "b0fdd63d58b18d663fbdf70e049f00a22c8e42be082203be7f26589213cd75ea" dependencies = [ - "itoa 1.0.6", + "deranged", + "itoa 1.0.9", "serde", "time-core", "time-macros", @@ -7894,9 +8272,9 @@ checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb" [[package]] name = "time-macros" -version = "0.2.9" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "372950940a5f07bf38dbe211d7283c9e6d7327df53794992d293e534c733d09b" +checksum = "eb71511c991639bb078fd5bf97757e03914361c48100d52878b8e52b46fb92cd" dependencies = [ "time-core", ] @@ -7973,22 +8351,23 @@ dependencies = [ [[package]] name = "tokio" -version = "1.28.2" +version = "1.29.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94d7b1cfd2aa4011f2de74c2c4c63665e27a71006b0a192dcd2710272e73dfa2" +checksum = "532826ff75199d5833b9d2c5fe410f29235e25704ee5f0ef599fb51c21f4a4da" dependencies = [ "autocfg", + "backtrace", "bytes", "libc", "mio", "num_cpus", - "parking_lot 0.12.1", + "parking_lot", "pin-project-lite", "signal-hook-registry", "socket2", "tokio-macros", "tracing", - "windows-sys 0.48.0", + "windows-sys", ] [[package]] @@ -8009,7 +8388,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.18", + "syn 2.0.28", ] [[package]] @@ -8061,7 +8440,7 @@ version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" dependencies = [ - "rustls 0.21.2", + "rustls 0.21.6", "tokio", ] @@ -8115,9 +8494,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.7.4" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6135d499e69981f9ff0ef2167955a5333c35e36f6937d382974566b3d5b94ec" +checksum = "c17e963a819c331dcacd7ab957d80bc2b9a9c1e71c804826d2f283dd65306542" dependencies = [ "serde", "serde_spanned", @@ -8127,20 +8506,20 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a76a9312f5ba4c2dec6b9161fdf25d87ad8a09256ccea5a556fef03c706a10f" +checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" dependencies = [ "serde", ] [[package]] name = "toml_edit" -version = "0.19.10" +version = "0.19.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2380d56e8670370eee6566b0bfd4265f65b3f432e8c6d85623f728d4fa31f739" +checksum = "f8123f27e969974a3dfba720fdb560be359f57b44302d280ba72e76a74480e8a" dependencies = [ - "indexmap", + "indexmap 2.0.0", "serde", "serde_spanned", "toml_datetime", @@ -8183,7 +8562,7 @@ checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" dependencies = [ "futures-core", "futures-util", - "indexmap", + "indexmap 1.9.3", "pin-project", "pin-project-lite", "rand", @@ -8222,13 +8601,13 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.25" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8803eee176538f94ae9a14b55b2804eb7e1441f8210b1c31290b3bccdccff73b" +checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" dependencies = [ "proc-macro2", "quote", - "syn 2.0.18", + "syn 2.0.28", ] [[package]] @@ -8318,14 +8697,14 @@ dependencies = [ "regex", "schemac", "serde", - "toml 0.7.4", + "toml 0.7.6", ] [[package]] name = "ucd-trie" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e79c4d996edb816c91e4308506774452e55e95c3c9de07b6729e17e15a5ef81" +checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" [[package]] name = "unicase" @@ -8344,9 +8723,9 @@ checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" [[package]] name = "unicode-ident" -version = "1.0.9" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0" +checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" [[package]] name = "unicode-normalization" @@ -8507,9 +8886,9 @@ dependencies = [ [[package]] name = "urlencoding" -version = "2.1.2" +version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8db7427f936968176eaa7cdf81b7f98b980b18495ec28f1b5791ac3bfe3eea9" +checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" [[package]] name = "user-avatar-upload-complete" @@ -8949,9 +9328,9 @@ dependencies = [ [[package]] name = "uuid" -version = "1.3.4" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa2982af2eec27de306107c027578ff7f423d65f7250e40ce0fea8f45248b81" +checksum = "79daa5ed5740825c40b389c5e50312b9c86df53fccd33f281df655642b43869d" dependencies = [ "getrandom", "serde", @@ -9017,7 +9396,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.18", + "syn 2.0.28", "wasm-bindgen-shared", ] @@ -9051,7 +9430,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.18", + "syn 2.0.28", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -9127,13 +9506,9 @@ dependencies = [ [[package]] name = "whoami" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c70234412ca409cc04e864e89523cb0fc37f5e1344ebed5a3ebf4192b6b9f68" -dependencies = [ - "wasm-bindgen", - "web-sys", -] +checksum = "22fc3756b8a9133049b26c7f61ab35416c130e8c09b660f5b3958b446f52cc50" [[package]] name = "winapi" @@ -9166,21 +9541,6 @@ dependencies = [ "windows-targets", ] -[[package]] -name = "windows-sys" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" -dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", -] - [[package]] name = "windows-sys" version = "0.48.0" @@ -9192,97 +9552,55 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.48.0" +version = "0.48.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" +checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" dependencies = [ - "windows_aarch64_gnullvm 0.48.0", - "windows_aarch64_msvc 0.48.0", - "windows_i686_gnu 0.48.0", - "windows_i686_msvc 0.48.0", - "windows_x86_64_gnu 0.48.0", - "windows_x86_64_gnullvm 0.48.0", - "windows_x86_64_msvc 0.48.0", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", ] -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" - [[package]] name = "windows_aarch64_gnullvm" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" -[[package]] -name = "windows_aarch64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" - [[package]] name = "windows_aarch64_msvc" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" -[[package]] -name = "windows_i686_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" - [[package]] name = "windows_i686_gnu" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" -[[package]] -name = "windows_i686_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" - [[package]] name = "windows_i686_msvc" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" -[[package]] -name = "windows_x86_64_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" - [[package]] name = "windows_x86_64_gnu" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" - [[package]] name = "windows_x86_64_gnullvm" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" -[[package]] -name = "windows_x86_64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" - [[package]] name = "windows_x86_64_msvc" version = "0.48.0" @@ -9291,9 +9609,9 @@ checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" [[package]] name = "winnow" -version = "0.4.7" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca0ace3845f0d96209f0375e6d367e3eb87eb65d27d445bdc9f1843a26f39448" +checksum = "acaaa1190073b2b101e15083c38ee8ec891b5e05cbee516521e94ec008f61e64" dependencies = [ "memchr", ] @@ -9339,5 +9657,5 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.18", + "syn 2.0.28", ] diff --git a/svc/Cargo.toml b/svc/Cargo.toml index aaf6159c54..df09b1629e 100644 --- a/svc/Cargo.toml +++ b/svc/Cargo.toml @@ -1,7 +1,7 @@ # This is generated by Bolt. Do not modify. [workspace] -members = ["api/cloud", "api/group", "api/route", "api/portal", "api/job", "api/cf-verification", "api/module", "api/identity", "api/admin", "api/matchmaker", "api/chat", "api/status", "api/kv", "api/auth", "pkg/push-notification/worker", "pkg/cdn/worker", "pkg/cdn/ops/ns-enable-domain-public-auth-set", "pkg/cdn/ops/namespace-get", "pkg/cdn/ops/version-get", "pkg/cdn/ops/namespace-create", "pkg/cdn/ops/namespace-domain-remove", "pkg/cdn/ops/namespace-auth-user-update", "pkg/cdn/ops/site-get", "pkg/cdn/ops/namespace-resolve-domain", "pkg/cdn/ops/version-publish", "pkg/cdn/ops/namespace-auth-user-remove", "pkg/cdn/ops/namespace-domain-create", "pkg/cdn/ops/site-list-for-game", "pkg/cdn/ops/version-prepare", "pkg/cdn/ops/site-create", "pkg/cdn/ops/ns-auth-type-set", "pkg/captcha/ops/hcaptcha-verify", "pkg/captcha/ops/verify", "pkg/captcha/ops/request", "pkg/captcha/ops/hcaptcha-config-get", "pkg/email-verification/ops/complete", "pkg/email-verification/ops/create", "pkg/team/worker", "pkg/team/standalone/billing-collect", "pkg/team/ops/member-get", "pkg/team/ops/member-relationship-get", "pkg/team/ops/resolve-display-name", "pkg/team/ops/profile-validate", "pkg/team/ops/user-ban-get", "pkg/team/ops/get", "pkg/team/ops/join-request-list", "pkg/team/ops/recommend", "pkg/team/ops/user-ban-list", "pkg/team/ops/search", "pkg/team/ops/avatar-upload-complete", "pkg/team/ops/validate", "pkg/team/ops/billing-aggregate", "pkg/team/ops/member-count", "pkg/team/ops/member-list", "pkg/cloud/worker", "pkg/cloud/ops/namespace-token-development-create", "pkg/cloud/ops/game-config-get", "pkg/cloud/ops/namespace-get", "pkg/cloud/ops/version-get", "pkg/cloud/ops/namespace-create", "pkg/cloud/ops/namespace-token-public-create", "pkg/cloud/ops/version-publish", "pkg/cloud/ops/game-config-create", "pkg/cloud/ops/game-token-create", "pkg/cloud/ops/device-link-create", "pkg/nomad-log/worker", "pkg/nomad-log/standalone/follower", "pkg/nomad-log/ops/read", "pkg/faker/ops/mm-player", "pkg/faker/ops/job-template", "pkg/faker/ops/team", "pkg/faker/ops/region", "pkg/faker/ops/game-version", "pkg/faker/ops/build", "pkg/faker/ops/cdn-site", "pkg/faker/ops/user", "pkg/faker/ops/mm-lobby", "pkg/faker/ops/game", "pkg/faker/ops/job-run", "pkg/faker/ops/game-namespace", "pkg/faker/ops/mm-lobby-row", "pkg/token/ops/get", "pkg/token/ops/exchange", "pkg/token/ops/create", "pkg/token/ops/revoke", "pkg/user-follow/worker", "pkg/user-follow/ops/relationship-get", "pkg/user-follow/ops/request-list", "pkg/user-follow/ops/get", "pkg/user-follow/ops/toggle", "pkg/user-follow/ops/count", "pkg/user-follow/ops/list", "pkg/user-notification-auth/ops/register", "pkg/user-notification-auth/ops/unregister", "pkg/chat-thread/worker", "pkg/chat-thread/ops/unread-count", "pkg/chat-thread/ops/participant-list", "pkg/chat-thread/ops/get", "pkg/chat-thread/ops/get-or-create-for-topic", "pkg/chat-thread/ops/list-for-participant", "pkg/chat-thread/ops/get-for-topic", "pkg/chat-thread/ops/recent-for-user", "pkg/region/ops/get", "pkg/region/ops/recommend", "pkg/region/ops/list", "pkg/region/ops/resolve", "pkg/user-dev/worker", "pkg/custom-user-avatar/ops/upload-complete", "pkg/custom-user-avatar/ops/list-for-game", "pkg/kv-config/ops/namespace-get", "pkg/kv-config/ops/version-get", "pkg/kv-config/ops/namespace-create", "pkg/kv-config/ops/version-publish", "pkg/kv-config/ops/version-prepare", "pkg/telemetry/standalone/beacon", "pkg/nsfw/ops/image-score", "pkg/build/standalone/default-create", "pkg/build/ops/get", "pkg/build/ops/list-for-game", "pkg/build/ops/create", "pkg/job/standalone/gc", "pkg/cf/ops/turnstile-verify", "pkg/analytics/worker", "pkg/team-invite/worker", "pkg/team-invite/ops/get", "pkg/misc/standalone/playground", "pkg/email/ops/send", "pkg/profanity/ops/check", "pkg/user-identity/ops/delete", "pkg/user-identity/ops/get", "pkg/user-identity/ops/create", "pkg/user/worker", "pkg/user/standalone/delete-pending", "pkg/user/standalone/search-user-gc", "pkg/user/ops/pending-delete-toggle", "pkg/user/ops/thread-typing-status-set", "pkg/user/ops/profile-validate", "pkg/user/ops/get", "pkg/user/ops/mutual-friend-list", "pkg/user/ops/search", "pkg/user/ops/resolve-email", "pkg/user/ops/token-create", "pkg/user/ops/avatar-upload-complete", "pkg/user/ops/team-list", "pkg/module/worker", "pkg/module/ops/game-version-get", "pkg/module/ops/version-get", "pkg/module/ops/game-version-publish", "pkg/module/ops/get", "pkg/module/ops/ns-instance-get", "pkg/module/ops/instance-call", "pkg/module/ops/instance-get", "pkg/module/ops/game-version-prepare", "pkg/team-dev/worker", "pkg/team-dev/standalone/halt-collect", "pkg/team-dev/ops/get", "pkg/team-dev/ops/halt", "pkg/team-dev/ops/game-list", "pkg/user-presence/worker", "pkg/user-presence/standalone/gc", "pkg/user-presence/ops/touch", "pkg/user-presence/ops/get", "pkg/mm/worker", "pkg/mm/standalone/gc", "pkg/mm/standalone/gc-full", "pkg/mm/ops/lobby-player-count", "pkg/mm/ops/lobby-idle-update", "pkg/mm/ops/player-count-for-namespace", "pkg/mm/ops/lobby-find-try-complete", "pkg/mm/ops/lobby-find-fail", "pkg/mm/ops/lobby-get", "pkg/mm/ops/player-get", "pkg/mm/ops/lobby-list-for-namespace", "pkg/mm/ops/lobby-find-lobby-query-list", "pkg/mm/ops/lobby-history", "pkg/mm/ops/lobby-runtime-aggregate", "pkg/mm/ops/dev-player-token-create", "pkg/ip/ops/info", "pkg/mm-config/ops/namespace-get", "pkg/mm-config/ops/version-get", "pkg/mm-config/ops/namespace-create", "pkg/mm-config/ops/lobby-group-resolve-version", "pkg/mm-config/ops/version-publish", "pkg/mm-config/ops/lobby-group-get", "pkg/mm-config/ops/version-prepare", "pkg/mm-config/ops/lobby-group-resolve-name-id", "pkg/mm-config/ops/namespace-config-set", "pkg/mm-config/ops/namespace-config-validate", "pkg/chat-message/worker", "pkg/chat-message/ops/body-validate", "pkg/chat-message/ops/create-with-topic", "pkg/chat-message/ops/get", "pkg/chat-message/ops/list-for-user", "pkg/chat-message/ops/list", "pkg/chat-message/ops/validate", "pkg/user-report/worker", "pkg/game/ops/namespace-resolve-name-id", "pkg/game/ops/namespace-get", "pkg/game/ops/version-get", "pkg/game/ops/namespace-resolve-url", "pkg/game/ops/namespace-create", "pkg/game/ops/version-create", "pkg/game/ops/namespace-version-history-list", "pkg/game/ops/resolve-name-id", "pkg/game/ops/get", "pkg/game/ops/token-development-validate", "pkg/game/ops/version-validate", "pkg/game/ops/recommend", "pkg/game/ops/namespace-validate", "pkg/game/ops/banner-upload-complete", "pkg/game/ops/resolve-namespace-id", "pkg/game/ops/namespace-version-set", "pkg/game/ops/list-all", "pkg/game/ops/validate", "pkg/game/ops/namespace-list", "pkg/game/ops/create", "pkg/game/ops/logo-upload-complete", "pkg/game/ops/version-list", "pkg/identity-config/ops/namespace-get", "pkg/identity-config/ops/version-get", "pkg/identity-config/ops/namespace-create", "pkg/identity-config/ops/version-publish", "pkg/identity-config/ops/version-prepare", "pkg/job-run/worker", "pkg/job-run/standalone/alloc-update-monitor", "pkg/job-run/standalone/alloc-plan-monitor", "pkg/job-run/standalone/eval-update-monitor", "pkg/job-run/ops/get", "pkg/job-run/ops/metrics-log", "pkg/chat/worker", "pkg/chat/ops/last-read-ts-get", "pkg/game-user/worker", "pkg/game-user/ops/recent-session-list", "pkg/game-user/ops/get", "pkg/game-user/ops/recommend", "pkg/game-user/ops/link-create", "pkg/game-user/ops/link-get", "pkg/game-user/ops/list-for-user", "pkg/game-user/ops/create", "pkg/debug/ops/email-res", "pkg/cf-custom-hostname/worker", "pkg/cf-custom-hostname/ops/resolve-hostname", "pkg/cf-custom-hostname/ops/get", "pkg/cf-custom-hostname/ops/list-for-namespace-id", "pkg/upload/worker", "pkg/upload/standalone/provider-fill", "pkg/upload/ops/complete", "pkg/upload/ops/file-list", "pkg/upload/ops/get", "pkg/upload/ops/prepare", "pkg/upload/ops/list-for-user", "pkg/kv/worker", "pkg/kv/ops/get", "pkg/kv/ops/list", "pkg/tier/ops/list", "pkg/perf/ops/log-get"] +members = ["api/cloud", "api/group", "api/route", "api/portal", "api/job", "api/cf-verification", "api/module", "api/identity", "api/admin", "api/matchmaker", "api/chat", "api/status", "api/kv", "api/auth", "pkg/push-notification/worker", "pkg/cdn/worker", "pkg/cdn/ops/ns-enable-domain-public-auth-set", "pkg/cdn/ops/namespace-get", "pkg/cdn/ops/version-get", "pkg/cdn/ops/namespace-create", "pkg/cdn/ops/namespace-domain-remove", "pkg/cdn/ops/namespace-auth-user-update", "pkg/cdn/ops/site-get", "pkg/cdn/ops/namespace-resolve-domain", "pkg/cdn/ops/version-publish", "pkg/cdn/ops/namespace-auth-user-remove", "pkg/cdn/ops/namespace-domain-create", "pkg/cdn/ops/site-list-for-game", "pkg/cdn/ops/version-prepare", "pkg/cdn/ops/site-create", "pkg/cdn/ops/ns-auth-type-set", "pkg/captcha/ops/hcaptcha-verify", "pkg/captcha/ops/verify", "pkg/captcha/ops/request", "pkg/captcha/ops/hcaptcha-config-get", "pkg/email-verification/ops/complete", "pkg/email-verification/ops/create", "pkg/team/worker", "pkg/team/standalone/billing-collect", "pkg/team/ops/member-get", "pkg/team/ops/member-relationship-get", "pkg/team/ops/resolve-display-name", "pkg/team/ops/profile-validate", "pkg/team/ops/user-ban-get", "pkg/team/ops/get", "pkg/team/ops/join-request-list", "pkg/team/ops/recommend", "pkg/team/ops/user-ban-list", "pkg/team/ops/search", "pkg/team/ops/avatar-upload-complete", "pkg/team/ops/validate", "pkg/team/ops/billing-aggregate", "pkg/team/ops/member-count", "pkg/team/ops/member-list", "pkg/cloud/worker", "pkg/cloud/ops/namespace-token-development-create", "pkg/cloud/ops/game-config-get", "pkg/cloud/ops/namespace-get", "pkg/cloud/ops/version-get", "pkg/cloud/ops/namespace-create", "pkg/cloud/ops/namespace-token-public-create", "pkg/cloud/ops/version-publish", "pkg/cloud/ops/game-config-create", "pkg/cloud/ops/game-token-create", "pkg/cloud/ops/device-link-create", "pkg/external/worker", "pkg/external/ops/request-validate", "pkg/nomad-log/worker", "pkg/nomad-log/standalone/follower", "pkg/nomad-log/ops/read", "pkg/faker/ops/mm-player", "pkg/faker/ops/job-template", "pkg/faker/ops/team", "pkg/faker/ops/region", "pkg/faker/ops/game-version", "pkg/faker/ops/build", "pkg/faker/ops/cdn-site", "pkg/faker/ops/user", "pkg/faker/ops/mm-lobby", "pkg/faker/ops/game", "pkg/faker/ops/job-run", "pkg/faker/ops/game-namespace", "pkg/faker/ops/mm-lobby-row", "pkg/token/ops/get", "pkg/token/ops/exchange", "pkg/token/ops/create", "pkg/token/ops/revoke", "pkg/user-follow/worker", "pkg/user-follow/ops/relationship-get", "pkg/user-follow/ops/request-list", "pkg/user-follow/ops/get", "pkg/user-follow/ops/toggle", "pkg/user-follow/ops/count", "pkg/user-follow/ops/list", "pkg/user-notification-auth/ops/register", "pkg/user-notification-auth/ops/unregister", "pkg/chat-thread/worker", "pkg/chat-thread/ops/unread-count", "pkg/chat-thread/ops/participant-list", "pkg/chat-thread/ops/get", "pkg/chat-thread/ops/get-or-create-for-topic", "pkg/chat-thread/ops/list-for-participant", "pkg/chat-thread/ops/get-for-topic", "pkg/chat-thread/ops/recent-for-user", "pkg/region/ops/get", "pkg/region/ops/recommend", "pkg/region/ops/list", "pkg/region/ops/resolve", "pkg/user-dev/worker", "pkg/custom-user-avatar/ops/upload-complete", "pkg/custom-user-avatar/ops/list-for-game", "pkg/kv-config/ops/namespace-get", "pkg/kv-config/ops/version-get", "pkg/kv-config/ops/namespace-create", "pkg/kv-config/ops/version-publish", "pkg/kv-config/ops/version-prepare", "pkg/telemetry/standalone/beacon", "pkg/nsfw/ops/image-score", "pkg/build/standalone/default-create", "pkg/build/ops/get", "pkg/build/ops/list-for-game", "pkg/build/ops/create", "pkg/job/standalone/gc", "pkg/cf/ops/turnstile-verify", "pkg/analytics/worker", "pkg/team-invite/worker", "pkg/team-invite/ops/get", "pkg/misc/standalone/playground", "pkg/email/ops/send", "pkg/profanity/ops/check", "pkg/user-identity/ops/delete", "pkg/user-identity/ops/get", "pkg/user-identity/ops/create", "pkg/user/worker", "pkg/user/standalone/delete-pending", "pkg/user/standalone/search-user-gc", "pkg/user/ops/pending-delete-toggle", "pkg/user/ops/thread-typing-status-set", "pkg/user/ops/profile-validate", "pkg/user/ops/get", "pkg/user/ops/mutual-friend-list", "pkg/user/ops/search", "pkg/user/ops/resolve-email", "pkg/user/ops/token-create", "pkg/user/ops/avatar-upload-complete", "pkg/user/ops/team-list", "pkg/module/worker", "pkg/module/ops/game-version-get", "pkg/module/ops/version-get", "pkg/module/ops/game-version-publish", "pkg/module/ops/get", "pkg/module/ops/ns-instance-get", "pkg/module/ops/instance-call", "pkg/module/ops/instance-get", "pkg/module/ops/game-version-prepare", "pkg/team-dev/worker", "pkg/team-dev/standalone/halt-collect", "pkg/team-dev/ops/get", "pkg/team-dev/ops/halt", "pkg/team-dev/ops/game-list", "pkg/user-presence/worker", "pkg/user-presence/standalone/gc", "pkg/user-presence/ops/touch", "pkg/user-presence/ops/get", "pkg/mm/worker", "pkg/mm/standalone/gc", "pkg/mm/standalone/gc-full", "pkg/mm/ops/lobby-player-count", "pkg/mm/ops/lobby-idle-update", "pkg/mm/ops/player-count-for-namespace", "pkg/mm/ops/lobby-find-try-complete", "pkg/mm/ops/lobby-find-fail", "pkg/mm/ops/lobby-get", "pkg/mm/ops/player-get", "pkg/mm/ops/lobby-list-for-namespace", "pkg/mm/ops/lobby-find-lobby-query-list", "pkg/mm/ops/lobby-history", "pkg/mm/ops/lobby-runtime-aggregate", "pkg/mm/ops/dev-player-token-create", "pkg/mm/ops/lobby-list-for-user-id", "pkg/ip/ops/info", "pkg/mm-config/ops/namespace-get", "pkg/mm-config/ops/version-get", "pkg/mm-config/ops/namespace-create", "pkg/mm-config/ops/lobby-group-resolve-version", "pkg/mm-config/ops/version-publish", "pkg/mm-config/ops/lobby-group-get", "pkg/mm-config/ops/version-prepare", "pkg/mm-config/ops/lobby-group-resolve-name-id", "pkg/mm-config/ops/namespace-config-set", "pkg/mm-config/ops/namespace-config-validate", "pkg/chat-message/worker", "pkg/chat-message/ops/body-validate", "pkg/chat-message/ops/create-with-topic", "pkg/chat-message/ops/get", "pkg/chat-message/ops/list-for-user", "pkg/chat-message/ops/list", "pkg/chat-message/ops/validate", "pkg/user-report/worker", "pkg/game/ops/namespace-resolve-name-id", "pkg/game/ops/namespace-get", "pkg/game/ops/version-get", "pkg/game/ops/namespace-resolve-url", "pkg/game/ops/namespace-create", "pkg/game/ops/version-create", "pkg/game/ops/namespace-version-history-list", "pkg/game/ops/resolve-name-id", "pkg/game/ops/get", "pkg/game/ops/token-development-validate", "pkg/game/ops/version-validate", "pkg/game/ops/recommend", "pkg/game/ops/namespace-validate", "pkg/game/ops/banner-upload-complete", "pkg/game/ops/resolve-namespace-id", "pkg/game/ops/namespace-version-set", "pkg/game/ops/list-all", "pkg/game/ops/validate", "pkg/game/ops/namespace-list", "pkg/game/ops/create", "pkg/game/ops/logo-upload-complete", "pkg/game/ops/version-list", "pkg/identity-config/ops/namespace-get", "pkg/identity-config/ops/version-get", "pkg/identity-config/ops/namespace-create", "pkg/identity-config/ops/version-publish", "pkg/identity-config/ops/version-prepare", "pkg/job-run/worker", "pkg/job-run/standalone/alloc-update-monitor", "pkg/job-run/standalone/alloc-plan-monitor", "pkg/job-run/standalone/eval-update-monitor", "pkg/job-run/ops/get", "pkg/job-run/ops/metrics-log", "pkg/chat/worker", "pkg/chat/ops/last-read-ts-get", "pkg/game-user/worker", "pkg/game-user/ops/recent-session-list", "pkg/game-user/ops/get", "pkg/game-user/ops/recommend", "pkg/game-user/ops/link-create", "pkg/game-user/ops/link-get", "pkg/game-user/ops/list-for-user", "pkg/game-user/ops/create", "pkg/debug/ops/email-res", "pkg/cf-custom-hostname/worker", "pkg/cf-custom-hostname/ops/resolve-hostname", "pkg/cf-custom-hostname/ops/get", "pkg/cf-custom-hostname/ops/list-for-namespace-id", "pkg/upload/worker", "pkg/upload/standalone/provider-fill", "pkg/upload/ops/complete", "pkg/upload/ops/file-list", "pkg/upload/ops/get", "pkg/upload/ops/prepare", "pkg/upload/ops/list-for-user", "pkg/kv/worker", "pkg/kv/ops/get", "pkg/kv/ops/list", "pkg/tier/ops/list", "pkg/perf/ops/log-get"] # Speed up compilation [profile.dev] diff --git a/svc/api/admin/Cargo.toml b/svc/api/admin/Cargo.toml index b113ac624d..885dae3e39 100644 --- a/svc/api/admin/Cargo.toml +++ b/svc/api/admin/Cargo.toml @@ -27,7 +27,7 @@ s3-util = { path = "../../../lib/s3-util" } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" thiserror = "1.0" -tokio = { version = "1.21" } +tokio = { version = "1.29" } tracing = "0.1" tracing-futures = "0.2" tracing-subscriber = { version = "0.3", default-features = false, features = ["fmt", "json", "ansi"] } diff --git a/svc/api/admin/src/auth.rs b/svc/api/admin/src/auth.rs index d7313b00e5..44c06adb3c 100644 --- a/svc/api/admin/src/auth.rs +++ b/svc/api/admin/src/auth.rs @@ -23,9 +23,11 @@ impl ApiAuth for Auth { API_FORBIDDEN, reason = "Invalid auth" ); - } - Ok(Auth { _claims: None }) + Ok(Auth { _claims: None }) + } else { + internal_panic!("unreachable"); + } } async fn rate_limit(_rate_limit_ctx: AuthRateLimitCtx<'_>) -> GlobalResult<()> { diff --git a/svc/api/auth/Cargo.toml b/svc/api/auth/Cargo.toml index 8a6d905749..9b167b29cc 100644 --- a/svc/api/auth/Cargo.toml +++ b/svc/api/auth/Cargo.toml @@ -24,7 +24,7 @@ rivet-pools = { path = "../../../lib/pools" } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" thiserror = "1.0" -tokio = { version = "1.21" } +tokio = { version = "1.29" } tracing = "0.1" tracing-subscriber = { version = "0.3", default-features = false, features = ["fmt", "json", "ansi"] } url = "2.2.2" diff --git a/svc/api/cf-verification/Cargo.toml b/svc/api/cf-verification/Cargo.toml index ceb3b9e93a..6d267634f7 100644 --- a/svc/api/cf-verification/Cargo.toml +++ b/svc/api/cf-verification/Cargo.toml @@ -24,7 +24,7 @@ rivet-pools = { path = "../../../lib/pools" } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" thiserror = "1.0" -tokio = { version = "1.21" } +tokio = { version = "1.29" } tracing = "0.1" tracing-subscriber = { version = "0.3", default-features = false, features = ["fmt", "json", "ansi"] } url = "2.2.2" diff --git a/svc/api/chat/Cargo.toml b/svc/api/chat/Cargo.toml index 84b210c7c8..0b3fa8dfad 100644 --- a/svc/api/chat/Cargo.toml +++ b/svc/api/chat/Cargo.toml @@ -25,7 +25,7 @@ rivet-pools = { path = "../../../lib/pools" } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" thiserror = "1.0" -tokio = { version = "1.21" } +tokio = { version = "1.29" } tracing = "0.1" tracing-subscriber = { version = "0.3", default-features = false, features = ["fmt", "json", "ansi"] } url = "2.2.2" diff --git a/svc/api/cloud/Cargo.toml b/svc/api/cloud/Cargo.toml index 10c31222b1..962a31430d 100644 --- a/svc/api/cloud/Cargo.toml +++ b/svc/api/cloud/Cargo.toml @@ -29,7 +29,7 @@ rivet-pools = { path = "../../../lib/pools" } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" thiserror = "1.0" -tokio = { version = "1.21" } +tokio = { version = "1.29" } tracing = "0.1" tracing-subscriber = { version = "0.3", default-features = false, features = ["fmt", "json", "ansi"] } url = "2.2.2" diff --git a/svc/api/cloud/src/route/games/builds.rs b/svc/api/cloud/src/route/games/builds.rs index 13377299d6..644b507fb1 100644 --- a/svc/api/cloud/src/route/games/builds.rs +++ b/svc/api/cloud/src/route/games/builds.rs @@ -76,29 +76,45 @@ pub async fn create_build( // TODO: Read and validate image file + let multipart_upload = body.multipart_upload.unwrap_or(false); + let create_res = op!([ctx] build_create { game_id: Some(game_id.into()), display_name: body.display_name, image_tag: Some(body.image_tag), image_file: Some((*body.image_file).try_into()?), + multipart: multipart_upload, ..Default::default() }) .await?; - Ok(new_models::CloudGamesCreateGameBuildResponse { - build_id: internal_unwrap!(create_res.build_id).as_uuid(), - upload_id: internal_unwrap!(create_res.upload_id).as_uuid(), - // Deprecated - image_presigned_request: Box::new( + let image_presigned_request = if !multipart_upload { + Some(Box::new( internal_unwrap_owned!(create_res.image_presigned_requests.first()) .clone() .try_into()?, - ), - image_presigned_requests: create_res - .image_presigned_requests - .iter() - .cloned() - .map(ApiTryInto::try_into) - .collect::>>()?, + )) + } else { + None + }; + + let image_presigned_requests = if multipart_upload { + Some( + create_res + .image_presigned_requests + .iter() + .cloned() + .map(ApiTryInto::try_into) + .collect::>>()?, + ) + } else { + None + }; + + Ok(new_models::CloudGamesCreateGameBuildResponse { + build_id: internal_unwrap!(create_res.build_id).as_uuid(), + upload_id: internal_unwrap!(create_res.upload_id).as_uuid(), + image_presigned_request, + image_presigned_requests, }) } diff --git a/svc/api/cloud/src/route/games/matchmaker.rs b/svc/api/cloud/src/route/games/matchmaker.rs index 10bfaf1388..29314b16e6 100644 --- a/svc/api/cloud/src/route/games/matchmaker.rs +++ b/svc/api/cloud/src/route/games/matchmaker.rs @@ -23,6 +23,7 @@ pub async fn delete_lobby( let lobby_get_res = op!([ctx] mm_lobby_get { lobby_ids: vec![lobby_id.into()], include_stopped: false, + include_private: true, }) .await?; @@ -261,6 +262,7 @@ async fn get_alloc_id( let lobby_res = op!([ctx] mm_lobby_get { lobby_ids: vec![lobby_id.into()], include_stopped: true, + include_private: true, }) .await?; let lobby = unwrap_with_owned!(lobby_res.lobbies.first(), MATCHMAKER_LOBBY_NOT_FOUND); diff --git a/svc/api/cloud/src/route/games/mod.rs b/svc/api/cloud/src/route/games/mod.rs index c19fe0f2f9..7f0c792307 100644 --- a/svc/api/cloud/src/route/games/mod.rs +++ b/svc/api/cloud/src/route/games/mod.rs @@ -177,6 +177,7 @@ async fn gen_default_version_config( max_players_normal: 32, max_players_direct: 32, max_players_party: 32, + listable: true, runtime: Some( backend::matchmaker::lobby_runtime::Docker { @@ -200,6 +201,10 @@ async fn gen_default_version_config( } .into(), ), + + find_config: None, + join_config: None, + create_config: None, }], captcha: None, }), diff --git a/svc/api/cloud/src/route/games/namespaces/analytics.rs b/svc/api/cloud/src/route/games/namespaces/analytics.rs index d97ef8c7c7..3021cd440d 100644 --- a/svc/api/cloud/src/route/games/namespaces/analytics.rs +++ b/svc/api/cloud/src/route/games/namespaces/analytics.rs @@ -34,6 +34,7 @@ pub async fn matchmaker_live( op!([ctx] mm_lobby_get { lobby_ids: lobby_ids.clone(), include_stopped: false, + include_private: true, }), op!([ctx] mm_lobby_player_count { lobby_ids: lobby_ids.clone(), diff --git a/svc/api/cloud/src/route/games/namespaces/logs.rs b/svc/api/cloud/src/route/games/namespaces/logs.rs index 42050afa70..99cffd87f8 100644 --- a/svc/api/cloud/src/route/games/namespaces/logs.rs +++ b/svc/api/cloud/src/route/games/namespaces/logs.rs @@ -125,6 +125,7 @@ async fn fetch_lobby_logs(ctx: &Ctx, lobby_ids: Vec) -> GlobalResult .map(|x| Into::into(*x)) .collect(), include_stopped: true, + include_private: true, }) .await?; let mut lobbies = lobby_res.lobbies.iter().collect::>(); diff --git a/svc/api/cloud/tests/basic.rs b/svc/api/cloud/tests/basic.rs index 4c674be3f1..322b7b2469 100644 --- a/svc/api/cloud/tests/basic.rs +++ b/svc/api/cloud/tests/basic.rs @@ -527,6 +527,11 @@ async fn generic() { region_id: Some(primary_region_id.into()), create_ray_id: None, preemptively_created: false, + + creator_user_id: None, + is_custom: false, + publicity: None, + lobby_config_json: None, }) .await .unwrap(); diff --git a/svc/api/group/Cargo.toml b/svc/api/group/Cargo.toml index c5791e5fc2..9bbb657332 100644 --- a/svc/api/group/Cargo.toml +++ b/svc/api/group/Cargo.toml @@ -25,7 +25,7 @@ rivet-pools = { path = "../../../lib/pools" } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" thiserror = "1.0" -tokio = { version = "1.21" } +tokio = { version = "1.29" } tracing = "0.1" tracing-subscriber = { version = "0.3", default-features = false, features = ["fmt", "json", "ansi"] } url = "2.2.2" diff --git a/svc/api/identity/Cargo.toml b/svc/api/identity/Cargo.toml index e0ecac2912..e7bb2dce65 100644 --- a/svc/api/identity/Cargo.toml +++ b/svc/api/identity/Cargo.toml @@ -24,7 +24,7 @@ rivet-pools = { path = "../../../lib/pools" } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" thiserror = "1.0" -tokio = { version = "1.21" } +tokio = { version = "1.29" } tracing = "0.1" tracing-subscriber = { version = "0.3", default-features = false, features = ["fmt", "json", "ansi"] } url = "2.2.2" diff --git a/svc/api/identity/src/route/events.rs b/svc/api/identity/src/route/events.rs index 076f6e7cf5..aad9da6ca0 100644 --- a/svc/api/identity/src/route/events.rs +++ b/svc/api/identity/src/route/events.rs @@ -388,6 +388,7 @@ async fn process_mm_lobby_events( .filter_map(|(_, x)| x.lobby_id) .collect(), include_stopped: true, + include_private: true, }) .await?; diff --git a/svc/api/identity/src/route/identities.rs b/svc/api/identity/src/route/identities.rs index 6c1b7206fb..0765379e39 100644 --- a/svc/api/identity/src/route/identities.rs +++ b/svc/api/identity/src/route/identities.rs @@ -206,7 +206,10 @@ async fn attempt_setup_existing_identity_token( .await?; // Fetch user data - let user_id = utils::resolve_user_with_game_user_id(ctx, game_user_ent.game_user_id).await?; + let Some(user_id) = utils::resolve_user_with_game_user_id(ctx, game_user_ent.game_user_id).await? else { + tracing::info!("game user not found"); + return Ok(None); + }; utils::touch_user_presence(ctx.op_ctx().base(), user_id, false); let (identities, game_resolve_res) = tokio::try_join!( @@ -499,16 +502,14 @@ pub async fn set_game_activity( game_activity: Some(backend::user::presence::GameActivity { game_id: Some(game_user.game_id.into()), message: body.game_activity.message.unwrap_or_default(), - // TODO: - public_metadata: None, friend_metadata: None, - // public_metadata: body.game_activity - // .public_metadata - // .map(|public_metadata| serde_json::to_string(&public_metadata)) - // .transpose()?, - // friend_metadata: body.game_activity - // .mutual_metadata - // .map(|mutual_metadata| serde_json::to_string(&mutual_metadata)) - // .transpose()?, + public_metadata: body.game_activity + .public_metadata + .map(|public_metadata| serde_json::to_string(&public_metadata)) + .transpose()?, + friend_metadata: body.game_activity + .mutual_metadata + .map(|mutual_metadata| serde_json::to_string(&mutual_metadata)) + .transpose()?, }), }) .await?; diff --git a/svc/api/identity/src/utils.rs b/svc/api/identity/src/utils.rs index b4a87c3101..2538a15853 100644 --- a/svc/api/identity/src/utils.rs +++ b/svc/api/identity/src/utils.rs @@ -81,14 +81,16 @@ pub async fn get_namespace_id(ctx: &Ctx) -> GlobalResult { pub async fn resolve_user_with_game_user_id( ctx: &Ctx, game_user_id: Uuid, -) -> GlobalResult { +) -> GlobalResult> { let game_user_res = op!([ctx] game_user_get { game_user_ids: vec![game_user_id.into()] }) .await?; - let game_user = internal_unwrap_owned!(game_user_res.game_users.first()).clone(); + let Some(game_user) = game_user_res.game_users.first().clone() else { + return Ok(None) + }; - Ok(internal_unwrap!(game_user.user_id).as_uuid()) + Ok(Some(internal_unwrap!(game_user.user_id).as_uuid())) } pub fn touch_user_presence(ctx: OperationContext<()>, user_id: Uuid, silent: bool) { diff --git a/svc/api/identity/tests/basic.rs b/svc/api/identity/tests/basic.rs index fdf9b39e5d..12f261ea16 100644 --- a/svc/api/identity/tests/basic.rs +++ b/svc/api/identity/tests/basic.rs @@ -127,6 +127,7 @@ impl Ctx { max_players_normal: 8, max_players_direct: 10, max_players_party: 12, + listable: true, runtime: Some(backend::matchmaker::lobby_runtime::Docker { build_id: build_res.build_id, @@ -157,6 +158,10 @@ impl Ctx { }, ], }.into()), + + find_config: None, + join_config: None, + create_config: None, }], }), ..Default::default() diff --git a/svc/api/job/Cargo.toml b/svc/api/job/Cargo.toml index 8e809daf93..b53305d27b 100644 --- a/svc/api/job/Cargo.toml +++ b/svc/api/job/Cargo.toml @@ -23,7 +23,7 @@ rivet-pools = { path = "../../../lib/pools" } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" thiserror = "1.0" -tokio = { version = "1.21" } +tokio = { version = "1.29" } tracing = "0.1" tracing-subscriber = { version = "0.3", default-features = false, features = ["fmt", "json", "ansi"] } url = "2.2.2" diff --git a/svc/api/kv/Cargo.toml b/svc/api/kv/Cargo.toml index c315b12f04..2af83b60a0 100644 --- a/svc/api/kv/Cargo.toml +++ b/svc/api/kv/Cargo.toml @@ -26,7 +26,7 @@ rivet-pools = { path = "../../../lib/pools" } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" thiserror = "1.0" -tokio = { version = "1.21" } +tokio = { version = "1.29" } tracing = "0.1" tracing-subscriber = { version = "0.3", default-features = false, features = ["fmt", "json", "ansi"] } url = "2.2.2" diff --git a/svc/api/kv/src/auth.rs b/svc/api/kv/src/auth.rs index 416938e612..d577351ee7 100644 --- a/svc/api/kv/src/auth.rs +++ b/svc/api/kv/src/auth.rs @@ -104,6 +104,7 @@ impl Auth { let lobbies_res = op!([ctx] mm_lobby_get { lobby_ids: vec![lobby_ent.lobby_id.into()], include_stopped: false, + include_private: true, }) .await?; diff --git a/svc/api/kv/src/route/mod.rs b/svc/api/kv/src/route/mod.rs index a07de78553..d849fd9a94 100644 --- a/svc/api/kv/src/route/mod.rs +++ b/svc/api/kv/src/route/mod.rs @@ -22,17 +22,59 @@ define_router! { cors: CorsConfigBuilder::public().build(), routes: { "entries": { - GET: operations::get(query: operations::SingleQuery), - PUT: operations::put(body: models::KvPutRequest), - DELETE: operations::delete(query: operations::SingleQuery), + GET: operations::get( + query: operations::SingleQuery, + rate_limit: { + buckets: [ + { count: 1_000_000 }, + ], + }, + ), + PUT: operations::put( + body: models::KvPutRequest, + rate_limit: { + buckets: [ + { count: 100_000 }, + ], + }, + ), + DELETE: operations::delete( + query: operations::SingleQuery, + rate_limit: { + buckets: [ + { count: 100_000 }, + ], + }, + ), }, "entries" / "list": { GET: operations::list(query: operations::ListQuery), }, "entries" / "batch": { - GET: batch_operations::get_batch(query: batch_operations::BatchQuery), - PUT: batch_operations::put_batch(body: models::KvPutBatchRequest), - DELETE: batch_operations::delete_batch(query: batch_operations::BatchQuery), + GET: batch_operations::get_batch( + query: batch_operations::BatchQuery, + rate_limit: { + buckets: [ + { count: 1_000_000 }, + ], + }, + ), + PUT: batch_operations::put_batch( + body: models::KvPutBatchRequest, + rate_limit: { + buckets: [ + { count: 100_000 }, + ], + }, + ), + DELETE: batch_operations::delete_batch( + query: batch_operations::BatchQuery, + rate_limit: { + buckets: [ + { count: 100_000 }, + ], + }, + ), }, }, } diff --git a/svc/api/kv/tests/basic.rs b/svc/api/kv/tests/basic.rs index b189831ddb..e6932b3b40 100644 --- a/svc/api/kv/tests/basic.rs +++ b/svc/api/kv/tests/basic.rs @@ -86,6 +86,11 @@ impl Ctx { region_id: Some(self.primary_region_id.into()), create_ray_id: None, preemptively_created: false, + + creator_user_id: None, + is_custom: false, + publicity: None, + lobby_config_json: None, }) .await .unwrap(); @@ -156,6 +161,7 @@ impl Ctx { max_players_normal: 8, max_players_direct: 10, max_players_party: 12, + listable: true, runtime: Some(backend::matchmaker::lobby_runtime::Docker { build_id: build_res.build_id, @@ -186,6 +192,10 @@ impl Ctx { }, ], }.into()), + + find_config: None, + join_config: None, + create_config: None, }], }), ..Default::default() diff --git a/svc/api/matchmaker/Cargo.toml b/svc/api/matchmaker/Cargo.toml index 10dfbd2ade..8e836f6ba1 100644 --- a/svc/api/matchmaker/Cargo.toml +++ b/svc/api/matchmaker/Cargo.toml @@ -25,7 +25,7 @@ rivet-pools = { path = "../../../lib/pools" } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" thiserror = "1.0" -tokio = { version = "1.21" } +tokio = { version = "1.29" } tracing = "0.1" tracing-subscriber = { version = "0.3", default-features = false, features = ["fmt", "json", "ansi"] } url = "2.2.2" @@ -37,6 +37,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-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" } mm-config-lobby-group-resolve-version = { path = "../../pkg/mm-config/ops/lobby-group-resolve-version" } @@ -49,6 +50,8 @@ region-get = { path = "../../pkg/region/ops/get" } region-recommend = { path = "../../pkg/region/ops/recommend" } region-resolve = { path = "../../pkg/region/ops/resolve" } token-create = { path = "../../pkg/token/ops/create" } +token-revoke = { path = "../../pkg/token/ops/revoke" } +user-identity-get = { path = "../../pkg/user-identity/ops/get" } [dev-dependencies] reqwest = "0.11" diff --git a/svc/api/matchmaker/src/auth.rs b/svc/api/matchmaker/src/auth.rs index 5f8eb016e7..62b8e1a168 100644 --- a/svc/api/matchmaker/src/auth.rs +++ b/svc/api/matchmaker/src/auth.rs @@ -110,4 +110,34 @@ impl Auth { Ok(None) } } + + pub async fn fetch_game_user_option( + &self, + ctx: &OperationContext<()>, + ) -> GlobalResult> { + if let Ok(claims) = self.claims() { + if let Ok(game_user_ent) = claims.as_game_user() { + let game_user_res = op!([ctx] game_user_get { + game_user_ids: vec![game_user_ent.game_user_id.into()] + }) + .await?; + let game_user = internal_unwrap_owned!(game_user_res.game_users.first()); + + // Verify that game user is not deleted + if game_user.deleted_ts.is_some() { + let jti = internal_unwrap_owned!(claims.jti); + op!([ctx] token_revoke { + jtis: vec![jti], + }) + .await?; + + panic_with!(TOKEN_REVOKED); + } + + return Ok(Some(internal_unwrap!(game_user.user_id).as_uuid())); + } + } + + Ok(None) + } } diff --git a/svc/api/matchmaker/src/route/lobbies.rs b/svc/api/matchmaker/src/route/lobbies.rs index f6475bcb83..54cd601371 100644 --- a/svc/api/matchmaker/src/route/lobbies.rs +++ b/svc/api/matchmaker/src/route/lobbies.rs @@ -1,3 +1,8 @@ +use std::{ + collections::{HashMap, HashSet}, + str::FromStr, +}; + use api_helper::{anchor::WatchIndexQuery, ctx::Ctx}; use proto::{ backend::{self, pkg::*}, @@ -7,10 +12,6 @@ use rivet_api::models; use rivet_convert::ApiTryInto; use rivet_operation::prelude::*; use serde_json::json; -use std::{ - collections::{HashMap, HashSet}, - str::FromStr, -}; use crate::{ auth::Auth, @@ -66,7 +67,15 @@ pub async fn join( lobby, ports, player, - } = find_inner(&ctx, &ns_data, find_query, body.captcha).await?; + } = find_inner( + &ctx, + &ns_data, + find_query, + None, + body.captcha, + VerificationType::UserData(body.verification_data.flatten()), + ) + .await?; Ok(models::MatchmakerJoinLobbyResponse { lobby, @@ -128,56 +137,9 @@ pub async fn find( }) .collect::>>()?; - // Resolve the region IDs. - // - // `region_ids` represents the requested regions in order of priority. - let region_ids = if let Some(region_name_ids) = body.regions { - // Resolve the region ID corresponding to the name IDs - let resolve_res = op!([ctx] region_resolve { - name_ids: region_name_ids.clone(), - }) - .await?; - - // Map to region IDs and decide - let region_ids = region_name_ids - .iter() - .flat_map(|name_id| resolve_res.regions.iter().find(|r| r.name_id == *name_id)) - .flat_map(|r| r.region_id.as_ref()) - .map(common::Uuid::as_uuid) - .collect::>(); - - internal_assert_eq!(region_ids.len(), region_name_ids.len(), "region not found"); - - region_ids - } else { - // Find all enabled region IDs in all requested lobby groups - let enabled_region_ids = lobby_groups - .iter() - .flat_map(|(lg, _)| { - lg.regions - .iter() - .filter_map(|r| r.region_id.as_ref()) - .map(common::Uuid::as_uuid) - .collect::>() - }) - .collect::>() - .into_iter() - .map(Into::::into) - .collect::>(); - - // Auto-select the closest region - let recommend_res = op!([ctx] region_recommend { - latitude: Some(lat), - longitude: Some(long), - region_ids: enabled_region_ids, - ..Default::default() - }) - .await?; - let primary_region = internal_unwrap_owned!(recommend_res.regions.first()); - let primary_region_id = internal_unwrap!(primary_region.region_id).as_uuid(); - - vec![primary_region_id] - }; + // Resolve region IDs + let region_ids = + resolve_region_ids(&ctx, lat, long, body.regions.as_ref(), &lobby_groups).await?; // Validate that there is a lobby group and region pair that is valid. // @@ -220,7 +182,7 @@ pub async fn find( let auto_create = if let Some(auto_create) = auto_create { auto_create } else { - internal_panic!("no valid lobby group and region id pair found for auto-create"); + panic_with!(MATCHMAKER_AUTO_CREATE_FAILED); }; // Build query and find lobby @@ -245,7 +207,15 @@ pub async fn find( lobby, ports, player, - } = find_inner(&ctx, &ns_data, find_query, body.captcha).await?; + } = find_inner( + &ctx, + &ns_data, + find_query, + None, + body.captcha, + VerificationType::UserData(body.verification_data.flatten()), + ) + .await?; Ok(models::MatchmakerFindLobbyResponse { lobby, @@ -254,6 +224,150 @@ pub async fn find( }) } +// MARK: POST /lobbies/create +pub async fn create( + ctx: Ctx, + body: models::MatchmakerLobbiesCreateRequest, +) -> GlobalResult { + let (lat, long) = internal_unwrap_owned!(ctx.coords()); + + // Mock response + if let Some(ns_dev_ent) = ctx.auth().game_ns_dev_option()? { + let FindResponse { + lobby, + ports, + player, + } = dev_mock_lobby(&ctx, &ns_dev_ent).await?; + return Ok(models::MatchmakerCreateLobbyResponse { + lobby, + ports, + player, + }); + } + + // Verify bearer auth and get user ID + let (game_ns, user_id) = tokio::try_join!( + ctx.auth().game_ns(&ctx), + ctx.auth().fetch_game_user_option(ctx.op_ctx()), + )?; + let ns_data = fetch_ns(&ctx, &game_ns).await?; + + // Fetch version config + let version_config_res = op!([ctx] mm_config_version_get { + version_ids: vec![ns_data.version_id.into()], + }) + .await?; + let version_data = internal_unwrap_owned!(version_config_res.versions.first()); + let version_config = internal_unwrap!(version_data.config); + let version_meta = internal_unwrap!(version_data.config_meta); + + // Find lobby groups that match the requested game mode + let (lobby_group, lobby_group_meta) = unwrap_with_owned!( + version_config + .lobby_groups + .iter() + .zip(version_meta.lobby_groups.iter()) + .find(|(lgc, _)| lgc.name_id == body.game_mode), + MATCHMAKER_GAME_MODE_NOT_FOUND + ); + + let publicity = match body.publicity { + models::MatchmakerCustomLobbyPublicity::Public => { + backend::matchmaker::lobby::Publicity::Public + } + models::MatchmakerCustomLobbyPublicity::Private => { + backend::matchmaker::lobby::Publicity::Private + } + }; + + // Verify that lobby creation is enabled and user can create a lobby + util_mm::verification::verify_config( + ctx.op_ctx(), + &util_mm::verification::VerifyConfigOpts { + kind: util_mm::verification::ConnectionKind::Create, + namespace_id: ns_data.namespace_id, + user_id, + lobby_group, + lobby_group_meta, + lobby_state: None, + verification_data_json: body + .verification_data + .as_ref() + .map(|o| o.as_ref().map(serde_json::to_string)) + .flatten() + .transpose()? + .as_ref(), + lobby_config_json: body + .lobby_config + .as_ref() + .map(|o| o.as_ref().map(serde_json::to_string)) + .flatten() + .transpose()? + .as_ref(), + custom_lobby_publicity: Some(publicity), + }, + ) + .await?; + + // Resolve region IDs + let region_ids = resolve_region_ids( + &ctx, + lat, + long, + body.region.map(|r| vec![r]).as_ref(), + &[(lobby_group, lobby_group_meta)], + ) + .await?; + let region_id = *unwrap_with_owned!(region_ids.first(), MATCHMAKER_REGION_NOT_FOUND); + + let lobby_id = Uuid::new_v4(); + let lobby_create_res = + msg!([ctx] mm::msg::lobby_create(lobby_id) -> mm::msg::lobby_create_complete { + lobby_id: Some(lobby_id.into()), + namespace_id: Some(ns_data.namespace_id.into()), + lobby_group_id: lobby_group_meta.lobby_group_id, + region_id: Some(region_id.into()), + create_ray_id: Some(ctx.op_ctx().ray_id().into()), + preemptively_created: false, + + creator_user_id: user_id.map(Into::into), + is_custom: true, + publicity: Some(publicity as i32), + lobby_config_json: body.lobby_config + .as_ref() + .map(serde_json::to_string) + .transpose()?, + }) + .await?; + + // Join the lobby that was just created + let find_query = + mm::msg::lobby_find::message::Query::Direct(backend::matchmaker::query::Direct { + lobby_id: lobby_create_res.lobby_id, + }); + let FindResponse { + lobby, + ports, + player, + } = find_inner( + &ctx, + &ns_data, + find_query, + Some(version_config.clone()), + body.captcha, + VerificationType::Bypass, + ) + .await?; + + // TODO: Cleanup lobby if find failed + + Ok(models::MatchmakerCreateLobbyResponse { + lobby, + ports, + player, + }) +} + // MARK: GET /lobbies/list pub async fn list( ctx: Ctx, @@ -305,8 +419,13 @@ pub async fn list( None } }) - // Filter out empty lobbies - .filter(|(lobby, _)| { + // Filter out empty and unlistable lobbies + .filter(|(lobby, lobby_group)| { + // Hide if not listable + if !lobby_group.listable { + return false; + } + // Keep if lobby not empty if lobby.player_count.registered_player_count != 0 { return true; @@ -356,76 +475,6 @@ pub async fn list( }) } -async fn dev_mock_lobby_list( - ctx: &Ctx, - ns_dev_ent: &rivet_claims::ent::GameNamespaceDevelopment, -) -> GlobalResult { - // Read the version config - let ns_res = op!([ctx] game_namespace_get { - namespace_ids: vec![ns_dev_ent.namespace_id.into()], - }) - .await?; - let ns_data = internal_unwrap_owned!(ns_res.namespaces.first()); - let version_id = internal_unwrap!(ns_data.version_id).as_uuid(); - - let version_res = op!([ctx] mm_config_version_get { - version_ids: vec![version_id.into()], - }) - .await?; - let version = internal_unwrap_owned!( - version_res.versions.first(), - "no matchmaker config for namespace" - ); - let version_config = internal_unwrap!(version.config); - - // Create fake region - let region = models::MatchmakerRegionInfo { - region_id: util_mm::consts::DEV_REGION_ID.into(), - provider_display_name: util_mm::consts::DEV_PROVIDER_NAME.into(), - region_display_name: util_mm::consts::DEV_REGION_NAME.into(), - datacenter_coord: Box::new(models::GeoCoord { - latitude: 0.0, - longitude: 0.0, - }), - datacenter_distance_from_client: Box::new(models::GeoDistance { - kilometers: 0.0, - miles: 0.0, - }), - }; - - // List game modes - let game_modes = version_config - .lobby_groups - .iter() - .map(|lg| models::MatchmakerGameModeInfo { - game_mode_id: lg.name_id.clone(), - }) - .collect(); - - // Create a fake lobby in each game mode - let lobbies = version_config - .lobby_groups - .iter() - .map(|lg| { - GlobalResult::Ok(models::MatchmakerLobbyInfo { - region_id: util_mm::consts::DEV_REGION_ID.into(), - game_mode_id: lg.name_id.clone(), - lobby_id: Uuid::nil(), - max_players_normal: std::convert::TryInto::try_into(lg.max_players_normal)?, - max_players_direct: std::convert::TryInto::try_into(lg.max_players_direct)?, - max_players_party: std::convert::TryInto::try_into(lg.max_players_party)?, - total_player_count: 0, - }) - }) - .collect::>>()?; - - Ok(models::MatchmakerListLobbiesResponse { - regions: vec![region], - game_modes, - lobbies, - }) -} - struct FetchLobbyListMeta { lobby_groups: Vec<( backend::matchmaker::LobbyGroup, @@ -534,6 +583,7 @@ async fn fetch_lobby_list( op!([ctx] mm_lobby_get { lobby_ids: lobby_ids.clone(), include_stopped: false, + include_private: false, }), op!([ctx] mm_lobby_player_count { lobby_ids: lobby_ids.clone(), @@ -588,21 +638,38 @@ struct FindResponse { player: Box, } +#[derive(Debug)] +enum VerificationType { + UserData(Option), + Bypass, +} + #[tracing::instrument(err, skip(ctx, game_ns))] async fn find_inner( ctx: &Ctx, game_ns: &NamespaceData, query: mm::msg::lobby_find::message::Query, + version_config: Option, captcha: Option>, + verification: VerificationType, ) -> GlobalResult { - // Get version config - let version_config_res = op!([ctx] mm_config_version_get { - version_ids: vec![game_ns.version_id.into()], - }) - .await?; + let (version_config, user_id) = tokio::try_join!( + // Fetch version config if it was not passed as an argument + async { + if let Some(version_config) = version_config { + Ok(version_config) + } else { + let version_config_res = op!([ctx] mm_config_version_get { + version_ids: vec![game_ns.version_id.into()], + }) + .await?; - let version_config = internal_unwrap_owned!(version_config_res.versions.first()); - let version_config = internal_unwrap!(version_config.config); + let version_config = internal_unwrap_owned!(version_config_res.versions.first()); + Ok(internal_unwrap!(version_config.config).clone()) + } + }, + ctx.auth().fetch_game_user_option(ctx.op_ctx()), + )?; // Validate captcha if let Some(captcha_config) = &version_config.captcha { @@ -695,7 +762,9 @@ async fn find_inner( // Find lobby let query_id = Uuid::new_v4(); - let find_res = msg!([ctx] @notrace mm::msg::lobby_find(game_ns.namespace_id, query_id) -> Result { + let find_res = msg!([ctx] @notrace mm::msg::lobby_find(game_ns.namespace_id, query_id) + -> Result + { namespace_id: Some(game_ns.namespace_id.into()), query_id: Some(query_id.into()), join_kind: backend::matchmaker::query::JoinKind::Normal as i32, @@ -705,6 +774,16 @@ async fn find_inner( client_info: Some(ctx.client_info()), }], query: Some(query), + user_id: user_id.map(Into::into), + verification_data_json: if let VerificationType::UserData(verification_data) = &verification { + verification_data + .as_ref() + .map(|data| serde_json::to_string(&data)) + .transpose()? + } else { + None + }, + bypass_verification: matches!(verification, VerificationType::Bypass), }) .await?; let lobby_id = match find_res @@ -728,6 +807,13 @@ async fn find_inner( RegionNotEnabled => panic_with!(MATCHMAKER_REGION_NOT_ENABLED_FOR_GAME_MODE), DevTeamInvalidStatus => panic_with!(GROUP_INVALID_DEVELOPER_STATUS), + + FindDisabled => panic_with!(MATCHMAKER_FIND_DISABLED), + JoinDisabled => panic_with!(MATCHMAKER_JOIN_DISABLED), + VerificationFailed => panic_with!(MATCHMAKER_VERIFICATION_FAILED), + VerificationRequestFailed => panic_with!(MATCHMAKER_VERIFICATION_REQUEST_FAILED), + IdentityRequired => panic_with!(MATCHMAKER_IDENTITY_REQUIRED), + RegistrationRequired => panic_with!(MATCHMAKER_REGISTRATION_REQUIRED), }; } Err(None) => internal_panic!("failed to parse find error code"), @@ -771,6 +857,7 @@ async fn find_inner( }) .await?; + // NOTE: The matchmaker config is fetched again to account for outdated lobbies let version_id = internal_unwrap_owned!(version_res.versions.first()); let version_id = internal_unwrap!(version_id.version_id); let version_res = op!([ctx] mm_config_version_get { @@ -799,7 +886,6 @@ async fn find_inner( // Convert the ports to client-friendly ports let run = internal_unwrap_owned!(run_res.runs.first()); - let ports = docker_runtime .ports .iter() @@ -837,6 +923,71 @@ async fn find_inner( }) } +async fn resolve_region_ids( + ctx: &Ctx, + lat: f64, + long: f64, + regions: Option<&Vec>, + lobby_groups: &[( + &backend::matchmaker::LobbyGroup, + &backend::matchmaker::LobbyGroupMeta, + )], +) -> GlobalResult> { + // Represents the requested regions in order of priority. + 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 { + name_ids: region_name_ids.clone(), + }) + .await?; + + // Map to region IDs and decide + let region_ids = resolve_res + .regions + .iter() + .map(|r| Ok(internal_unwrap!(r.region_id).as_uuid())) + .collect::>>()?; + + assert_eq_with!( + region_ids.len(), + region_name_ids.len(), + MATCHMAKER_REGION_NOT_FOUND + ); + + region_ids + } else { + // Find all enabled region IDs in all requested lobby groups + let enabled_region_ids = lobby_groups + .iter() + .flat_map(|(lg, _)| { + lg.regions + .iter() + .filter_map(|r| r.region_id.as_ref()) + .map(common::Uuid::as_uuid) + .collect::>() + }) + .collect::>() + .into_iter() + .map(Into::::into) + .collect::>(); + + // Auto-select the closest region + let recommend_res = op!([ctx] region_recommend { + latitude: Some(lat), + longitude: Some(long), + region_ids: enabled_region_ids, + ..Default::default() + }) + .await?; + let primary_region = internal_unwrap_owned!(recommend_res.regions.first()); + let primary_region_id = internal_unwrap!(primary_region.region_id).as_uuid(); + + vec![primary_region_id] + }; + + Ok(region_ids) +} + #[tracing::instrument(err, skip(ctx))] async fn dev_mock_lobby( ctx: &Ctx, @@ -903,6 +1054,76 @@ async fn dev_mock_lobby( }) } +async fn dev_mock_lobby_list( + ctx: &Ctx, + ns_dev_ent: &rivet_claims::ent::GameNamespaceDevelopment, +) -> GlobalResult { + // Read the version config + let ns_res = op!([ctx] game_namespace_get { + namespace_ids: vec![ns_dev_ent.namespace_id.into()], + }) + .await?; + let ns_data = internal_unwrap_owned!(ns_res.namespaces.first()); + let version_id = internal_unwrap!(ns_data.version_id).as_uuid(); + + let version_res = op!([ctx] mm_config_version_get { + version_ids: vec![version_id.into()], + }) + .await?; + let version = internal_unwrap_owned!( + version_res.versions.first(), + "no matchmaker config for namespace" + ); + let version_config = internal_unwrap!(version.config); + + // Create fake region + let region = models::MatchmakerRegionInfo { + region_id: util_mm::consts::DEV_REGION_ID.into(), + provider_display_name: util_mm::consts::DEV_PROVIDER_NAME.into(), + region_display_name: util_mm::consts::DEV_REGION_NAME.into(), + datacenter_coord: Box::new(models::GeoCoord { + latitude: 0.0, + longitude: 0.0, + }), + datacenter_distance_from_client: Box::new(models::GeoDistance { + kilometers: 0.0, + miles: 0.0, + }), + }; + + // List game modes + let game_modes = version_config + .lobby_groups + .iter() + .map(|lg| models::MatchmakerGameModeInfo { + game_mode_id: lg.name_id.clone(), + }) + .collect(); + + // Create a fake lobby in each game mode + let lobbies = version_config + .lobby_groups + .iter() + .map(|lg| { + GlobalResult::Ok(models::MatchmakerLobbyInfo { + region_id: util_mm::consts::DEV_REGION_ID.into(), + game_mode_id: lg.name_id.clone(), + lobby_id: Uuid::nil(), + max_players_normal: std::convert::TryInto::try_into(lg.max_players_normal)?, + max_players_direct: std::convert::TryInto::try_into(lg.max_players_direct)?, + max_players_party: std::convert::TryInto::try_into(lg.max_players_party)?, + total_player_count: 0, + }) + }) + .collect::>>()?; + + Ok(models::MatchmakerListLobbiesResponse { + regions: vec![region], + game_modes, + lobbies, + }) +} + // TODO: Copied to api-identity fn build_port( run: &backend::job::Run, diff --git a/svc/api/matchmaker/src/route/mod.rs b/svc/api/matchmaker/src/route/mod.rs index 3949d9f8aa..1e78ac62c4 100644 --- a/svc/api/matchmaker/src/route/mod.rs +++ b/svc/api/matchmaker/src/route/mod.rs @@ -61,6 +61,18 @@ define_router! { }, ), }, + "lobbies" / "create": { + POST: lobbies::create( + body: rivet_api::models::MatchmakerLobbiesCreateRequest, + opt_auth: true, + rate_limit: { + key: "lobby-create", + buckets: [ + { count: 3 }, + ], + }, + ), + }, "lobbies" / "closed": { PUT: lobbies::closed( body: rivet_api::models::MatchmakerLobbiesSetClosedRequest, diff --git a/svc/api/matchmaker/tests/basic.rs b/svc/api/matchmaker/tests/basic.rs index 3937db13b5..e8f696e16d 100644 --- a/svc/api/matchmaker/tests/basic.rs +++ b/svc/api/matchmaker/tests/basic.rs @@ -1,9 +1,13 @@ use std::{collections::HashSet, str::FromStr, sync::Once}; use proto::backend::{self, pkg::*}; -use rivet_api::apis::{configuration::Configuration, *}; +use rivet_api::{ + apis::{configuration::Configuration, *}, + models, +}; use rivet_matchmaker::model; use rivet_operation::prelude::*; +use serde_json::json; const LOBBY_GROUP_NAME_ID_BRIDGE: &str = "test-bridge"; const LOBBY_GROUP_NAME_ID_HOST: &str = "test-host"; @@ -108,7 +112,8 @@ impl Ctx { fn config(&self, bearer_token: String) -> Configuration { Configuration { - base_path: util::env::svc_router_url("api-matchmaker"), + base_path: format!("https://matchmaker.api.{}/v1", util::env::domain_main()), + // base_path: util::env::svc_router_url("api-matchmaker"), bearer_access_token: Some(bearer_token), ..Default::default() } @@ -170,11 +175,18 @@ impl Ctx { regions: vec![backend::matchmaker::lobby_group::Region { region_id: Some(region_id.into()), tier_name_id: "basic-1d8".into(), - idle_lobbies: None, + idle_lobbies: Some(backend::matchmaker::lobby_group::IdleLobbies { + min_idle_lobbies: 0, + // Set a high max lobby count in case this is + // coming from a test that test mm-lobby-create + // without creating an associated player + max_idle_lobbies: 32, + }), }], max_players_normal: 8, max_players_direct: 10, max_players_party: 12, + listable: true, runtime: Some(backend::matchmaker::lobby_runtime::Docker { build_id: build_res.build_id, @@ -226,6 +238,17 @@ impl Ctx { }, ], }.into()), + + find_config: None, + join_config: None, + create_config: Some(backend::matchmaker::CreateConfig { + identity_requirement: backend::matchmaker::IdentityRequirement::None as i32, + verification_config: None, + + enable_public: true, + enable_private: true, + max_lobbies_per_identity: Some(1), + }), }, backend::matchmaker::LobbyGroup { name_id: LOBBY_GROUP_NAME_ID_HOST.into(), @@ -238,6 +261,7 @@ impl Ctx { max_players_normal: 8, max_players_direct: 10, max_players_party: 12, + listable: true, runtime: Some(backend::matchmaker::lobby_runtime::Docker { build_id: build_res.build_id, @@ -288,6 +312,10 @@ impl Ctx { }, ], }.into()), + + find_config: None, + join_config: None, + create_config: None, }, ], }), @@ -401,7 +429,7 @@ async fn find_with_regions() { .await .unwrap(); - assert_lobby_state(&ctx, res.lobby().unwrap()).await; + assert_lobby_state_smithy(&ctx, res.lobby().unwrap()).await; } } @@ -424,7 +452,37 @@ async fn find_without_regions() { .await .unwrap(); - assert_lobby_state(&ctx, res.lobby().unwrap()).await; + assert_lobby_state_smithy(&ctx, res.lobby().unwrap()).await; + } +} + +#[tokio::test(flavor = "multi_thread")] +async fn create_custom_lobby() { + let ctx = Ctx::init().await; + + { + tracing::info!("creating custom lobby"); + + let res = matchmaker_lobbies_api::matchmaker_lobbies_create( + &ctx.config(ctx.ns_auth_token.clone()), + models::MatchmakerLobbiesCreateRequest { + game_mode: LOBBY_GROUP_NAME_ID_BRIDGE.to_string(), + region: Some(ctx.primary_region_name_id.clone()), + publicity: models::MatchmakerCustomLobbyPublicity::Public, + lobby_config: Some(Some(json!({ "foo": "bar" }))), + verification_data: None, + captcha: Some(Box::new(models::CaptchaConfig { + hcaptcha: Some(Box::new(models::CaptchaConfigHcaptcha { + client_response: "10000000-aaaa-bbbb-cccc-000000000001".to_string(), + })), + turnstile: None, + })), + }, + ) + .await + .unwrap(); + + assert_lobby_state(&ctx, &res.lobby).await; } } @@ -465,6 +523,7 @@ async fn list_lobbies() { query: Some(mm::msg::lobby_find::message::Query::Direct(backend::matchmaker::query::Direct { lobby_id: Some(lobby_id.into()), })), + ..Default::default() }) .await .unwrap().unwrap(); @@ -521,7 +580,7 @@ async fn lobby_lifecycle() { .await .unwrap(); let lobby = res.lobby().unwrap(); - assert_lobby_state(&ctx, lobby).await; + assert_lobby_state_smithy(&ctx, lobby).await; let lobby_token = ctx.lobby_token(lobby.lobby_id().unwrap()).await; @@ -554,7 +613,7 @@ async fn lobby_lifecycle() { .await .unwrap(); let lobby = res.lobby().unwrap(); - assert_lobby_state(&ctx, lobby).await; + assert_lobby_state_smithy(&ctx, lobby).await; let lobby_token = ctx.lobby_token(lobby.lobby_id().unwrap()).await; @@ -815,7 +874,7 @@ async fn find_domain_auth() { .send() .await .unwrap(); - assert_lobby_state(&ctx, res.lobby().unwrap()).await; + assert_lobby_state_smithy(&ctx, res.lobby().unwrap()).await; } // Custom domain @@ -832,7 +891,7 @@ async fn find_domain_auth() { .send() .await .unwrap(); - assert_lobby_state(&ctx, res.lobby().unwrap()).await; + assert_lobby_state_smithy(&ctx, res.lobby().unwrap()).await; } } @@ -852,7 +911,7 @@ async fn player_statistics() { tracing::info!(?player_count, ?game_modes); } -async fn assert_lobby_state( +async fn assert_lobby_state_smithy( ctx: &Ctx, lobby: &model::MatchmakerLobbyJoinInfo, ) -> backend::matchmaker::Lobby { @@ -869,29 +928,30 @@ async fn assert_lobby_state( // Validate ports { - tracing::info!(ports = ?lobby.ports().unwrap(), "validating ports"); - assert_eq!(6, lobby.ports().unwrap().len()); + let ports = lobby.ports().unwrap(); + tracing::info!(?ports, "validating ports"); + assert_eq!(6, ports.len()); { - let p = lobby.ports().unwrap().get("test-80-http").unwrap(); + let p = ports.get("test-80-http").unwrap(); assert_eq!(80, p.port().unwrap()); assert!(!p.is_tls().unwrap()); } { - let p = lobby.ports().unwrap().get("test-80-https").unwrap(); + let p = ports.get("test-80-https").unwrap(); assert_eq!(443, p.port().unwrap()); assert!(p.is_tls().unwrap()); } { - let p = lobby.ports().unwrap().get("test-5050-https").unwrap(); + let p = ports.get("test-5050-https").unwrap(); assert_eq!(443, p.port().unwrap()); assert!(p.is_tls().unwrap()); } { - let p = lobby.ports().unwrap().get("test-5051-tcp").unwrap(); + let p = ports.get("test-5051-tcp").unwrap(); assert!( p.port().unwrap() >= util_job::consts::MIN_INGRESS_PORT_TCP as i32 && p.port().unwrap() <= util_job::consts::MAX_INGRESS_PORT_TCP as i32 @@ -900,7 +960,7 @@ async fn assert_lobby_state( } { - let p = lobby.ports().unwrap().get("test-5051-tls").unwrap(); + let p = ports.get("test-5051-tls").unwrap(); assert!( p.port().unwrap() >= util_job::consts::MIN_INGRESS_PORT_TCP as i32 && p.port().unwrap() <= util_job::consts::MAX_INGRESS_PORT_TCP as i32 @@ -909,7 +969,7 @@ async fn assert_lobby_state( } { - let p = lobby.ports().unwrap().get("test-5052-udp").unwrap(); + let p = ports.get("test-5052-udp").unwrap(); assert!( p.port().unwrap() >= util_job::consts::MIN_INGRESS_PORT_UDP as i32 && p.port().unwrap() <= util_job::consts::MAX_INGRESS_PORT_UDP as i32 @@ -921,6 +981,76 @@ async fn assert_lobby_state( lobby_data.clone() } +async fn assert_lobby_state( + ctx: &Ctx, + lobby: &models::MatchmakerJoinLobby, +) -> backend::matchmaker::Lobby { + // Fetch lobby data + let lobby_res = op!([ctx] mm_lobby_get { + lobby_ids: vec![lobby.lobby_id.into()], + ..Default::default() + }) + .await + .unwrap(); + let lobby_data = lobby_res.lobbies.first().expect("lobby not created"); + assert!(lobby_data.ready_ts.is_some(), "lobby not ready"); + assert!(lobby_data.run_id.is_some(), "no run id"); + + // Validate ports + { + let ports = &lobby.ports; + tracing::info!(?ports, "validating ports"); + assert_eq!(6, ports.len()); + + { + let p = ports.get("test-80-http").unwrap(); + assert_eq!(80, p.port.unwrap()); + assert!(!p.is_tls); + } + + { + let p = ports.get("test-80-https").unwrap(); + assert_eq!(443, p.port.unwrap()); + assert!(p.is_tls); + } + + { + let p = ports.get("test-5050-https").unwrap(); + assert_eq!(443, p.port.unwrap()); + assert!(p.is_tls); + } + + { + let p = ports.get("test-5051-tcp").unwrap(); + assert!( + p.port.unwrap() >= util_job::consts::MIN_INGRESS_PORT_TCP as i32 + && p.port.unwrap() <= util_job::consts::MAX_INGRESS_PORT_TCP as i32 + ); + assert!(!p.is_tls); + } + + { + let p = ports.get("test-5051-tls").unwrap(); + assert!( + p.port.unwrap() >= util_job::consts::MIN_INGRESS_PORT_TCP as i32 + && p.port.unwrap() <= util_job::consts::MAX_INGRESS_PORT_TCP as i32 + ); + assert!(p.is_tls); + } + + { + let p = ports.get("test-5052-udp").unwrap(); + assert!( + p.port.unwrap() >= util_job::consts::MIN_INGRESS_PORT_UDP as i32 + && p.port.unwrap() <= util_job::consts::MAX_INGRESS_PORT_UDP as i32 + ); + assert!(!p.is_tls); + } + } + + lobby_data.clone() +} + fn captcha_config() -> model::CaptchaConfig { model::CaptchaConfig::Hcaptcha( model::captcha_config_hcaptcha::Builder::default() @@ -941,6 +1071,11 @@ async fn create_lobby( region_id: Some(ctx.primary_region_id.into()), create_ray_id: None, preemptively_created: false, + + creator_user_id: None, + is_custom: false, + publicity: None, + lobby_config_json: None, }) .await .unwrap(); diff --git a/svc/api/module/Cargo.toml b/svc/api/module/Cargo.toml index 613197bf4e..cb5006ff0e 100644 --- a/svc/api/module/Cargo.toml +++ b/svc/api/module/Cargo.toml @@ -26,7 +26,7 @@ rivet-pools = { path = "../../../lib/pools" } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" thiserror = "1.0" -tokio = { version = "1.21" } +tokio = { version = "1.29" } tracing = "0.1" tracing-subscriber = { version = "0.3", default-features = false, features = ["fmt", "json", "ansi"] } url = "2.2.2" diff --git a/svc/api/module/tests/basic.rs b/svc/api/module/tests/basic.rs index f9a33b1da4..600b0b9e6b 100644 --- a/svc/api/module/tests/basic.rs +++ b/svc/api/module/tests/basic.rs @@ -97,6 +97,7 @@ impl Ctx { region_id: Some(self.primary_region_id.into()), create_ray_id: None, preemptively_created: false, + ..Default::default() }) .await .unwrap(); @@ -250,6 +251,7 @@ impl Ctx { }, ], }.into()), + ..Default::default() }], }), ..Default::default() diff --git a/svc/api/portal/Cargo.toml b/svc/api/portal/Cargo.toml index 548f8b1888..000165a2e4 100644 --- a/svc/api/portal/Cargo.toml +++ b/svc/api/portal/Cargo.toml @@ -26,7 +26,7 @@ rivet-portal-server = { path = "../../../lib/smithy-output/api-portal/rust-serve serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" thiserror = "1.0" -tokio = { version = "1.21" } +tokio = { version = "1.29" } tracing = "0.1" tracing-subscriber = { version = "0.3", default-features = false, features = ["fmt", "json", "ansi"] } url = "2.2.2" diff --git a/svc/api/route/Cargo.toml b/svc/api/route/Cargo.toml index de9453193a..7e5d209319 100644 --- a/svc/api/route/Cargo.toml +++ b/svc/api/route/Cargo.toml @@ -25,7 +25,7 @@ s3-util = { path = "../../../lib/s3-util" } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" thiserror = "1.0" -tokio = { version = "1.21" } +tokio = { version = "1.29" } toml = "0.5" tracing = "0.1" tracing-subscriber = { version = "0.3", default-features = false, features = ["fmt", "json", "ansi"] } diff --git a/svc/api/status/Cargo.toml b/svc/api/status/Cargo.toml index e936d1551f..c05ee0ae9c 100644 --- a/svc/api/status/Cargo.toml +++ b/svc/api/status/Cargo.toml @@ -30,7 +30,7 @@ s3-util = { path = "../../../lib/s3-util" } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" thiserror = "1.0" -tokio = { version = "1.21" } +tokio = { version = "1.29" } tracing = "0.1" tracing-subscriber = { version = "0.3", default-features = false, features = ["fmt", "json", "ansi"] } url = "2.2.2" diff --git a/svc/api/status/src/auth.rs b/svc/api/status/src/auth.rs index c3ceb470f0..43d7568e6b 100644 --- a/svc/api/status/src/auth.rs +++ b/svc/api/status/src/auth.rs @@ -14,7 +14,6 @@ impl ApiAuth for Auth { ) -> GlobalResult { Self::rate_limit(rate_limit_ctx).await?; - // TODO: Don't hardcode this // TODO: Use JWT if let Some(api_token) = api_token { assert_eq_with!( @@ -23,9 +22,10 @@ impl ApiAuth for Auth { API_FORBIDDEN, reason = "Invalid auth" ); + Ok(Auth { _claims: None }) + } else { + internal_panic!("unreachable"); } - - Ok(Auth { _claims: None }) } async fn rate_limit(_rate_limit_ctx: AuthRateLimitCtx<'_>) -> GlobalResult<()> { diff --git a/svc/pkg/analytics/worker/src/workers/event_create.rs b/svc/pkg/analytics/worker/src/workers/event_create.rs index 74fa851eb7..ef11824531 100644 --- a/svc/pkg/analytics/worker/src/workers/event_create.rs +++ b/svc/pkg/analytics/worker/src/workers/event_create.rs @@ -15,7 +15,7 @@ struct Event { } #[worker(name = "analytics-event-create")] -async fn worker(ctx: OperationContext) -> GlobalResult<()> { +async fn worker(ctx: &OperationContext) -> GlobalResult<()> { let ray_id = ctx.ray_id(); let client = clickhouse::Client::default() diff --git a/svc/pkg/build/ops/create/Cargo.toml b/svc/pkg/build/ops/create/Cargo.toml index fbe7d31a5c..dd4c68f86b 100644 --- a/svc/pkg/build/ops/create/Cargo.toml +++ b/svc/pkg/build/ops/create/Cargo.toml @@ -14,7 +14,7 @@ game-get = { path = "../../../game/ops/get" } upload-prepare = { path = "../../../upload/ops/prepare" } [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/build/ops/create/src/lib.rs b/svc/pkg/build/ops/create/src/lib.rs index d2422e08fc..180548d67a 100644 --- a/svc/pkg/build/ops/create/src/lib.rs +++ b/svc/pkg/build/ops/create/src/lib.rs @@ -72,7 +72,7 @@ async fn handle( path: "image.tar".into(), mime: Some("application/x-tar".into()), content_length: image_file.content_length, - multipart: true, + multipart: ctx.multipart, ..Default::default() }, ], diff --git a/svc/pkg/build/ops/get/Cargo.toml b/svc/pkg/build/ops/get/Cargo.toml index 3fbdce1fea..8597e7384e 100644 --- a/svc/pkg/build/ops/get/Cargo.toml +++ b/svc/pkg/build/ops/get/Cargo.toml @@ -11,7 +11,7 @@ chirp-client = { path = "../../../../../lib/chirp/client" } prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/build/ops/list-for-game/Cargo.toml b/svc/pkg/build/ops/list-for-game/Cargo.toml index 3e8ec2ad1f..671466daad 100644 --- a/svc/pkg/build/ops/list-for-game/Cargo.toml +++ b/svc/pkg/build/ops/list-for-game/Cargo.toml @@ -11,7 +11,7 @@ chirp-client = { path = "../../../../../lib/chirp/client" } prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/build/standalone/default-create/Cargo.toml b/svc/pkg/build/standalone/default-create/Cargo.toml index 86ef376ed3..8e8a55d70d 100644 --- a/svc/pkg/build/standalone/default-create/Cargo.toml +++ b/svc/pkg/build/standalone/default-create/Cargo.toml @@ -14,7 +14,7 @@ prost = "0.10" rivet-connection = { path = "../../../../../lib/connection" } reqwest = "0.11" rivet-pools = { path = "../../../../../lib/pools" } -tokio = { version = "1.21", features = ["full"] } +tokio = { version = "1.29", features = ["full"] } tracing = "0.1" tracing-subscriber = { version = "0.3", default-features = false, features = ["fmt", "json", "ansi"] } uuid = { version = "1", features = ["v4"] } @@ -23,14 +23,13 @@ upload-complete = { path = "../../../upload/ops/complete" } upload-prepare = { path = "../../../upload/ops/prepare" } [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false features = [ - "runtime-tokio-native-tls", + "runtime-tokio", "postgres", "uuid", "json", - "tls", ] [dev-dependencies] diff --git a/svc/pkg/build/types/create.proto b/svc/pkg/build/types/create.proto index a186324dac..3ac96e19e3 100644 --- a/svc/pkg/build/types/create.proto +++ b/svc/pkg/build/types/create.proto @@ -10,6 +10,7 @@ message Request { string display_name = 2; optional string image_tag = 4; optional rivet.backend.upload.PrepareFile image_file = 3; + bool multipart = 6; // If provided, will look up the pre-uploaded upload ID for a given kind. optional string default_build_kind = 5; diff --git a/svc/pkg/captcha/ops/request/Cargo.toml b/svc/pkg/captcha/ops/request/Cargo.toml index dc4fdd8346..3c028a13ae 100644 --- a/svc/pkg/captcha/ops/request/Cargo.toml +++ b/svc/pkg/captcha/ops/request/Cargo.toml @@ -13,7 +13,7 @@ chrono = "0.4" util-captcha = { package = "rivet-util-captcha", path = "../../util" } [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/cdn/ops/namespace-auth-user-remove/Cargo.toml b/svc/pkg/cdn/ops/namespace-auth-user-remove/Cargo.toml index 8af25eb0f8..f21760268f 100644 --- a/svc/pkg/cdn/ops/namespace-auth-user-remove/Cargo.toml +++ b/svc/pkg/cdn/ops/namespace-auth-user-remove/Cargo.toml @@ -11,7 +11,7 @@ chirp-client = { path = "../../../../../lib/chirp/client" } prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/cdn/ops/namespace-auth-user-update/Cargo.toml b/svc/pkg/cdn/ops/namespace-auth-user-update/Cargo.toml index 6defc8026e..cf89c5ca25 100644 --- a/svc/pkg/cdn/ops/namespace-auth-user-update/Cargo.toml +++ b/svc/pkg/cdn/ops/namespace-auth-user-update/Cargo.toml @@ -11,7 +11,7 @@ chirp-client = { path = "../../../../../lib/chirp/client" } prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/cdn/ops/namespace-create/Cargo.toml b/svc/pkg/cdn/ops/namespace-create/Cargo.toml index a95e157fdc..a5414d3cc6 100644 --- a/svc/pkg/cdn/ops/namespace-create/Cargo.toml +++ b/svc/pkg/cdn/ops/namespace-create/Cargo.toml @@ -11,7 +11,7 @@ chirp-client = { path = "../../../../../lib/chirp/client" } prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/cdn/ops/namespace-domain-create/Cargo.toml b/svc/pkg/cdn/ops/namespace-domain-create/Cargo.toml index 48d1ae2534..6a88d323d3 100644 --- a/svc/pkg/cdn/ops/namespace-domain-create/Cargo.toml +++ b/svc/pkg/cdn/ops/namespace-domain-create/Cargo.toml @@ -14,7 +14,7 @@ game-get = { path = "../../../game/ops/get" } game-resolve-namespace-id = { path = "../../../game/ops/resolve-namespace-id" } [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/cdn/ops/namespace-domain-remove/Cargo.toml b/svc/pkg/cdn/ops/namespace-domain-remove/Cargo.toml index cb9cf7f996..73c2b52ea1 100644 --- a/svc/pkg/cdn/ops/namespace-domain-remove/Cargo.toml +++ b/svc/pkg/cdn/ops/namespace-domain-remove/Cargo.toml @@ -14,7 +14,7 @@ game-get = { path = "../../../game/ops/get" } game-resolve-namespace-id = { path = "../../../game/ops/resolve-namespace-id" } [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/cdn/ops/namespace-get/Cargo.toml b/svc/pkg/cdn/ops/namespace-get/Cargo.toml index b5bb186bfa..9bd9b8eefb 100644 --- a/svc/pkg/cdn/ops/namespace-get/Cargo.toml +++ b/svc/pkg/cdn/ops/namespace-get/Cargo.toml @@ -11,7 +11,7 @@ chirp-client = { path = "../../../../../lib/chirp/client" } prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/cdn/ops/namespace-resolve-domain/Cargo.toml b/svc/pkg/cdn/ops/namespace-resolve-domain/Cargo.toml index 0708028a9b..9777553afd 100644 --- a/svc/pkg/cdn/ops/namespace-resolve-domain/Cargo.toml +++ b/svc/pkg/cdn/ops/namespace-resolve-domain/Cargo.toml @@ -11,7 +11,7 @@ chirp-client = { path = "../../../../../lib/chirp/client" } prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/cdn/ops/ns-auth-type-set/Cargo.toml b/svc/pkg/cdn/ops/ns-auth-type-set/Cargo.toml index 99577b1d5a..64374820ab 100644 --- a/svc/pkg/cdn/ops/ns-auth-type-set/Cargo.toml +++ b/svc/pkg/cdn/ops/ns-auth-type-set/Cargo.toml @@ -11,7 +11,7 @@ chirp-client = { path = "../../../../../lib/chirp/client" } prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/cdn/ops/ns-enable-domain-public-auth-set/Cargo.toml b/svc/pkg/cdn/ops/ns-enable-domain-public-auth-set/Cargo.toml index af4ae6edce..cf30bce172 100644 --- a/svc/pkg/cdn/ops/ns-enable-domain-public-auth-set/Cargo.toml +++ b/svc/pkg/cdn/ops/ns-enable-domain-public-auth-set/Cargo.toml @@ -11,7 +11,7 @@ chirp-client = { path = "../../../../../lib/chirp/client" } prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/cdn/ops/site-create/Cargo.toml b/svc/pkg/cdn/ops/site-create/Cargo.toml index deced8872b..70c503f842 100644 --- a/svc/pkg/cdn/ops/site-create/Cargo.toml +++ b/svc/pkg/cdn/ops/site-create/Cargo.toml @@ -14,7 +14,7 @@ game-get = { path = "../../../game/ops/get" } upload-prepare = { path = "../../../upload/ops/prepare" } [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/cdn/ops/site-get/Cargo.toml b/svc/pkg/cdn/ops/site-get/Cargo.toml index 1e741f055f..32d72113a1 100644 --- a/svc/pkg/cdn/ops/site-get/Cargo.toml +++ b/svc/pkg/cdn/ops/site-get/Cargo.toml @@ -11,7 +11,7 @@ chirp-client = { path = "../../../../../lib/chirp/client" } prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/cdn/ops/site-list-for-game/Cargo.toml b/svc/pkg/cdn/ops/site-list-for-game/Cargo.toml index c191f605cb..dbd26586ee 100644 --- a/svc/pkg/cdn/ops/site-list-for-game/Cargo.toml +++ b/svc/pkg/cdn/ops/site-list-for-game/Cargo.toml @@ -11,7 +11,7 @@ chirp-client = { path = "../../../../../lib/chirp/client" } prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/cdn/ops/version-get/Cargo.toml b/svc/pkg/cdn/ops/version-get/Cargo.toml index 5aea2f4077..ed7e13849e 100644 --- a/svc/pkg/cdn/ops/version-get/Cargo.toml +++ b/svc/pkg/cdn/ops/version-get/Cargo.toml @@ -11,7 +11,7 @@ chirp-client = { path = "../../../../../lib/chirp/client" } prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/cdn/ops/version-publish/Cargo.toml b/svc/pkg/cdn/ops/version-publish/Cargo.toml index 827bee0f84..70535c0673 100644 --- a/svc/pkg/cdn/ops/version-publish/Cargo.toml +++ b/svc/pkg/cdn/ops/version-publish/Cargo.toml @@ -13,7 +13,7 @@ unzip-n = "0.1.2" itertools = "0.10.5" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/cdn/worker/src/workers/ns_config_populate.rs b/svc/pkg/cdn/worker/src/workers/ns_config_populate.rs index c54035c1da..9fa0e9c54e 100644 --- a/svc/pkg/cdn/worker/src/workers/ns_config_populate.rs +++ b/svc/pkg/cdn/worker/src/workers/ns_config_populate.rs @@ -3,7 +3,7 @@ use proto::backend::{self, pkg::*}; use redis::AsyncCommands; #[worker(name = "cdn-ns-config-populate")] -async fn worker(ctx: OperationContext) -> GlobalResult<()> { +async fn worker(ctx: &OperationContext) -> GlobalResult<()> { let namespace_id = internal_unwrap_owned!(ctx.namespace_id).as_uuid(); if let Some((game, ns, cdn_ns_config, cdn_version)) = get_cdn_version(ctx, namespace_id).await? diff --git a/svc/pkg/cf-custom-hostname/ops/get/Cargo.toml b/svc/pkg/cf-custom-hostname/ops/get/Cargo.toml index 5a1bfdd049..186288f1ff 100644 --- a/svc/pkg/cf-custom-hostname/ops/get/Cargo.toml +++ b/svc/pkg/cf-custom-hostname/ops/get/Cargo.toml @@ -11,7 +11,7 @@ chirp-client = { path = "../../../../../lib/chirp/client" } prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/cf-custom-hostname/ops/list-for-namespace-id/Cargo.toml b/svc/pkg/cf-custom-hostname/ops/list-for-namespace-id/Cargo.toml index 829ab4e10d..a41c3f82a1 100644 --- a/svc/pkg/cf-custom-hostname/ops/list-for-namespace-id/Cargo.toml +++ b/svc/pkg/cf-custom-hostname/ops/list-for-namespace-id/Cargo.toml @@ -11,7 +11,7 @@ chirp-client = { path = "../../../../../lib/chirp/client" } prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/cf-custom-hostname/ops/resolve-hostname/Cargo.toml b/svc/pkg/cf-custom-hostname/ops/resolve-hostname/Cargo.toml index a355f6a8d9..f7f7ef8f28 100644 --- a/svc/pkg/cf-custom-hostname/ops/resolve-hostname/Cargo.toml +++ b/svc/pkg/cf-custom-hostname/ops/resolve-hostname/Cargo.toml @@ -11,7 +11,7 @@ chirp-client = { path = "../../../../../lib/chirp/client" } prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/cf-custom-hostname/worker/src/workers/create.rs b/svc/pkg/cf-custom-hostname/worker/src/workers/create.rs index 656413b909..70da032d3d 100644 --- a/svc/pkg/cf-custom-hostname/worker/src/workers/create.rs +++ b/svc/pkg/cf-custom-hostname/worker/src/workers/create.rs @@ -51,7 +51,7 @@ async fn fail( #[worker(name = "cf-custom-hostname-create")] async fn worker( - ctx: OperationContext, + ctx: &OperationContext, ) -> GlobalResult<()> { let namespace_id = internal_unwrap!(ctx.namespace_id).as_uuid(); diff --git a/svc/pkg/cf-custom-hostname/worker/src/workers/delete.rs b/svc/pkg/cf-custom-hostname/worker/src/workers/delete.rs index ad452abbe3..3bd35eb583 100644 --- a/svc/pkg/cf-custom-hostname/worker/src/workers/delete.rs +++ b/svc/pkg/cf-custom-hostname/worker/src/workers/delete.rs @@ -15,7 +15,7 @@ struct CloudflareErrorEntry { #[worker(name = "cf-custom-hostname-delete")] async fn worker( - ctx: OperationContext, + ctx: &OperationContext, ) -> GlobalResult<()> { let namespace_id = internal_unwrap!(ctx.namespace_id).as_uuid(); let crdb = ctx.crdb("db-cf-custom-hostname").await?; diff --git a/svc/pkg/cf-custom-hostname/worker/src/workers/status_set.rs b/svc/pkg/cf-custom-hostname/worker/src/workers/status_set.rs index e64fe8583a..d57b723fee 100644 --- a/svc/pkg/cf-custom-hostname/worker/src/workers/status_set.rs +++ b/svc/pkg/cf-custom-hostname/worker/src/workers/status_set.rs @@ -3,7 +3,7 @@ use proto::backend::{self, pkg::*}; #[worker(name = "cf-custom-hostname-status-set")] async fn worker( - ctx: OperationContext, + ctx: &OperationContext, ) -> GlobalResult<()> { let identifier = internal_unwrap!(ctx.identifier).as_uuid(); diff --git a/svc/pkg/chat-message/ops/get/Cargo.toml b/svc/pkg/chat-message/ops/get/Cargo.toml index 2e07aea2ad..d1aefa9c6f 100644 --- a/svc/pkg/chat-message/ops/get/Cargo.toml +++ b/svc/pkg/chat-message/ops/get/Cargo.toml @@ -12,7 +12,7 @@ chrono = "0.4" prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/chat-message/ops/list-for-user/Cargo.toml b/svc/pkg/chat-message/ops/list-for-user/Cargo.toml index 61e9bcbdd3..e3f6bbfa72 100644 --- a/svc/pkg/chat-message/ops/list-for-user/Cargo.toml +++ b/svc/pkg/chat-message/ops/list-for-user/Cargo.toml @@ -12,7 +12,7 @@ chrono = "0.4" prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/chat-message/ops/list/Cargo.toml b/svc/pkg/chat-message/ops/list/Cargo.toml index 9f0d52395e..4fe04e50f1 100644 --- a/svc/pkg/chat-message/ops/list/Cargo.toml +++ b/svc/pkg/chat-message/ops/list/Cargo.toml @@ -12,7 +12,7 @@ chrono = "0.4" prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/chat-message/worker/src/workers/create.rs b/svc/pkg/chat-message/worker/src/workers/create.rs index f5e2352189..497cd2207c 100644 --- a/svc/pkg/chat-message/worker/src/workers/create.rs +++ b/svc/pkg/chat-message/worker/src/workers/create.rs @@ -7,7 +7,7 @@ lazy_static::lazy_static! { } #[worker(name = "chat-message-create")] -async fn worker(ctx: OperationContext) -> GlobalResult<()> { +async fn worker(ctx: &OperationContext) -> GlobalResult<()> { let crdb = ctx.crdb("db-chat").await?; let chat_message_id = internal_unwrap!(ctx.chat_message_id).as_uuid(); diff --git a/svc/pkg/chat-message/worker/src/workers/edit.rs b/svc/pkg/chat-message/worker/src/workers/edit.rs index 16b2e10800..80ba7fae2a 100644 --- a/svc/pkg/chat-message/worker/src/workers/edit.rs +++ b/svc/pkg/chat-message/worker/src/workers/edit.rs @@ -7,7 +7,7 @@ lazy_static::lazy_static! { // TODO: Implement editing for `Text` message bodies with an `edited` property (See RIV-460) #[worker(name = "chat-message-edit")] -async fn worker(ctx: OperationContext) -> GlobalResult<()> { +async fn worker(ctx: &OperationContext) -> GlobalResult<()> { let crdb = ctx.crdb("db-chat").await?; let chat_message_id = internal_unwrap!(ctx.chat_message_id).as_uuid(); diff --git a/svc/pkg/chat-thread/ops/get-for-topic/Cargo.toml b/svc/pkg/chat-thread/ops/get-for-topic/Cargo.toml index 40a8fce677..7d3d4395a5 100644 --- a/svc/pkg/chat-thread/ops/get-for-topic/Cargo.toml +++ b/svc/pkg/chat-thread/ops/get-for-topic/Cargo.toml @@ -12,7 +12,7 @@ chrono = "0.4" prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/chat-thread/ops/get/Cargo.toml b/svc/pkg/chat-thread/ops/get/Cargo.toml index afea653a48..02f309572f 100644 --- a/svc/pkg/chat-thread/ops/get/Cargo.toml +++ b/svc/pkg/chat-thread/ops/get/Cargo.toml @@ -12,7 +12,7 @@ chrono = "0.4" prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/chat-thread/ops/list-for-participant/Cargo.toml b/svc/pkg/chat-thread/ops/list-for-participant/Cargo.toml index ace6222fa9..7dca39cf89 100644 --- a/svc/pkg/chat-thread/ops/list-for-participant/Cargo.toml +++ b/svc/pkg/chat-thread/ops/list-for-participant/Cargo.toml @@ -14,7 +14,7 @@ prost = "0.10" user-team-list = { path = "../../../user/ops/team-list" } [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/chat-thread/ops/recent-for-user/Cargo.toml b/svc/pkg/chat-thread/ops/recent-for-user/Cargo.toml index db74712745..af7831fda5 100644 --- a/svc/pkg/chat-thread/ops/recent-for-user/Cargo.toml +++ b/svc/pkg/chat-thread/ops/recent-for-user/Cargo.toml @@ -17,7 +17,7 @@ chat-thread-get = { path = "../get" } chat-thread-list-for-participant = { path = "../list-for-participant" } [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/chat-thread/ops/unread-count/Cargo.toml b/svc/pkg/chat-thread/ops/unread-count/Cargo.toml index b75664defe..853f61db9d 100644 --- a/svc/pkg/chat-thread/ops/unread-count/Cargo.toml +++ b/svc/pkg/chat-thread/ops/unread-count/Cargo.toml @@ -15,7 +15,7 @@ serde_json = "1.0" chat-last-read-ts-get = { path = "../../../chat/ops/last-read-ts-get" } [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/chat-thread/worker/Cargo.toml b/svc/pkg/chat-thread/worker/Cargo.toml index 0afb80b59b..ec40af319d 100644 --- a/svc/pkg/chat-thread/worker/Cargo.toml +++ b/svc/pkg/chat-thread/worker/Cargo.toml @@ -15,7 +15,7 @@ lazy_static = "1.4.0" chrono = "0.4" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/chat-thread/worker/src/workers/create.rs b/svc/pkg/chat-thread/worker/src/workers/create.rs index 30e6bc7b47..873ab74cdc 100644 --- a/svc/pkg/chat-thread/worker/src/workers/create.rs +++ b/svc/pkg/chat-thread/worker/src/workers/create.rs @@ -3,7 +3,7 @@ use proto::backend::{self, pkg::*}; use serde_json::json; #[worker(name = "chat-thread-create")] -async fn worker(ctx: OperationContext) -> GlobalResult<()> { +async fn worker(ctx: &OperationContext) -> GlobalResult<()> { let crdb = ctx.crdb("db-chat").await?; let request_id = internal_unwrap!(ctx.request_id).as_uuid(); diff --git a/svc/pkg/chat/ops/last-read-ts-get/Cargo.toml b/svc/pkg/chat/ops/last-read-ts-get/Cargo.toml index bc21da748b..d9aa23f091 100644 --- a/svc/pkg/chat/ops/last-read-ts-get/Cargo.toml +++ b/svc/pkg/chat/ops/last-read-ts-get/Cargo.toml @@ -12,7 +12,7 @@ chrono = "0.4" prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/chat/worker/src/workers/last_read_ts_set.rs b/svc/pkg/chat/worker/src/workers/last_read_ts_set.rs index df294bdfe7..9805b8e160 100644 --- a/svc/pkg/chat/worker/src/workers/last_read_ts_set.rs +++ b/svc/pkg/chat/worker/src/workers/last_read_ts_set.rs @@ -2,7 +2,7 @@ use chirp_worker::prelude::*; use proto::backend::pkg::*; #[worker(name = "chat-last-read-ts-set")] -async fn worker(ctx: OperationContext) -> GlobalResult<()> { +async fn worker(ctx: &OperationContext) -> GlobalResult<()> { let crdb = ctx.crdb("db-chat").await?; let user_id = internal_unwrap!(ctx.user_id).as_uuid(); diff --git a/svc/pkg/cloud/ops/game-config-create/Cargo.toml b/svc/pkg/cloud/ops/game-config-create/Cargo.toml index 3deb7aa33d..94af0569df 100644 --- a/svc/pkg/cloud/ops/game-config-create/Cargo.toml +++ b/svc/pkg/cloud/ops/game-config-create/Cargo.toml @@ -11,7 +11,7 @@ chirp-client = { path = "../../../../../lib/chirp/client" } prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/cloud/ops/game-config-get/Cargo.toml b/svc/pkg/cloud/ops/game-config-get/Cargo.toml index f710928b59..2fc404c910 100644 --- a/svc/pkg/cloud/ops/game-config-get/Cargo.toml +++ b/svc/pkg/cloud/ops/game-config-get/Cargo.toml @@ -11,7 +11,7 @@ chirp-client = { path = "../../../../../lib/chirp/client" } prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/cloud/ops/game-token-create/Cargo.toml b/svc/pkg/cloud/ops/game-token-create/Cargo.toml index 2c9996c3e4..fb1c97a00c 100644 --- a/svc/pkg/cloud/ops/game-token-create/Cargo.toml +++ b/svc/pkg/cloud/ops/game-token-create/Cargo.toml @@ -13,7 +13,7 @@ prost = "0.10" token-create = { path = "../../../token/ops/create" } [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/cloud/ops/namespace-create/Cargo.toml b/svc/pkg/cloud/ops/namespace-create/Cargo.toml index 68b8f9e7fe..a4f75a47e8 100644 --- a/svc/pkg/cloud/ops/namespace-create/Cargo.toml +++ b/svc/pkg/cloud/ops/namespace-create/Cargo.toml @@ -18,7 +18,7 @@ kv-config-namespace-create = { path = "../../../kv-config/ops/namespace-create" identity-config-namespace-create = { path = "../../../identity-config/ops/namespace-create" } [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/cloud/ops/namespace-get/Cargo.toml b/svc/pkg/cloud/ops/namespace-get/Cargo.toml index 8cc109f520..9d3d60fcf8 100644 --- a/svc/pkg/cloud/ops/namespace-get/Cargo.toml +++ b/svc/pkg/cloud/ops/namespace-get/Cargo.toml @@ -16,7 +16,7 @@ kv-config-namespace-get = { path = "../../../kv-config/ops/namespace-get" } mm-config-namespace-get = { path = "../../../mm-config/ops/namespace-get" } [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/cloud/ops/namespace-token-development-create/Cargo.toml b/svc/pkg/cloud/ops/namespace-token-development-create/Cargo.toml index b935e592a5..16e8a2ae4e 100644 --- a/svc/pkg/cloud/ops/namespace-token-development-create/Cargo.toml +++ b/svc/pkg/cloud/ops/namespace-token-development-create/Cargo.toml @@ -15,7 +15,7 @@ game-token-development-validate = { path = "../../../game/ops/token-development- token-create = { path = "../../../token/ops/create" } [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/cloud/ops/namespace-token-public-create/Cargo.toml b/svc/pkg/cloud/ops/namespace-token-public-create/Cargo.toml index 3d6563061f..2ba6eb987b 100644 --- a/svc/pkg/cloud/ops/namespace-token-public-create/Cargo.toml +++ b/svc/pkg/cloud/ops/namespace-token-public-create/Cargo.toml @@ -15,7 +15,7 @@ game-namespace-get = { path = "../../../game/ops/namespace-get" } token-create = { path = "../../../token/ops/create" } [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/cloud/ops/version-get/Cargo.toml b/svc/pkg/cloud/ops/version-get/Cargo.toml index f6d4ce3cc5..e22fc993c6 100644 --- a/svc/pkg/cloud/ops/version-get/Cargo.toml +++ b/svc/pkg/cloud/ops/version-get/Cargo.toml @@ -18,7 +18,7 @@ mm-config-version-get = { path = "../../../mm-config/ops/version-get" } module-game-version-get = { path = "../../../module/ops/game-version-get" } [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/cloud/ops/version-get/tests/integration.rs b/svc/pkg/cloud/ops/version-get/tests/integration.rs index d835ba3187..2f00f80138 100644 --- a/svc/pkg/cloud/ops/version-get/tests/integration.rs +++ b/svc/pkg/cloud/ops/version-get/tests/integration.rs @@ -38,6 +38,7 @@ async fn empty(ctx: TestCtx) { max_players_normal: 8, max_players_direct: 10, max_players_party: 12, + listable: true, runtime: Some(backend::matchmaker::lobby_runtime::Docker { build_id: build_res.build_id, @@ -59,6 +60,10 @@ async fn empty(ctx: TestCtx) { }, ], }.into()), + + find_config: None, + join_config: None, + create_config: None, }, ], captcha: None, diff --git a/svc/pkg/cloud/ops/version-publish/Cargo.toml b/svc/pkg/cloud/ops/version-publish/Cargo.toml index 47cbc69a45..43da7e59e4 100644 --- a/svc/pkg/cloud/ops/version-publish/Cargo.toml +++ b/svc/pkg/cloud/ops/version-publish/Cargo.toml @@ -25,7 +25,7 @@ module-game-version-prepare = { path = "../../../module/ops/game-version-prepare module-game-version-publish = { path = "../../../module/ops/game-version-publish" } [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/cloud/ops/version-publish/tests/integration.rs b/svc/pkg/cloud/ops/version-publish/tests/integration.rs index e3717e56ab..bc39f543db 100644 --- a/svc/pkg/cloud/ops/version-publish/tests/integration.rs +++ b/svc/pkg/cloud/ops/version-publish/tests/integration.rs @@ -45,6 +45,7 @@ async fn empty(ctx: TestCtx) { max_players_normal: 8, max_players_direct: 10, max_players_party: 12, + listable: true, runtime: Some(backend::matchmaker::lobby_runtime::Docker { build_id: build_res.build_id, @@ -66,6 +67,10 @@ async fn empty(ctx: TestCtx) { }, ], }.into()), + + find_config: None, + join_config: None, + create_config: None, }, ], captcha: None, diff --git a/svc/pkg/cloud/worker/src/workers/device_link_complete.rs b/svc/pkg/cloud/worker/src/workers/device_link_complete.rs index 282e75a9af..e167f2dd7d 100644 --- a/svc/pkg/cloud/worker/src/workers/device_link_complete.rs +++ b/svc/pkg/cloud/worker/src/workers/device_link_complete.rs @@ -3,7 +3,7 @@ use proto::backend::pkg::*; #[worker(name = "cloud-device-link-complete")] async fn worker( - ctx: OperationContext, + ctx: &OperationContext, ) -> GlobalResult<()> { let device_link_id = internal_unwrap!(ctx.device_link_id).as_uuid(); diff --git a/svc/pkg/custom-user-avatar/ops/list-for-game/Cargo.toml b/svc/pkg/custom-user-avatar/ops/list-for-game/Cargo.toml index 24e87ab191..4fce1dc75b 100644 --- a/svc/pkg/custom-user-avatar/ops/list-for-game/Cargo.toml +++ b/svc/pkg/custom-user-avatar/ops/list-for-game/Cargo.toml @@ -11,7 +11,7 @@ chirp-client = { path = "../../../../../lib/chirp/client" } prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/custom-user-avatar/ops/upload-complete/Cargo.toml b/svc/pkg/custom-user-avatar/ops/upload-complete/Cargo.toml index 4f85ad4e95..24abf1e7b6 100644 --- a/svc/pkg/custom-user-avatar/ops/upload-complete/Cargo.toml +++ b/svc/pkg/custom-user-avatar/ops/upload-complete/Cargo.toml @@ -13,7 +13,7 @@ prost = "0.10" upload-complete = { path = "../../../upload/ops/complete" } [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/debug/ops/email-res/Cargo.toml b/svc/pkg/debug/ops/email-res/Cargo.toml index 2e32780ca8..009dc7a79a 100644 --- a/svc/pkg/debug/ops/email-res/Cargo.toml +++ b/svc/pkg/debug/ops/email-res/Cargo.toml @@ -13,7 +13,7 @@ rand = "0.8" serde_json = "1.0" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/email-verification/ops/complete/Cargo.toml b/svc/pkg/email-verification/ops/complete/Cargo.toml index aff5e415de..0dcf81bd18 100644 --- a/svc/pkg/email-verification/ops/complete/Cargo.toml +++ b/svc/pkg/email-verification/ops/complete/Cargo.toml @@ -12,7 +12,7 @@ chrono = "0.4" prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/email-verification/ops/create/Cargo.toml b/svc/pkg/email-verification/ops/create/Cargo.toml index 5a0847998f..46bfea86ad 100644 --- a/svc/pkg/email-verification/ops/create/Cargo.toml +++ b/svc/pkg/email-verification/ops/create/Cargo.toml @@ -18,7 +18,7 @@ email-send = { path = "../../../email/ops/send" } game-get = { path = "../../../game/ops/get" } [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/external/ops/request-validate/Cargo.toml b/svc/pkg/external/ops/request-validate/Cargo.toml new file mode 100644 index 0000000000..e52a7f4686 --- /dev/null +++ b/svc/pkg/external/ops/request-validate/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "external-request-validate" +version = "0.0.1" +edition = "2018" +authors = ["Rivet Gaming, LLC "] +license = "Apache-2.0" + +[dependencies] +chirp-client = { path = "../../../../../lib/chirp/client" } +chrono = "0.4" +http = "0.2" +prost = "0.10" +reqwest = { version = "0.11" } +rivet-operation = { path = "../../../../../lib/operation/core" } +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" + +[dependencies.sqlx] +version = "0.7" +default-features = false + +[dev-dependencies] +chirp-worker = { path = "../../../../../lib/chirp/worker" } diff --git a/svc/pkg/external/ops/request-validate/README.md b/svc/pkg/external/ops/request-validate/README.md new file mode 100644 index 0000000000..120b8e9d0b --- /dev/null +++ b/svc/pkg/external/ops/request-validate/README.md @@ -0,0 +1 @@ +# external-request-validate diff --git a/svc/pkg/external/ops/request-validate/Service.toml b/svc/pkg/external/ops/request-validate/Service.toml new file mode 100644 index 0000000000..5f986171cd --- /dev/null +++ b/svc/pkg/external/ops/request-validate/Service.toml @@ -0,0 +1,7 @@ +[service] +name = "external-request-validate" + +[runtime] +kind = "rust" + +[operation] diff --git a/svc/pkg/external/ops/request-validate/src/lib.rs b/svc/pkg/external/ops/request-validate/src/lib.rs new file mode 100644 index 0000000000..bb70062070 --- /dev/null +++ b/svc/pkg/external/ops/request-validate/src/lib.rs @@ -0,0 +1,127 @@ +use http::{uri::Scheme, HeaderName, HeaderValue, Uri}; +use std::{net::IpAddr, str::FromStr}; + +use proto::backend::pkg::*; +use rivet_operation::prelude::*; + +#[operation(name = "external-request-validate")] +async fn handle( + ctx: OperationContext, +) -> GlobalResult { + let config = internal_unwrap!(ctx.config); + let mut errors = Vec::new(); + + // Parse URL + if let Ok(url) = config.url.parse::() { + if let Some(host) = url.host() { + // Validate as IP + if let Ok(ip) = IpAddr::from_str(host) { + // Validate that IP is global + if !is_global_ip(ip) { + errors.push(util::err_path!["url", "invalid-ip"]); + } + } + // Validate that URL is not internal + else if host.ends_with(".consul") { + errors.push(util::err_path!["url", "invalid"]); + } + + // Validate URL scheme + if let Some(scheme) = url.scheme() { + if scheme != &Scheme::HTTP && scheme != &Scheme::HTTPS { + errors.push(util::err_path!["url", "invalid-scheme"]); + } + } else { + errors.push(util::err_path!["url", "invalid-scheme"]); + } + } else { + errors.push(util::err_path!["url", "no-host"]); + } + } else { + errors.push(util::err_path!["url", "invalid"]); + } + + // Validate DNS + if errors.is_empty() { + let req = reqwest::Client::new() + .get(&config.url) + .timeout(std::time::Duration::from_secs(5)); + + if let Err(err) = req.send().await { + if err.is_connect() { + errors.push(util::err_path!["url", "dns-failed"]); + } else if err.is_timeout() { + errors.push(util::err_path!["url", "dns-timeout"]); + } else { + // Throw error if its not a connection or timeout problem + return Err(err.into()); + } + } + } + + // Validate headers + for (k, v) in &config.headers { + let header_label = format!("*{}*", k); + + if HeaderName::from_str(k).is_err() { + errors.push(util::err_path!["headers", header_label, "invalid-name"]); + } + if HeaderValue::from_str(v).is_err() { + errors.push(util::err_path!["headers", header_label, "invalid-value"]); + } + } + + Ok(external::request_validate::Response { + errors: errors + .into_iter() + .map(|path| external::request_validate::response::Error { path }) + .collect::>(), + }) +} + +// TODO: Replace with `IpAddr::is_global` whenever that stabilizes +#[allow(clippy::manual_range_contains)] +fn is_global_ip(ip: IpAddr) -> bool { + match ip { + IpAddr::V4(ip) => { + !(ip.octets()[0] == 0 // "This network" + || ip.is_private() + || (ip.octets()[0] == 100 && (ip.octets()[1] & 0b1100_0000 == 0b0100_0000)) + || ip.is_loopback() + || ip.is_link_local() + // addresses reserved for future protocols (`192.0.0.0/24`) + ||(ip.octets()[0] == 192 && ip.octets()[1] == 0 && ip.octets()[2] == 0) + || ip.is_documentation() + || (ip.octets()[0] == 198 && (ip.octets()[1] & 0xfe) == 18) + || (ip.octets()[0] & 240 == 240 && !ip.is_broadcast()) + || ip.is_broadcast()) + } + IpAddr::V6(ip) => { + !(ip.is_unspecified() + || ip.is_loopback() + // IPv4-mapped Address (`::ffff:0:0/96`) + || matches!(ip.segments(), [0, 0, 0, 0, 0, 0xffff, _, _]) + // IPv4-IPv6 Translat. (`64:ff9b:1::/48`) + || matches!(ip.segments(), [0x64, 0xff9b, 1, _, _, _, _, _]) + // Discard-Only Address Block (`100::/64`) + || matches!(ip.segments(), [0x100, 0, 0, 0, _, _, _, _]) + // IETF Protocol Assignments (`2001::/23`) + || (matches!(ip.segments(), [0x2001, b, _, _, _, _, _, _] if b < 0x200) + && !( + // Port Control Protocol Anycast (`2001:1::1`) + u128::from_be_bytes(ip.octets()) == 0x2001_0001_0000_0000_0000_0000_0000_0001 + // Traversal Using Relays around NAT Anycast (`2001:1::2`) + || u128::from_be_bytes(ip.octets()) == 0x2001_0001_0000_0000_0000_0000_0000_0002 + // AMT (`2001:3::/32`) + || matches!(ip.segments(), [0x2001, 3, _, _, _, _, _, _]) + // AS112-v6 (`2001:4:112::/48`) + || matches!(ip.segments(), [0x2001, 4, 0x112, _, _, _, _, _]) + // ORCHIDv2 (`2001:20::/28`) + || matches!(ip.segments(), [0x2001, b, _, _, _, _, _, _] if b >= 0x20 && b <= 0x2F) + )) + || ((ip.segments()[0] == 0x2001) && (ip.segments()[1] == 0xdb8)) + || ((ip.segments()[0] & 0xfe00) == 0xfc00) + || ((ip.segments()[0] & 0xffc0) == 0xfe80)) + } + } +} diff --git a/svc/pkg/external/ops/request-validate/tests/integration.rs b/svc/pkg/external/ops/request-validate/tests/integration.rs new file mode 100644 index 0000000000..071e625af7 --- /dev/null +++ b/svc/pkg/external/ops/request-validate/tests/integration.rs @@ -0,0 +1,42 @@ +use std::collections::HashMap; + +use chirp_worker::prelude::*; +use proto::backend; + +#[worker_test] +async fn empty(ctx: TestCtx) { + let headers = IntoIterator::into_iter([( + " invalid name ".to_string(), + "\ninvalid value".to_string(), + )]) + .collect::>(); + + let res = op!([ctx] external_request_validate { + config: Some(backend::net::ExternalRequestConfig { + url: "ssh://example.com".to_string(), + method: backend::net::HttpMethod::Get as i32, + headers, + }), + }) + .await + .unwrap(); + + tracing::info!(errors=?res.errors); + assert_eq!(3, res.errors.len()); +} + +#[worker_test] +async fn dns(ctx: TestCtx) { + let res = op!([ctx] external_request_validate { + config: Some(backend::net::ExternalRequestConfig { + url: "https://httpstat.us/200?sleep=6000".to_string(), + method: backend::net::HttpMethod::Get as i32, + headers: HashMap::new(), + }), + }) + .await + .unwrap(); + + tracing::info!(errors=?res.errors); + assert_eq!(1, res.errors.len()); +} diff --git a/svc/pkg/external/types/msg/request-call-complete.proto b/svc/pkg/external/types/msg/request-call-complete.proto new file mode 100644 index 0000000000..3b59c2c5f0 --- /dev/null +++ b/svc/pkg/external/types/msg/request-call-complete.proto @@ -0,0 +1,16 @@ +syntax = "proto3"; + +package rivet.backend.pkg.external.msg.request_call_complete; + +import "proto/common.proto"; + +/// name = "msg-external-request-call-complete" +/// parameters = [ +/// { name = "request_id" }, +/// ] +message Message { + rivet.common.Uuid request_id = 1; + uint32 status_code = 2; + // This property is only set if `read_response_body` is true in the `external-request-call` message + optional bytes body = 3; +} diff --git a/svc/pkg/external/types/msg/request-call-fail.proto b/svc/pkg/external/types/msg/request-call-fail.proto new file mode 100644 index 0000000000..8fa51de69c --- /dev/null +++ b/svc/pkg/external/types/msg/request-call-fail.proto @@ -0,0 +1,21 @@ +syntax = "proto3"; + +package rivet.backend.pkg.external.msg.request_call_fail; + +import "proto/common.proto"; + +enum ErrorCode { + UNKNOWN = 0; + + REQUEST_FAILED = 1; +} + +/// name = "msg-external-request-call-fail" +/// parameters = [ +/// { name = "request_id" }, +/// ] +message Message { + rivet.common.Uuid request_id = 1; + ErrorCode error_code = 2; +} + diff --git a/svc/pkg/external/types/msg/request-call.proto b/svc/pkg/external/types/msg/request-call.proto new file mode 100644 index 0000000000..c668a75954 --- /dev/null +++ b/svc/pkg/external/types/msg/request-call.proto @@ -0,0 +1,19 @@ +syntax = "proto3"; + +package rivet.backend.pkg.external.msg.request_call; + +import "proto/common.proto"; +import "proto/backend/net.proto"; + +/// name = "msg-external-request-call" +/// parameters = [ +/// { name = "request_id" }, +/// ] +message Message { + rivet.common.Uuid request_id = 1; + rivet.backend.net.ExternalRequestConfig config = 2; + // 0 for no timeout + uint64 timeout = 3; + optional bytes body = 4; + bool read_response_body = 5; +} diff --git a/svc/pkg/external/types/request-validate.proto b/svc/pkg/external/types/request-validate.proto new file mode 100644 index 0000000000..893cc38125 --- /dev/null +++ b/svc/pkg/external/types/request-validate.proto @@ -0,0 +1,18 @@ +syntax = "proto3"; + +package rivet.backend.pkg.external.request_validate; + +import "proto/common.proto"; +import "proto/backend/net.proto"; + +message Request { + rivet.backend.net.ExternalRequestConfig config = 1; +} + +message Response { + message Error { + repeated string path = 1; + } + + repeated Error errors = 1; +} diff --git a/svc/pkg/external/worker/Cargo.toml b/svc/pkg/external/worker/Cargo.toml new file mode 100644 index 0000000000..f64c5805bd --- /dev/null +++ b/svc/pkg/external/worker/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "external-worker" +version = "0.0.1" +edition = "2018" +authors = ["Rivet Gaming, LLC "] +license = "Apache-2.0" + +[dependencies] +chirp-worker = { path = "../../../../lib/chirp/worker" } +chirp-client = { path = "../../../../lib/chirp/client" } +reqwest = { version = "0.11" } +rivet-health-checks = { path = "../../../../lib/health-checks" } +rivet-metrics = { path = "../../../../lib/metrics" } +rivet-runtime = { path = "../../../../lib/runtime" } +chrono = "0.4" + +[dev-dependencies] +chirp-worker = { path = "../../../../lib/chirp/worker" } diff --git a/svc/pkg/external/worker/Service.toml b/svc/pkg/external/worker/Service.toml new file mode 100644 index 0000000000..62db18d071 --- /dev/null +++ b/svc/pkg/external/worker/Service.toml @@ -0,0 +1,7 @@ +[service] +name = "external-worker" + +[runtime] +kind = "rust" + +[consumer] diff --git a/svc/pkg/external/worker/src/main.rs b/svc/pkg/external/worker/src/main.rs new file mode 100644 index 0000000000..fc7071fc27 --- /dev/null +++ b/svc/pkg/external/worker/src/main.rs @@ -0,0 +1,14 @@ +use chirp_worker::prelude::*; +use chirp_worker::ManagerError; + +mod workers; +use workers::*; + +fn main() -> Result<(), ManagerError> { + // Start runtime + rivet_runtime::run(async move { + worker_group![request_call].await; + + Result::<_, ManagerError>::Ok(()) + })? +} diff --git a/svc/pkg/external/worker/src/workers/mod.rs b/svc/pkg/external/worker/src/workers/mod.rs new file mode 100644 index 0000000000..a1682bc1f2 --- /dev/null +++ b/svc/pkg/external/worker/src/workers/mod.rs @@ -0,0 +1 @@ +pub mod request_call; diff --git a/svc/pkg/external/worker/src/workers/request_call.rs b/svc/pkg/external/worker/src/workers/request_call.rs new file mode 100644 index 0000000000..9353d6850b --- /dev/null +++ b/svc/pkg/external/worker/src/workers/request_call.rs @@ -0,0 +1,103 @@ +use std::str::FromStr; + +use chirp_worker::prelude::*; +use proto::backend::{net::HttpMethod, pkg::*}; +use reqwest::{ + header::{HeaderMap, HeaderName, HeaderValue}, + StatusCode, +}; + +#[tracing::instrument] +async fn fail( + ctx: &OperationContext, + request_id: Uuid, + error_code: external::msg::request_call_fail::ErrorCode, +) -> GlobalResult<()> { + msg!([ctx] external::msg::request_call_fail(request_id) { + request_id: Some(request_id.into()), + error_code: error_code as i32, + }) + .await?; + + Ok(()) +} + +#[worker(name = "external-request-call")] +async fn worker(ctx: &OperationContext) -> GlobalResult<()> { + let request_id = internal_unwrap!(ctx.request_id).as_uuid(); + let config = internal_unwrap!(ctx.config); + + let req = reqwest::Client::new(); + + // Add method + let method = internal_unwrap_owned!(HttpMethod::from_i32(config.method), "invalid http method"); + let req = match method { + HttpMethod::Get => req.get(&config.url), + HttpMethod::Post => req.post(&config.url), + HttpMethod::Put => req.put(&config.url), + HttpMethod::Delete => req.delete(&config.url), + }; + + // Add body + // TODO: Figure out a way to not clone this + let req = if let Some(body) = ctx.body.clone() { + req.body(body) + } else { + req + }; + + // Add headers (NOTE: If using a config that has been validated by `external-request-validate`, the + // creation of this header map should be infallible) + let headers = config + .headers + .iter() + .map(|(k, v)| Ok((HeaderName::from_str(k)?, HeaderValue::from_str(v)?))) + .collect::>()?; + let req = req.headers(headers); + + // Add timeout + let req = if ctx.timeout != 0 { + let timeout = std::time::Duration::from_millis(ctx.timeout); + req.timeout(timeout) + } else { + req + }; + + // Execute + let (status, body) = match req.send().await { + Ok(res) => ( + res.status().as_u16(), + if ctx.read_response_body { + Some(res.bytes().await?.to_vec()) + } else { + None + }, + ), + Err(err) => { + // Coerce reqwest timeout into http request timeout + if err.is_timeout() { + (StatusCode::REQUEST_TIMEOUT.as_u16(), None) + } else { + tracing::info!(?err, "external request failed"); + + fail( + ctx, + request_id, + external::msg::request_call_fail::ErrorCode::RequestFailed, + ) + .await?; + + return Ok(()); + } + } + }; + + msg!([ctx] external::msg::request_call_complete(request_id) { + request_id: ctx.request_id, + status_code: status as u32, + body: body, + }) + .await?; + + Ok(()) +} diff --git a/svc/pkg/external/worker/tests/request_call.rs b/svc/pkg/external/worker/tests/request_call.rs new file mode 100644 index 0000000000..86c2b5f7c3 --- /dev/null +++ b/svc/pkg/external/worker/tests/request_call.rs @@ -0,0 +1,69 @@ +use std::collections::HashMap; + +use chirp_worker::prelude::*; +use proto::backend::{self, pkg::*}; + +#[worker_test] +async fn empty(ctx: TestCtx) { + let request_id = Uuid::new_v4(); + let res = + msg!([ctx] external::msg::request_call(request_id) -> external::msg::request_call_complete { + request_id: Some(request_id.into()), + config: Some(backend::net::ExternalRequestConfig { + url: "https://example.com".to_string(), + method: backend::net::HttpMethod::Get as i32, + headers: HashMap::new(), + }), + timeout: 0, + body: None, + read_response_body: true, + }) + .await + .unwrap(); + + assert_eq!(200, res.status_code); + // TODO: Verify body + tracing::info!(body=?std::str::from_utf8(res.body.as_ref().unwrap())); +} + +#[worker_test] +async fn delete(ctx: TestCtx) { + let request_id = Uuid::new_v4(); + let res = + msg!([ctx] external::msg::request_call(request_id) -> external::msg::request_call_complete { + request_id: Some(request_id.into()), + config: Some(backend::net::ExternalRequestConfig { + url: "https://example.com".to_string(), + method: backend::net::HttpMethod::Delete as i32, + headers: HashMap::new(), + }), + timeout: 0, + body: None, + read_response_body: false, + }) + .await + .unwrap(); + + assert_eq!(405, res.status_code); +} + +#[worker_test] +async fn timeout(ctx: TestCtx) { + let request_id = Uuid::new_v4(); + let res = + msg!([ctx] external::msg::request_call(request_id) -> external::msg::request_call_complete { + request_id: Some(request_id.into()), + config: Some(backend::net::ExternalRequestConfig { + url: "https://httpstat.us/200?sleep=10000".to_string(), + method: backend::net::HttpMethod::Get as i32, + headers: HashMap::new(), + }), + timeout: 1000, + body: None, + read_response_body: false, + }) + .await + .unwrap(); + + assert_eq!(408, res.status_code); +} diff --git a/svc/pkg/faker/ops/game-version/src/lib.rs b/svc/pkg/faker/ops/game-version/src/lib.rs index 036d2dca40..e64262f137 100644 --- a/svc/pkg/faker/ops/game-version/src/lib.rs +++ b/svc/pkg/faker/ops/game-version/src/lib.rs @@ -12,67 +12,68 @@ async fn handle( }) .await?; - let config = if let Some(config) = ctx.override_config.clone() { - config - } else { - backend::cloud::VersionConfig { - cdn: if let Some(config) = ctx.override_cdn_config.clone() { - config.config - } else { - let cdn_site_res = op!([ctx] faker_cdn_site { - game_id: Some(*game_id), - }) - .await?; - let site_id = internal_unwrap!(cdn_site_res.site_id); + let config = + if let Some(config) = ctx.override_config.clone() { + config + } else { + backend::cloud::VersionConfig { + cdn: if let Some(config) = ctx.override_cdn_config.clone() { + config.config + } else { + let cdn_site_res = op!([ctx] faker_cdn_site { + game_id: Some(*game_id), + }) + .await?; + let site_id = internal_unwrap!(cdn_site_res.site_id); - Some(VersionConfig { - site_id: Some(*site_id), - routes: vec![ - Route { - glob: Some(util::glob::Glob::parse("test-glob")?.into()), - priority: 0, - middlewares: vec![Middleware { - kind: Some(middleware::Kind::CustomHeaders( - CustomHeadersMiddleware { - headers: vec![custom_headers_middleware::Header { - name: "header-name".to_string(), - value: "header-value".to_string(), - }], - }, - )), - }], - }, - Route { - glob: Some(util::glob::Glob::parse("test-glob2")?.into()), - priority: 1, - middlewares: vec![Middleware { - kind: Some(middleware::Kind::CustomHeaders( - CustomHeadersMiddleware { - headers: vec![custom_headers_middleware::Header { - name: "header-name2".to_string(), - value: "header-value2".to_string(), - }], - }, - )), - }], - }, - ], - }) - }, - matchmaker: if let Some(config) = ctx.override_mm_config.clone() { - config.config - } else { - let build_res = op!([ctx] faker_build { - game_id: Some(*game_id), - image: faker::build::Image::MmLobbyAutoReady as i32, - }) - .await?; - let build_id = internal_unwrap!(build_res.build_id); + Some(VersionConfig { + site_id: Some(*site_id), + routes: vec![ + Route { + glob: Some(util::glob::Glob::parse("test-glob")?.into()), + priority: 0, + middlewares: vec![Middleware { + kind: Some(middleware::Kind::CustomHeaders( + CustomHeadersMiddleware { + headers: vec![custom_headers_middleware::Header { + name: "header-name".to_string(), + value: "header-value".to_string(), + }], + }, + )), + }], + }, + Route { + glob: Some(util::glob::Glob::parse("test-glob2")?.into()), + priority: 1, + middlewares: vec![Middleware { + kind: Some(middleware::Kind::CustomHeaders( + CustomHeadersMiddleware { + headers: vec![custom_headers_middleware::Header { + name: "header-name2".to_string(), + value: "header-value2".to_string(), + }], + }, + )), + }], + }, + ], + }) + }, + matchmaker: if let Some(config) = ctx.override_mm_config.clone() { + config.config + } else { + let build_res = op!([ctx] faker_build { + game_id: Some(*game_id), + image: faker::build::Image::MmLobbyAutoReady as i32, + }) + .await?; + let build_id = internal_unwrap!(build_res.build_id); - Some(backend::matchmaker::VersionConfig { - lobby_groups: ctx.override_lobby_groups.clone().map_or_else( - || { - vec![backend::matchmaker::LobbyGroup { + Some(backend::matchmaker::VersionConfig { + lobby_groups: ctx.override_lobby_groups.clone().map_or_else( + || { + vec![backend::matchmaker::LobbyGroup { name_id: "test-1".into(), regions: region_list_res @@ -82,13 +83,20 @@ async fn handle( .map(|region_id| backend::matchmaker::lobby_group::Region { region_id: Some(region_id), tier_name_id: util_mm::test::TIER_NAME_ID.to_owned(), - idle_lobbies: None, + idle_lobbies: Some(backend::matchmaker::lobby_group::IdleLobbies { + min_idle_lobbies: 0, + // Set a high max lobby count in case this is + // coming from a test that test mm-lobby-create + // without creating an associated player + max_idle_lobbies: 32, + }), }) .collect(), max_players_normal: 8, max_players_direct: 10, max_players_party: 12, + listable: true, runtime: Some( backend::matchmaker::lobby_runtime::Docker { @@ -102,40 +110,44 @@ async fn handle( } .into(), ), + + find_config: None, + join_config: None, + create_config: None, }] - }, - |v| v.lobby_groups, - ), - captcha: ctx - .override_captcha - .clone() - .map_or_else(|| None, |config| config.captcha_config), - }) - }, - kv: if let Some(config) = ctx.override_kv_config.clone() { - config.config - } else { - Some(backend::kv::VersionConfig {}) - }, - identity: if let Some(config) = ctx.override_identity_config.clone() { - config.config - } else { - Some(backend::identity::VersionConfig { - custom_display_names: vec![backend::identity::CustomDisplayName { - display_name: "Guest".to_string(), - }], - custom_avatars: Vec::new(), - }) - }, - module: if let Some(config) = ctx.override_module_config.clone() { - config.config - } else { - Some(backend::module::GameVersionConfig { - dependencies: Vec::new(), - }) - }, - } - }; + }, + |v| v.lobby_groups, + ), + captcha: ctx + .override_captcha + .clone() + .map_or_else(|| None, |config| config.captcha_config), + }) + }, + kv: if let Some(config) = ctx.override_kv_config.clone() { + config.config + } else { + Some(backend::kv::VersionConfig {}) + }, + identity: if let Some(config) = ctx.override_identity_config.clone() { + config.config + } else { + Some(backend::identity::VersionConfig { + custom_display_names: vec![backend::identity::CustomDisplayName { + display_name: "Guest".to_string(), + }], + custom_avatars: Vec::new(), + }) + }, + module: if let Some(config) = ctx.override_module_config.clone() { + config.config + } else { + Some(backend::module::GameVersionConfig { + dependencies: Vec::new(), + }) + }, + } + }; let version_create_res = op!([ctx] cloud_version_publish { game_id: Some(*game_id), diff --git a/svc/pkg/faker/ops/mm-lobby/src/lib.rs b/svc/pkg/faker/ops/mm-lobby/src/lib.rs index 5f66a919a0..53e07b961b 100644 --- a/svc/pkg/faker/ops/mm-lobby/src/lib.rs +++ b/svc/pkg/faker/ops/mm-lobby/src/lib.rs @@ -70,11 +70,18 @@ async fn handle( regions: vec![backend::matchmaker::lobby_group::Region { region_id: region_res.region_id, tier_name_id: util_mm::test::TIER_NAME_ID.to_owned(), - idle_lobbies: None, + idle_lobbies: Some(backend::matchmaker::lobby_group::IdleLobbies { + min_idle_lobbies: 0, + // Set a high max lobby count in case this is + // coming from a test that test mm-lobby-create + // without creating an associated player + max_idle_lobbies: 32, + }), }], max_players_normal, max_players_direct, max_players_party, + listable: true, runtime: Some(backend::matchmaker::lobby_runtime::Docker { build_id: build_res.build_id, @@ -83,6 +90,10 @@ async fn handle( network_mode: backend::matchmaker::lobby_runtime::NetworkMode::Bridge as i32, ports: Vec::new(), }.into()), + + find_config: None, + join_config: None, + create_config: None, }], }), ..Default::default() @@ -127,6 +138,11 @@ async fn handle( region_id: region_res.region_id, create_ray_id: Some(ctx.ray_id().into()), preemptively_created: false, + + creator_user_id: ctx.creator_user_id, + is_custom: ctx.is_custom, + publicity: ctx.publicity, + lobby_config_json: ctx.lobby_config_json.clone(), }) .await?; let run_id = internal_unwrap!(complete_msg.run_id).as_uuid(); diff --git a/svc/pkg/faker/ops/mm-player/src/lib.rs b/svc/pkg/faker/ops/mm-player/src/lib.rs index a28bc80dcf..b8402cea1f 100644 --- a/svc/pkg/faker/ops/mm-player/src/lib.rs +++ b/svc/pkg/faker/ops/mm-player/src/lib.rs @@ -44,7 +44,9 @@ async fn handle( // Find lobby let query_id = Uuid::new_v4(); - let find_res = msg!([ctx] @notrace mm::msg::lobby_find(namespace_id, query_id) -> Result { + let find_res = msg!([ctx] @notrace mm::msg::lobby_find(namespace_id, query_id) + -> Result + { namespace_id: ctx.namespace_id, query_id: Some(query_id.into()), join_kind: backend::matchmaker::query::JoinKind::Normal as i32, @@ -56,6 +58,7 @@ async fn handle( query: Some(mm::msg::lobby_find::message::Query::Direct(backend::matchmaker::query::Direct { lobby_id: ctx.lobby_id, })), + ..Default::default() }) .await?; @@ -79,6 +82,13 @@ async fn handle( RegionNotEnabled => panic_with!(MATCHMAKER_REGION_NOT_ENABLED_FOR_GAME_MODE), DevTeamInvalidStatus => panic_with!(GROUP_INVALID_DEVELOPER_STATUS), + + FindDisabled => panic_with!(MATCHMAKER_FIND_DISABLED), + JoinDisabled => panic_with!(MATCHMAKER_JOIN_DISABLED), + VerificationFailed => panic_with!(MATCHMAKER_VERIFICATION_FAILED), + VerificationRequestFailed => panic_with!(MATCHMAKER_VERIFICATION_REQUEST_FAILED), + IdentityRequired => panic_with!(MATCHMAKER_IDENTITY_REQUIRED), + RegistrationRequired => panic_with!(MATCHMAKER_REGISTRATION_REQUIRED), }; } Err(None) => internal_panic!("failed to parse find error code"), diff --git a/svc/pkg/faker/ops/region/Cargo.toml b/svc/pkg/faker/ops/region/Cargo.toml index 51d1ad74e2..8d867ec66c 100644 --- a/svc/pkg/faker/ops/region/Cargo.toml +++ b/svc/pkg/faker/ops/region/Cargo.toml @@ -14,7 +14,7 @@ region-get = { path = "../../../region/ops/get" } region-list = { path = "../../../region/ops/list" } [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/faker/types/mm-lobby.proto b/svc/pkg/faker/types/mm-lobby.proto index e1ce34743f..1fa2fbd6db 100644 --- a/svc/pkg/faker/types/mm-lobby.proto +++ b/svc/pkg/faker/types/mm-lobby.proto @@ -14,6 +14,11 @@ message Request { uint32 max_players_party = 3; bool skip_set_ready = 4; optional rivet.backend.pkg.faker.build.Image image = 5; + + optional rivet.common.Uuid creator_user_id = 8; + bool is_custom = 9; + optional rivet.backend.matchmaker.Lobby.Publicity publicity = 10; + optional string lobby_config_json = 11; } message Response { diff --git a/svc/pkg/game-user/ops/create/Cargo.toml b/svc/pkg/game-user/ops/create/Cargo.toml index 1bc747b181..6f51cbe6e9 100644 --- a/svc/pkg/game-user/ops/create/Cargo.toml +++ b/svc/pkg/game-user/ops/create/Cargo.toml @@ -15,7 +15,7 @@ util-game-user = { package = "rivet-util-game-user", path = "../../util" } token-create = { path = "../../../token/ops/create" } [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/game-user/ops/get/Cargo.toml b/svc/pkg/game-user/ops/get/Cargo.toml index 7caeebcac5..b9e18a51f1 100644 --- a/svc/pkg/game-user/ops/get/Cargo.toml +++ b/svc/pkg/game-user/ops/get/Cargo.toml @@ -12,7 +12,7 @@ chrono = "0.4" prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/game-user/ops/link-create/Cargo.toml b/svc/pkg/game-user/ops/link-create/Cargo.toml index 2641a89814..6dc921d1bd 100644 --- a/svc/pkg/game-user/ops/link-create/Cargo.toml +++ b/svc/pkg/game-user/ops/link-create/Cargo.toml @@ -15,7 +15,7 @@ game-user-get = { path = "../get" } token-create = { path = "../../../token/ops/create" } [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/game-user/ops/link-get/Cargo.toml b/svc/pkg/game-user/ops/link-get/Cargo.toml index 27f3cac553..ac06ab5f1a 100644 --- a/svc/pkg/game-user/ops/link-get/Cargo.toml +++ b/svc/pkg/game-user/ops/link-get/Cargo.toml @@ -12,7 +12,7 @@ chrono = "0.4" prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/game-user/ops/list-for-user/Cargo.toml b/svc/pkg/game-user/ops/list-for-user/Cargo.toml index f517494567..091a0886ee 100644 --- a/svc/pkg/game-user/ops/list-for-user/Cargo.toml +++ b/svc/pkg/game-user/ops/list-for-user/Cargo.toml @@ -12,7 +12,7 @@ chrono = "0.4" prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/game-user/ops/recent-session-list/Cargo.toml b/svc/pkg/game-user/ops/recent-session-list/Cargo.toml index 7f43946381..ac365db3b5 100644 --- a/svc/pkg/game-user/ops/recent-session-list/Cargo.toml +++ b/svc/pkg/game-user/ops/recent-session-list/Cargo.toml @@ -12,7 +12,7 @@ chrono = "0.4" prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/game-user/worker/Cargo.toml b/svc/pkg/game-user/worker/Cargo.toml index 7bb8d102a3..58c0914233 100644 --- a/svc/pkg/game-user/worker/Cargo.toml +++ b/svc/pkg/game-user/worker/Cargo.toml @@ -19,7 +19,7 @@ token-exchange = { path = "../../token/ops/exchange" } token-revoke = { path = "../../token/ops/revoke" } [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/game-user/worker/src/workers/link_complete.rs b/svc/pkg/game-user/worker/src/workers/link_complete.rs index c985c266ed..9e902f281b 100644 --- a/svc/pkg/game-user/worker/src/workers/link_complete.rs +++ b/svc/pkg/game-user/worker/src/workers/link_complete.rs @@ -3,7 +3,9 @@ use proto::backend::pkg::*; use serde_json::json; #[worker(name = "game-user-link-complete")] -async fn worker(ctx: OperationContext) -> GlobalResult<()> { +async fn worker( + ctx: &OperationContext, +) -> GlobalResult<()> { let crdb = ctx.crdb("db-game-user").await?; let user_id = internal_unwrap!(ctx.user_id).as_uuid(); diff --git a/svc/pkg/game-user/worker/src/workers/session_create.rs b/svc/pkg/game-user/worker/src/workers/session_create.rs index fb4ffffa80..47ca0b21a4 100644 --- a/svc/pkg/game-user/worker/src/workers/session_create.rs +++ b/svc/pkg/game-user/worker/src/workers/session_create.rs @@ -3,7 +3,7 @@ use proto::backend::pkg::*; #[worker(name = "game-user-session-create")] async fn worker( - ctx: OperationContext, + ctx: &OperationContext, ) -> GlobalResult<()> { let crdb = ctx.crdb("db-game-user").await?; diff --git a/svc/pkg/game/ops/banner-upload-complete/Cargo.toml b/svc/pkg/game/ops/banner-upload-complete/Cargo.toml index 810390d9db..59078fd7c5 100644 --- a/svc/pkg/game/ops/banner-upload-complete/Cargo.toml +++ b/svc/pkg/game/ops/banner-upload-complete/Cargo.toml @@ -13,7 +13,7 @@ prost = "0.10" upload-complete = { path = "../../../upload/ops/complete" } [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/game/ops/create/Cargo.toml b/svc/pkg/game/ops/create/Cargo.toml index 3bd77072fa..e9560bd588 100644 --- a/svc/pkg/game/ops/create/Cargo.toml +++ b/svc/pkg/game/ops/create/Cargo.toml @@ -14,7 +14,7 @@ game-validate = { path = "../validate" } team-dev-get = { path = "../../../team-dev/ops/get" } [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/game/ops/get/Cargo.toml b/svc/pkg/game/ops/get/Cargo.toml index 95c61992f2..9411390013 100644 --- a/svc/pkg/game/ops/get/Cargo.toml +++ b/svc/pkg/game/ops/get/Cargo.toml @@ -14,7 +14,7 @@ upload-file-list = { path = "../../../upload/ops/file-list" } upload-get = { path = "../../../upload/ops/get" } [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/game/ops/list-all/Cargo.toml b/svc/pkg/game/ops/list-all/Cargo.toml index 80bbe29a73..0703121e8f 100644 --- a/svc/pkg/game/ops/list-all/Cargo.toml +++ b/svc/pkg/game/ops/list-all/Cargo.toml @@ -11,7 +11,7 @@ chirp-client = { path = "../../../../../lib/chirp/client" } prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/game/ops/logo-upload-complete/Cargo.toml b/svc/pkg/game/ops/logo-upload-complete/Cargo.toml index 989e3584eb..ce5d10d28f 100644 --- a/svc/pkg/game/ops/logo-upload-complete/Cargo.toml +++ b/svc/pkg/game/ops/logo-upload-complete/Cargo.toml @@ -13,7 +13,7 @@ prost = "0.10" upload-complete = { path = "../../../upload/ops/complete" } [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/game/ops/namespace-create/Cargo.toml b/svc/pkg/game/ops/namespace-create/Cargo.toml index 4c5030f50b..c5a82e6e97 100644 --- a/svc/pkg/game/ops/namespace-create/Cargo.toml +++ b/svc/pkg/game/ops/namespace-create/Cargo.toml @@ -13,7 +13,7 @@ prost = "0.10" game-namespace-validate = { path = "../namespace-validate" } [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/game/ops/namespace-get/Cargo.toml b/svc/pkg/game/ops/namespace-get/Cargo.toml index 978729e4db..0e748c7107 100644 --- a/svc/pkg/game/ops/namespace-get/Cargo.toml +++ b/svc/pkg/game/ops/namespace-get/Cargo.toml @@ -11,7 +11,7 @@ chirp-client = { path = "../../../../../lib/chirp/client" } prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/game/ops/namespace-list/Cargo.toml b/svc/pkg/game/ops/namespace-list/Cargo.toml index 1ca6dc3040..3cdccdd6e9 100644 --- a/svc/pkg/game/ops/namespace-list/Cargo.toml +++ b/svc/pkg/game/ops/namespace-list/Cargo.toml @@ -11,7 +11,7 @@ chirp-client = { path = "../../../../../lib/chirp/client" } prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/game/ops/namespace-resolve-name-id/Cargo.toml b/svc/pkg/game/ops/namespace-resolve-name-id/Cargo.toml index a150226bb4..0ebad0e439 100644 --- a/svc/pkg/game/ops/namespace-resolve-name-id/Cargo.toml +++ b/svc/pkg/game/ops/namespace-resolve-name-id/Cargo.toml @@ -11,7 +11,7 @@ chirp-client = { path = "../../../../../lib/chirp/client" } prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/game/ops/namespace-version-history-list/Cargo.toml b/svc/pkg/game/ops/namespace-version-history-list/Cargo.toml index f5e9a4593f..4f6caa3047 100644 --- a/svc/pkg/game/ops/namespace-version-history-list/Cargo.toml +++ b/svc/pkg/game/ops/namespace-version-history-list/Cargo.toml @@ -11,7 +11,7 @@ chirp-client = { path = "../../../../../lib/chirp/client" } prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/game/ops/namespace-version-set/Cargo.toml b/svc/pkg/game/ops/namespace-version-set/Cargo.toml index 3b57b410af..e08a06ac4d 100644 --- a/svc/pkg/game/ops/namespace-version-set/Cargo.toml +++ b/svc/pkg/game/ops/namespace-version-set/Cargo.toml @@ -16,7 +16,7 @@ region-list = { path = "../../../region/ops/list" } mm-lobby-idle-update = { path = "../../../mm/ops/lobby-idle-update" } [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/game/ops/namespace-version-set/src/lib.rs b/svc/pkg/game/ops/namespace-version-set/src/lib.rs index f4f8976e86..d7d66936e5 100644 --- a/svc/pkg/game/ops/namespace-version-set/src/lib.rs +++ b/svc/pkg/game/ops/namespace-version-set/src/lib.rs @@ -95,7 +95,10 @@ async fn handle( .await; match res { Ok(_) => { - tracing::info!("lobby idle updated successfully"); + tracing::info!( + ?namespace_id, + "lobby idle updated successfully" + ); } Err(err) => { tracing::error!(?err, "failed to update idle lobbies"); diff --git a/svc/pkg/game/ops/recommend/Cargo.toml b/svc/pkg/game/ops/recommend/Cargo.toml index 6cafddf829..ea56c140ed 100644 --- a/svc/pkg/game/ops/recommend/Cargo.toml +++ b/svc/pkg/game/ops/recommend/Cargo.toml @@ -11,7 +11,7 @@ chirp-client = { path = "../../../../../lib/chirp/client" } prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/game/ops/resolve-name-id/Cargo.toml b/svc/pkg/game/ops/resolve-name-id/Cargo.toml index 1295e1eb25..14574a25f7 100644 --- a/svc/pkg/game/ops/resolve-name-id/Cargo.toml +++ b/svc/pkg/game/ops/resolve-name-id/Cargo.toml @@ -11,7 +11,7 @@ chirp-client = { path = "../../../../../lib/chirp/client" } prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/game/ops/resolve-namespace-id/Cargo.toml b/svc/pkg/game/ops/resolve-namespace-id/Cargo.toml index 8eb3d1f302..c6bfe53d79 100644 --- a/svc/pkg/game/ops/resolve-namespace-id/Cargo.toml +++ b/svc/pkg/game/ops/resolve-namespace-id/Cargo.toml @@ -11,7 +11,7 @@ chirp-client = { path = "../../../../../lib/chirp/client" } prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/game/ops/version-create/Cargo.toml b/svc/pkg/game/ops/version-create/Cargo.toml index 27b5ae49d7..dfac123c99 100644 --- a/svc/pkg/game/ops/version-create/Cargo.toml +++ b/svc/pkg/game/ops/version-create/Cargo.toml @@ -14,7 +14,7 @@ game-version-get = { path = "../version-get" } game-version-list = { path = "../version-list" } [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/game/ops/version-get/Cargo.toml b/svc/pkg/game/ops/version-get/Cargo.toml index 3abae2834b..612bab18b0 100644 --- a/svc/pkg/game/ops/version-get/Cargo.toml +++ b/svc/pkg/game/ops/version-get/Cargo.toml @@ -11,7 +11,7 @@ chirp-client = { path = "../../../../../lib/chirp/client" } prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/game/ops/version-list/Cargo.toml b/svc/pkg/game/ops/version-list/Cargo.toml index d2a257d93a..dc3d9c4563 100644 --- a/svc/pkg/game/ops/version-list/Cargo.toml +++ b/svc/pkg/game/ops/version-list/Cargo.toml @@ -11,7 +11,7 @@ chirp-client = { path = "../../../../../lib/chirp/client" } prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/game/ops/version-validate/Cargo.toml b/svc/pkg/game/ops/version-validate/Cargo.toml index b934339ba0..fe99260561 100644 --- a/svc/pkg/game/ops/version-validate/Cargo.toml +++ b/svc/pkg/game/ops/version-validate/Cargo.toml @@ -11,6 +11,7 @@ rivet-operation = { path = "../../../../../lib/operation/core" } prost = "0.10" util-mm = { package = "rivet-util-mm", path = "../../../mm/util" } +external-request-validate = { path = "../../../external/ops/request-validate"} game-version-get = { path = "../version-get" } game-version-list = { path = "../version-list" } module-version-get = { path = "../../../module/ops/version-get" } diff --git a/svc/pkg/game/ops/version-validate/src/lib.rs b/svc/pkg/game/ops/version-validate/src/lib.rs index 001c251b0e..7f1c1cd5f1 100644 --- a/svc/pkg/game/ops/version-validate/src/lib.rs +++ b/svc/pkg/game/ops/version-validate/src/lib.rs @@ -976,6 +976,68 @@ async fn handle( "no-runtime", ]); } + + // Validate find config + if let Some(matchmaker::FindConfig { + verification_config: Some(verification_config), + .. + }) = &lobby_group.find_config + { + let validation_res = op!([ctx] external_request_validate { + config: Some(backend::net::ExternalRequestConfig { + url: verification_config.url.clone(), + headers: verification_config.headers.clone(), + ..Default::default() + }), + }) + .await?; + + // Append errors from external request validation + errors.extend(validation_res.errors.iter().map(|err| { + util::err_path![ + "config", + "matchmaker", + "game-modes", + lobby_group_label, + "find-config", + "verification-config" + ] + .into_iter() + .chain(err.path.clone()) + .collect::>() + })); + } + + // Validate join config + if let Some(matchmaker::JoinConfig { + verification_config: Some(verification_config), + .. + }) = &lobby_group.join_config + { + let validation_res = op!([ctx] external_request_validate { + config: Some(backend::net::ExternalRequestConfig { + url: verification_config.url.clone(), + headers: verification_config.headers.clone(), + ..Default::default() + }), + }) + .await?; + + // Append errors from external request validation + errors.extend(validation_res.errors.iter().map(|err| { + util::err_path![ + "config", + "matchmaker", + "game-modes", + lobby_group_label, + "join-config", + "verification-config" + ] + .into_iter() + .chain(err.path.clone()) + .collect::>() + })); + } } } diff --git a/svc/pkg/game/ops/version-validate/tests/integration.rs b/svc/pkg/game/ops/version-validate/tests/integration.rs index 5ad4243c33..4309e00c76 100644 --- a/svc/pkg/game/ops/version-validate/tests/integration.rs +++ b/svc/pkg/game/ops/version-validate/tests/integration.rs @@ -52,6 +52,8 @@ async fn empty(ctx: TestCtx) { max_players_normal: 33, max_players_direct: 0, max_players_party: 16, + listable: true, + runtime: Some(matchmaker::LobbyRuntime { runtime: Some(matchmaker::lobby_runtime::Runtime::Docker( matchmaker::lobby_runtime::Docker { @@ -127,6 +129,10 @@ async fn empty(ctx: TestCtx) { }, )), }), + + find_config: None, + join_config: None, + create_config: None, }, matchmaker::LobbyGroup { name_id: "name".to_owned(), @@ -138,6 +144,8 @@ async fn empty(ctx: TestCtx) { max_players_normal: 33, max_players_direct: 0, max_players_party: 16, + listable: true, + runtime: Some(matchmaker::LobbyRuntime { runtime: Some(matchmaker::lobby_runtime::Runtime::Docker( matchmaker::lobby_runtime::Docker { @@ -150,6 +158,10 @@ async fn empty(ctx: TestCtx) { }, )), }), + + find_config: None, + join_config: None, + create_config: None, }, ], captcha: Some(backend::captcha::CaptchaConfig { diff --git a/svc/pkg/identity-config/ops/namespace-create/Cargo.toml b/svc/pkg/identity-config/ops/namespace-create/Cargo.toml index c99f4a7d4e..16f36fc6bf 100644 --- a/svc/pkg/identity-config/ops/namespace-create/Cargo.toml +++ b/svc/pkg/identity-config/ops/namespace-create/Cargo.toml @@ -11,7 +11,7 @@ chirp-client = { path = "../../../../../lib/chirp/client" } prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/identity-config/ops/namespace-get/Cargo.toml b/svc/pkg/identity-config/ops/namespace-get/Cargo.toml index 271a92c8b7..9e10d10335 100644 --- a/svc/pkg/identity-config/ops/namespace-get/Cargo.toml +++ b/svc/pkg/identity-config/ops/namespace-get/Cargo.toml @@ -11,7 +11,7 @@ chirp-client = { path = "../../../../../lib/chirp/client" } prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/identity-config/ops/version-get/Cargo.toml b/svc/pkg/identity-config/ops/version-get/Cargo.toml index 27b839bbe6..5806f2419a 100644 --- a/svc/pkg/identity-config/ops/version-get/Cargo.toml +++ b/svc/pkg/identity-config/ops/version-get/Cargo.toml @@ -11,7 +11,7 @@ chirp-client = { path = "../../../../../lib/chirp/client" } prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/identity-config/ops/version-publish/Cargo.toml b/svc/pkg/identity-config/ops/version-publish/Cargo.toml index 3144022677..11d21644b0 100644 --- a/svc/pkg/identity-config/ops/version-publish/Cargo.toml +++ b/svc/pkg/identity-config/ops/version-publish/Cargo.toml @@ -11,7 +11,7 @@ chirp-client = { path = "../../../../../lib/chirp/client" } prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/ip/ops/info/Cargo.toml b/svc/pkg/ip/ops/info/Cargo.toml index 2d46bec7bc..6a4d648e25 100644 --- a/svc/pkg/ip/ops/info/Cargo.toml +++ b/svc/pkg/ip/ops/info/Cargo.toml @@ -15,7 +15,7 @@ serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/job-run/ops/get/Cargo.toml b/svc/pkg/job-run/ops/get/Cargo.toml index dfe7e9e405..8f17d2dc9b 100644 --- a/svc/pkg/job-run/ops/get/Cargo.toml +++ b/svc/pkg/job-run/ops/get/Cargo.toml @@ -14,7 +14,7 @@ nomad-client = "0.0.9" util-job = { package = "rivet-util-job", path = "../../../job/util" } [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/job-run/standalone/alloc-plan-monitor/Cargo.toml b/svc/pkg/job-run/standalone/alloc-plan-monitor/Cargo.toml index abb4b417b4..b664f524e3 100644 --- a/svc/pkg/job-run/standalone/alloc-plan-monitor/Cargo.toml +++ b/svc/pkg/job-run/standalone/alloc-plan-monitor/Cargo.toml @@ -21,7 +21,7 @@ rivet-pools = { path = "../../../../../lib/pools" } rivet-runtime = { path = "../../../../../lib/runtime" } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -tokio = { version = "1.21", features = ["full"] } +tokio = { version = "1.29", features = ["full"] } tracing = "0.1" tracing-subscriber = { version = "0.3", default-features = false, features = ["fmt", "json", "ansi"] } util-job = { package = "rivet-util-job", path = "../../../job/util" } diff --git a/svc/pkg/job-run/standalone/alloc-update-monitor/Cargo.toml b/svc/pkg/job-run/standalone/alloc-update-monitor/Cargo.toml index 770cd4a191..067b4db479 100644 --- a/svc/pkg/job-run/standalone/alloc-update-monitor/Cargo.toml +++ b/svc/pkg/job-run/standalone/alloc-update-monitor/Cargo.toml @@ -21,13 +21,13 @@ rivet-pools = { path = "../../../../../lib/pools" } rivet-runtime = { path = "../../../../../lib/runtime" } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -tokio = { version = "1.21", features = ["full"] } +tokio = { version = "1.29", features = ["full"] } tracing = "0.1" tracing-subscriber = { version = "0.3", default-features = false, features = ["fmt", "json", "ansi"] } util-job = { package = "rivet-util-job", path = "../../../job/util" } [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/job-run/standalone/eval-update-monitor/Cargo.toml b/svc/pkg/job-run/standalone/eval-update-monitor/Cargo.toml index fd067b76cd..8e48c64371 100644 --- a/svc/pkg/job-run/standalone/eval-update-monitor/Cargo.toml +++ b/svc/pkg/job-run/standalone/eval-update-monitor/Cargo.toml @@ -22,13 +22,13 @@ rivet-pools = { path = "../../../../../lib/pools" } rivet-runtime = { path = "../../../../../lib/runtime" } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -tokio = { version = "1.21", features = ["full"] } +tokio = { version = "1.29", features = ["full"] } tracing = "0.1" tracing-subscriber = { version = "0.3", default-features = false, features = ["fmt", "json", "ansi"] } util-job = { package = "rivet-util-job", path = "../../../job/util" } [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false diff --git a/svc/pkg/job-run/worker/Cargo.toml b/svc/pkg/job-run/worker/Cargo.toml index 2446d476ea..8ddf0edd90 100644 --- a/svc/pkg/job-run/worker/Cargo.toml +++ b/svc/pkg/job-run/worker/Cargo.toml @@ -27,7 +27,7 @@ region-get = { path = "../../region/ops/get" } token-create = { path = "../../token/ops/create" } [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/job-run/worker/src/workers/cleanup.rs b/svc/pkg/job-run/worker/src/workers/cleanup.rs index 1b6344392b..419dde042d 100644 --- a/svc/pkg/job-run/worker/src/workers/cleanup.rs +++ b/svc/pkg/job-run/worker/src/workers/cleanup.rs @@ -16,7 +16,7 @@ struct RunMetaNomadRow { } #[worker(name = "job-run-cleanup")] -async fn worker(ctx: OperationContext) -> GlobalResult<()> { +async fn worker(ctx: &OperationContext) -> GlobalResult<()> { // NOTE: Idempotent let crdb = ctx.crdb("db-job-state").await?; @@ -73,7 +73,7 @@ async fn update_db( " )) .bind(run_id) - .fetch_optional(&mut *tx) + .fetch_optional(&mut **tx) .await?; tracing::info!(?run_row, "run row"); @@ -90,7 +90,7 @@ async fn update_db( " )) .bind(run_id) - .fetch_optional(&mut *tx) + .fetch_optional(&mut **tx) .await?; tracing::info!(?run_meta_nomad_row, "run meta row"); @@ -116,7 +116,7 @@ async fn update_db( sqlx::query("UPDATE runs SET cleanup_ts = $2 WHERE run_id = $1") .bind(run_id) .bind(now) - .execute(&mut *tx) + .execute(&mut **tx) .await?; } diff --git a/svc/pkg/job-run/worker/src/workers/create/mod.rs b/svc/pkg/job-run/worker/src/workers/create/mod.rs index 3ac69cc066..0a3da93060 100644 --- a/svc/pkg/job-run/worker/src/workers/create/mod.rs +++ b/svc/pkg/job-run/worker/src/workers/create/mod.rs @@ -33,7 +33,7 @@ async fn fail( } #[worker(name = "job-run-create")] -async fn worker(ctx: OperationContext) -> GlobalResult<()> { +async fn worker(ctx: &OperationContext) -> GlobalResult<()> { let crdb = ctx.crdb("db-job-state").await?; let run_id = internal_unwrap!(ctx.run_id).as_uuid(); @@ -238,12 +238,12 @@ async fn write_to_db_before_run( .bind(region_id) .bind(ts) .bind(token_session_id) - .execute(&mut *tx) + .execute(&mut **tx) .await?; sqlx::query(indoc!("INSERT INTO run_meta_nomad (run_id) VALUES ($1)")) .bind(run_id) - .execute(&mut *tx) + .execute(&mut **tx) .await?; // Validate that the proxied ports point to existing ports @@ -289,7 +289,7 @@ async fn write_to_db_before_run( .bind(ingress_hostnames_sorted.join(",")) .bind(proxied_port.proxy_protocol) .bind(proxied_port.ssl_domain_mode) - .execute(&mut *tx) + .execute(&mut **tx) .await?; } diff --git a/svc/pkg/job-run/worker/src/workers/nomad_monitor_alloc_plan.rs b/svc/pkg/job-run/worker/src/workers/nomad_monitor_alloc_plan.rs index 461c4ae902..771df290b0 100644 --- a/svc/pkg/job-run/worker/src/workers/nomad_monitor_alloc_plan.rs +++ b/svc/pkg/job-run/worker/src/workers/nomad_monitor_alloc_plan.rs @@ -27,7 +27,7 @@ struct ProxiedPort { #[worker(name = "job-run-nomad-monitor-alloc-plan")] async fn worker( - ctx: OperationContext, + ctx: &OperationContext, ) -> GlobalResult<()> { let crdb = ctx.crdb("db-job-state").await?; let mut redis_job = ctx.redis_job().await?; @@ -199,7 +199,7 @@ async fn update_db( " )) .bind(&job_id) - .fetch_optional(&mut *tx) + .fetch_optional(&mut **tx) .await?; // Check if run found @@ -225,7 +225,7 @@ async fn update_db( .bind(&alloc_id) .bind(now) .bind(&nomad_node_id) - .execute(&mut *tx) + .execute(&mut **tx) .await?; // Save the ports to the db @@ -240,7 +240,7 @@ async fn update_db( .bind(run_id) .bind(&network.mode) .bind(&network.ip) - .execute(&mut *tx) + .execute(&mut **tx) .await?; } @@ -258,7 +258,7 @@ async fn update_db( .bind(port.source as i64) .bind(port.target as i64) .bind(&port.ip) - .execute(&mut *tx) + .execute(&mut **tx) .await?; } } @@ -272,7 +272,7 @@ async fn update_db( " )) .bind(run_id) - .fetch_all(&mut *tx) + .fetch_all(&mut **tx) .await?; tracing::info!(?proxied_ports, "fetched proxied ports"); diff --git a/svc/pkg/job-run/worker/src/workers/nomad_monitor_alloc_update.rs b/svc/pkg/job-run/worker/src/workers/nomad_monitor_alloc_update.rs index 52e628f102..670b070b03 100644 --- a/svc/pkg/job-run/worker/src/workers/nomad_monitor_alloc_update.rs +++ b/svc/pkg/job-run/worker/src/workers/nomad_monitor_alloc_update.rs @@ -17,7 +17,7 @@ enum TaskState { #[worker(name = "job-run-nomad-monitor-alloc-update")] async fn worker( - ctx: OperationContext, + ctx: &OperationContext, ) -> GlobalResult<()> { let crdb = ctx.crdb("db-job-state").await?; diff --git a/svc/pkg/job-run/worker/src/workers/nomad_monitor_eval_update.rs b/svc/pkg/job-run/worker/src/workers/nomad_monitor_eval_update.rs index 48fccbd2f1..22c7141b79 100644 --- a/svc/pkg/job-run/worker/src/workers/nomad_monitor_eval_update.rs +++ b/svc/pkg/job-run/worker/src/workers/nomad_monitor_eval_update.rs @@ -28,7 +28,7 @@ struct RunRow { #[worker(name = "job-run-nomad-monitor-eval-update")] async fn worker( - ctx: OperationContext, + ctx: &OperationContext, ) -> GlobalResult<()> { let crdb = ctx.crdb("db-job-state").await?; diff --git a/svc/pkg/job-run/worker/src/workers/stop.rs b/svc/pkg/job-run/worker/src/workers/stop.rs index 764454c076..433466ee89 100644 --- a/svc/pkg/job-run/worker/src/workers/stop.rs +++ b/svc/pkg/job-run/worker/src/workers/stop.rs @@ -19,7 +19,7 @@ struct RunMetaNomadRow { } #[worker(name = "job-run-stop")] -async fn worker(ctx: OperationContext) -> GlobalResult<()> { +async fn worker(ctx: &OperationContext) -> GlobalResult<()> { // NOTE: Idempotent let crdb = ctx.crdb("db-job-state").await?; @@ -99,7 +99,7 @@ async fn update_db( " )) .bind(run_id) - .fetch_optional(&mut *tx) + .fetch_optional(&mut **tx) .await?; tracing::info!(?run_row, "fetched run"); @@ -116,7 +116,7 @@ async fn update_db( " )) .bind(run_id) - .fetch_optional(&mut *tx) + .fetch_optional(&mut **tx) .await?; tracing::info!(?run_meta_nomad_row, "fetched run meta nomad"); @@ -143,7 +143,7 @@ async fn update_db( sqlx::query("UPDATE runs SET stop_ts = $2 WHERE run_id = $1") .bind(run_id) .bind(now) - .execute(&mut *tx) + .execute(&mut **tx) .await?; } diff --git a/svc/pkg/job/standalone/gc/Cargo.toml b/svc/pkg/job/standalone/gc/Cargo.toml index 08c104429d..1b258c00b9 100644 --- a/svc/pkg/job/standalone/gc/Cargo.toml +++ b/svc/pkg/job/standalone/gc/Cargo.toml @@ -21,20 +21,19 @@ rivet-operation = { path = "../../../../../lib/operation/core" } rivet-pools = { path = "../../../../../lib/pools" } rivet-runtime = { path = "../../../../../lib/runtime" } serde_json = "1.0" -tokio = { version = "1.21", features = ["full"] } +tokio = { version = "1.29", features = ["full"] } tracing = "0.1" tracing-subscriber = { version = "0.3", default-features = false, features = ["fmt", "json", "ansi"] } uuid = { version = "1", features = ["serde"] } [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false features = [ - "runtime-tokio-native-tls", + "runtime-tokio", "postgres", "uuid", "json", - "tls", "macros", ] diff --git a/svc/pkg/kv-config/ops/namespace-create/Cargo.toml b/svc/pkg/kv-config/ops/namespace-create/Cargo.toml index 75442b79c5..be592fb6bb 100644 --- a/svc/pkg/kv-config/ops/namespace-create/Cargo.toml +++ b/svc/pkg/kv-config/ops/namespace-create/Cargo.toml @@ -11,7 +11,7 @@ chirp-client = { path = "../../../../../lib/chirp/client" } prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/kv-config/ops/namespace-get/Cargo.toml b/svc/pkg/kv-config/ops/namespace-get/Cargo.toml index f7b7d6a4fa..7e1d404d9a 100644 --- a/svc/pkg/kv-config/ops/namespace-get/Cargo.toml +++ b/svc/pkg/kv-config/ops/namespace-get/Cargo.toml @@ -11,7 +11,7 @@ chirp-client = { path = "../../../../../lib/chirp/client" } prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/kv-config/ops/version-get/Cargo.toml b/svc/pkg/kv-config/ops/version-get/Cargo.toml index a090067124..7a222e0cf6 100644 --- a/svc/pkg/kv-config/ops/version-get/Cargo.toml +++ b/svc/pkg/kv-config/ops/version-get/Cargo.toml @@ -11,7 +11,7 @@ chirp-client = { path = "../../../../../lib/chirp/client" } prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/kv-config/ops/version-publish/Cargo.toml b/svc/pkg/kv-config/ops/version-publish/Cargo.toml index bb410d8fda..ea9a969853 100644 --- a/svc/pkg/kv-config/ops/version-publish/Cargo.toml +++ b/svc/pkg/kv-config/ops/version-publish/Cargo.toml @@ -11,7 +11,7 @@ chirp-client = { path = "../../../../../lib/chirp/client" } prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/kv/ops/get/Cargo.toml b/svc/pkg/kv/ops/get/Cargo.toml index d0c0712946..a82289ad81 100644 --- a/svc/pkg/kv/ops/get/Cargo.toml +++ b/svc/pkg/kv/ops/get/Cargo.toml @@ -11,7 +11,7 @@ chirp-client = { path = "../../../../../lib/chirp/client" } prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/kv/worker/src/workers/write.rs b/svc/pkg/kv/worker/src/workers/write.rs index f51d448609..754110bbdd 100644 --- a/svc/pkg/kv/worker/src/workers/write.rs +++ b/svc/pkg/kv/worker/src/workers/write.rs @@ -2,7 +2,7 @@ use chirp_worker::prelude::*; use proto::backend::pkg::*; #[worker(name = "kv-write")] -async fn worker(ctx: OperationContext) -> GlobalResult<()> { +async fn worker(ctx: &OperationContext) -> GlobalResult<()> { let crdb = ctx.crdb("db-kv").await?; let namespace_id = internal_unwrap!(ctx.namespace_id).as_uuid(); diff --git a/svc/pkg/misc/db/redis-search/Service.toml b/svc/pkg/misc/db/redis-search/Service.toml deleted file mode 100644 index 38f72eb893..0000000000 --- a/svc/pkg/misc/db/redis-search/Service.toml +++ /dev/null @@ -1,10 +0,0 @@ -[service] -name = "redis-search" - -[runtime] -kind = "redis" -index = 7 -persistent = true - -[cache] - diff --git a/svc/pkg/misc/standalone/playground/Cargo.toml b/svc/pkg/misc/standalone/playground/Cargo.toml index d88cb3051e..9e66ff40f4 100644 --- a/svc/pkg/misc/standalone/playground/Cargo.toml +++ b/svc/pkg/misc/standalone/playground/Cargo.toml @@ -24,7 +24,7 @@ rivet-pools = { path = "../../../../../lib/pools" } s3-util = { path = "../../../../../lib/s3-util" } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -tokio = { version = "1.21", features = ["full"] } +tokio = { version = "1.29", features = ["full"] } tracing = "0.1" tracing-subscriber = { version = "0.3", default-features = false, features = ["fmt", "json", "ansi"] } util-mm = { package = "rivet-util-mm", path = "../../../mm/util" } @@ -42,14 +42,13 @@ region-list = { path = "../../../region/ops/list" } upload-complete = { path = "../../../upload/ops/complete" } [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false features = [ - "runtime-tokio-native-tls", + "runtime-tokio", "postgres", "uuid", "json", - "tls", ] [dev-dependencies] diff --git a/svc/pkg/mm-config/db/mm-config/migrations/20230711222029_add_find_join_config.down.sql b/svc/pkg/mm-config/db/mm-config/migrations/20230711222029_add_find_join_config.down.sql new file mode 100644 index 0000000000..e69de29bb2 diff --git a/svc/pkg/mm-config/db/mm-config/migrations/20230711222029_add_find_join_config.up.sql b/svc/pkg/mm-config/db/mm-config/migrations/20230711222029_add_find_join_config.up.sql new file mode 100644 index 0000000000..53da5e9ca9 --- /dev/null +++ b/svc/pkg/mm-config/db/mm-config/migrations/20230711222029_add_find_join_config.up.sql @@ -0,0 +1,4 @@ +ALTER TABLE lobby_groups + ADD COLUMN find_config BYTES, + ADD COLUMN join_config BYTES, + ADD COLUMN create_config BYTES; diff --git a/svc/pkg/mm-config/db/mm-config/migrations/20230715175430_add_listable.down.sql b/svc/pkg/mm-config/db/mm-config/migrations/20230715175430_add_listable.down.sql new file mode 100644 index 0000000000..e69de29bb2 diff --git a/svc/pkg/mm-config/db/mm-config/migrations/20230715175430_add_listable.up.sql b/svc/pkg/mm-config/db/mm-config/migrations/20230715175430_add_listable.up.sql new file mode 100644 index 0000000000..493252de25 --- /dev/null +++ b/svc/pkg/mm-config/db/mm-config/migrations/20230715175430_add_listable.up.sql @@ -0,0 +1,2 @@ +ALTER TABLE lobby_groups + ADD COLUMN listable BOOLEAN NOT NULL DEFAULT true; diff --git a/svc/pkg/mm-config/ops/lobby-group-get/Cargo.toml b/svc/pkg/mm-config/ops/lobby-group-get/Cargo.toml index 6873d039d5..fb30db9814 100644 --- a/svc/pkg/mm-config/ops/lobby-group-get/Cargo.toml +++ b/svc/pkg/mm-config/ops/lobby-group-get/Cargo.toml @@ -11,7 +11,7 @@ chirp-client = { path = "../../../../../lib/chirp/client" } prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/mm-config/ops/lobby-group-resolve-name-id/Cargo.toml b/svc/pkg/mm-config/ops/lobby-group-resolve-name-id/Cargo.toml index 7a0a856665..0deb4d059c 100644 --- a/svc/pkg/mm-config/ops/lobby-group-resolve-name-id/Cargo.toml +++ b/svc/pkg/mm-config/ops/lobby-group-resolve-name-id/Cargo.toml @@ -12,7 +12,7 @@ prost = "0.10" util-mm = { package = "rivet-util-mm", path = "../../../mm/util" } [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/mm-config/ops/lobby-group-resolve-name-id/tests/integration.rs b/svc/pkg/mm-config/ops/lobby-group-resolve-name-id/tests/integration.rs index 5ef2af9f20..5a497faf54 100644 --- a/svc/pkg/mm-config/ops/lobby-group-resolve-name-id/tests/integration.rs +++ b/svc/pkg/mm-config/ops/lobby-group-resolve-name-id/tests/integration.rs @@ -35,6 +35,7 @@ async fn empty(ctx: TestCtx) { max_players_normal: 1, max_players_direct: 1, max_players_party: 1, + listable: true, runtime: Some(backend::matchmaker::lobby_runtime::Docker { build_id: build_res.build_id, @@ -43,6 +44,10 @@ async fn empty(ctx: TestCtx) { network_mode: backend::matchmaker::lobby_runtime::NetworkMode::Bridge as i32, ports: Vec::new(), }.into()), + + find_config: None, + join_config: None, + create_config: None, }) .collect(), }), diff --git a/svc/pkg/mm-config/ops/lobby-group-resolve-version/Cargo.toml b/svc/pkg/mm-config/ops/lobby-group-resolve-version/Cargo.toml index f3cbc54bc0..193bba2ab0 100644 --- a/svc/pkg/mm-config/ops/lobby-group-resolve-version/Cargo.toml +++ b/svc/pkg/mm-config/ops/lobby-group-resolve-version/Cargo.toml @@ -11,7 +11,7 @@ chirp-client = { path = "../../../../../lib/chirp/client" } prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/mm-config/ops/namespace-config-set/Cargo.toml b/svc/pkg/mm-config/ops/namespace-config-set/Cargo.toml index ac89aa1ce9..99f57bc749 100644 --- a/svc/pkg/mm-config/ops/namespace-config-set/Cargo.toml +++ b/svc/pkg/mm-config/ops/namespace-config-set/Cargo.toml @@ -13,7 +13,7 @@ prost = "0.10" mm-config-namespace-config-validate = { path = "../namespace-config-validate" } [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/mm-config/ops/namespace-create/Cargo.toml b/svc/pkg/mm-config/ops/namespace-create/Cargo.toml index e24738c96b..8368c6dd6c 100644 --- a/svc/pkg/mm-config/ops/namespace-create/Cargo.toml +++ b/svc/pkg/mm-config/ops/namespace-create/Cargo.toml @@ -11,7 +11,7 @@ chirp-client = { path = "../../../../../lib/chirp/client" } prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/mm-config/ops/namespace-get/Cargo.toml b/svc/pkg/mm-config/ops/namespace-get/Cargo.toml index 9cda257e09..2b85007637 100644 --- a/svc/pkg/mm-config/ops/namespace-get/Cargo.toml +++ b/svc/pkg/mm-config/ops/namespace-get/Cargo.toml @@ -11,7 +11,7 @@ chirp-client = { path = "../../../../../lib/chirp/client" } prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/mm-config/ops/version-get/Cargo.toml b/svc/pkg/mm-config/ops/version-get/Cargo.toml index 936aa68e83..63597698f0 100644 --- a/svc/pkg/mm-config/ops/version-get/Cargo.toml +++ b/svc/pkg/mm-config/ops/version-get/Cargo.toml @@ -12,7 +12,7 @@ prost = "0.10" util-mm = { package = "rivet-util-mm", path = "../../../mm/util" } [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/mm-config/ops/version-get/src/lib.rs b/svc/pkg/mm-config/ops/version-get/src/lib.rs index 5a518b95ad..c49d63ef35 100644 --- a/svc/pkg/mm-config/ops/version-get/src/lib.rs +++ b/svc/pkg/mm-config/ops/version-get/src/lib.rs @@ -17,9 +17,13 @@ struct LobbyGroup { max_players_normal: i64, max_players_direct: i64, max_players_party: i64, + listable: bool, runtime: Vec, runtime_meta: Vec, + find_config: Option>, + join_config: Option>, + create_config: Option>, } #[derive(Clone, sqlx::FromRow)] @@ -100,8 +104,9 @@ async fn fetch_versions( SELECT lobby_group_id, version_id, name_id, - max_players_normal, max_players_direct, max_players_party, - runtime, runtime_meta + max_players_normal, max_players_direct, max_players_party, listable, + runtime, runtime_meta, + find_config, join_config, create_config FROM lobby_groups WHERE version_id = ANY($1) " @@ -117,19 +122,19 @@ async fn fetch_versions( let (lobby_group_regions, lobby_group_idle_lobbies) = tokio::try_join!( sqlx::query_as::<_, LobbyGroupRegion>(indoc!( " - SELECT lobby_group_id, region_id, tier_name_id - FROM lobby_group_regions - WHERE lobby_group_id = ANY($1) - " + SELECT lobby_group_id, region_id, tier_name_id + FROM lobby_group_regions + WHERE lobby_group_id = ANY($1) + " )) .bind(&all_lobby_group_ids) .fetch_all(sql_pool), sqlx::query_as::<_, LobbyGroupIdleLobbies>(indoc!( " - SELECT lobby_group_id, region_id, min_idle_lobbies, max_idle_lobbies - FROM lobby_group_idle_lobbies - WHERE lobby_group_id = ANY($1) - " + SELECT lobby_group_id, region_id, min_idle_lobbies, max_idle_lobbies + FROM lobby_group_idle_lobbies + WHERE lobby_group_id = ANY($1) + " )) .bind(&all_lobby_group_ids) .fetch_all(sql_pool), @@ -167,6 +172,23 @@ async fn fetch_versions( let runtime = backend::matchmaker::LobbyRuntime::decode(lg.runtime.as_ref())?; + let find_config = lg + .find_config + .as_ref() + .map(|fc| backend::matchmaker::FindConfig::decode(fc.as_ref())) + .transpose()?; + let join_config = lg + .join_config + .as_ref() + .map(|jc| backend::matchmaker::JoinConfig::decode(jc.as_ref())) + .transpose()?; + let create_config = lg + .create_config + .as_ref() + .map(|jc| { + backend::matchmaker::CreateConfig::decode(jc.as_ref()) + }) + .transpose()?; Ok(backend::matchmaker::LobbyGroup { name_id: lg.name_id.clone(), @@ -197,8 +219,13 @@ async fn fetch_versions( max_players_normal: lg.max_players_normal as u32, max_players_direct: lg.max_players_direct as u32, max_players_party: lg.max_players_party as u32, + listable: lg.listable, runtime: Some(runtime), + + find_config, + join_config, + create_config, }) }) .collect::>>()?, diff --git a/svc/pkg/mm-config/ops/version-get/tests/integration.rs b/svc/pkg/mm-config/ops/version-get/tests/integration.rs index 2934cc0b12..69cbf32d85 100644 --- a/svc/pkg/mm-config/ops/version-get/tests/integration.rs +++ b/svc/pkg/mm-config/ops/version-get/tests/integration.rs @@ -40,6 +40,7 @@ impl TestVersion { max_players_normal: 8, max_players_direct: 10, max_players_party: 12, + listable: true, runtime: Some( backend::matchmaker::lobby_runtime::Docker { @@ -63,6 +64,10 @@ impl TestVersion { } .into(), ), + + find_config: None, + join_config: None, + create_config: None, }], captcha: None, }; diff --git a/svc/pkg/mm-config/ops/version-prepare/src/lib.rs b/svc/pkg/mm-config/ops/version-prepare/src/lib.rs index 9f102d34cc..6f6e766d78 100644 --- a/svc/pkg/mm-config/ops/version-prepare/src/lib.rs +++ b/svc/pkg/mm-config/ops/version-prepare/src/lib.rs @@ -124,6 +124,8 @@ async fn validate_build( let build_game_id = internal_unwrap!(build.game_id).as_uuid(); internal_assert_eq!(game_id, build_game_id); + tracing::info!(?build); + // Validate build has completed uploading let upload_res = op!([ctx] upload_get { upload_ids: vec![build_upload_id.into()], diff --git a/svc/pkg/mm-config/ops/version-prepare/tests/integration.rs b/svc/pkg/mm-config/ops/version-prepare/tests/integration.rs index 11da12a09a..e944879b8c 100644 --- a/svc/pkg/mm-config/ops/version-prepare/tests/integration.rs +++ b/svc/pkg/mm-config/ops/version-prepare/tests/integration.rs @@ -36,6 +36,7 @@ async fn empty(ctx: TestCtx) { max_players_normal: 8, max_players_direct: 10, max_players_party: 12, + listable: true, runtime: Some(backend::matchmaker::lobby_runtime::Docker { build_id: build_res.build_id, @@ -57,6 +58,10 @@ async fn empty(ctx: TestCtx) { }, ], }.into()), + + find_config: None, + join_config: None, + create_config: None, }, backend::matchmaker::LobbyGroup { name_id: "test-host".into(), @@ -71,6 +76,7 @@ async fn empty(ctx: TestCtx) { max_players_normal: 8, max_players_direct: 10, max_players_party: 12, + listable: true, runtime: Some(backend::matchmaker::lobby_runtime::Docker { build_id: build_res.build_id, @@ -133,6 +139,10 @@ async fn empty(ctx: TestCtx) { }, ], }.into()), + + find_config: None, + join_config: None, + create_config: None, }, ], captcha: None, diff --git a/svc/pkg/mm-config/ops/version-publish/Cargo.toml b/svc/pkg/mm-config/ops/version-publish/Cargo.toml index 1e769f9c9b..c67b20794b 100644 --- a/svc/pkg/mm-config/ops/version-publish/Cargo.toml +++ b/svc/pkg/mm-config/ops/version-publish/Cargo.toml @@ -12,14 +12,13 @@ prost = "0.10" util-mm = { package = "rivet-util-mm", path = "../../../mm/util" } [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false features = [ - "runtime-tokio-native-tls", + "runtime-tokio", "postgres", "uuid", "json", - "tls", "bit-vec", ] diff --git a/svc/pkg/mm-config/ops/version-publish/src/lib.rs b/svc/pkg/mm-config/ops/version-publish/src/lib.rs index 4e22f70988..edd8425ff5 100644 --- a/svc/pkg/mm-config/ops/version-publish/src/lib.rs +++ b/svc/pkg/mm-config/ops/version-publish/src/lib.rs @@ -42,10 +42,9 @@ async fn handle( .bind(version_id) .bind(captcha_buf) .bind(util_mm::version_migrations::all()) - .execute(&mut tx) + .execute(&mut *tx) .await?; - // TODO: Parallelize all futures in this for loop // Save lobby groups internal_assert_eq!(config.lobby_groups.len(), config_ctx.lobby_groups.len()); for (lobby_group, lobby_group_ctx) in config @@ -61,8 +60,7 @@ async fn handle( let (runtime, runtime_meta) = publish_runtime( internal_unwrap!(runtime.runtime), internal_unwrap!(runtime_ctx.runtime), - ) - .await?; + )?; // Encode runtime data let (runtime_buf, runtime_meta_buf) = { @@ -75,6 +73,28 @@ async fn handle( (runtime_buf, runtime_meta_buf) }; + // Encode config data + let find_config_buf = lobby_group + .find_config + .as_ref() + .map(|config| { + let mut buf = Vec::with_capacity(config.encoded_len()); + config.encode(&mut buf)?; + + GlobalResult::Ok(buf) + }) + .transpose()?; + let join_config_buf = lobby_group + .join_config + .as_ref() + .map(|config| { + let mut buf = Vec::with_capacity(config.encoded_len()); + config.encode(&mut buf)?; + + GlobalResult::Ok(buf) + }) + .transpose()?; + sqlx::query(indoc!( " INSERT INTO lobby_groups ( @@ -86,11 +106,14 @@ async fn handle( max_players_normal, max_players_direct, max_players_party, + listable, runtime, - runtime_meta + runtime_meta, + find_config, + join_config ) - VALUES ($1, $2, $3, $4, $5, $6, $7, $8) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11) " )) .bind(lobby_group_id) @@ -99,31 +122,45 @@ async fn handle( .bind(lobby_group.max_players_normal as i64) .bind(lobby_group.max_players_direct as i64) .bind(lobby_group.max_players_party as i64) + .bind(lobby_group.listable) .bind(&runtime_buf) .bind(&runtime_meta_buf) - .execute(&mut tx) + .bind(&find_config_buf) + .bind(&join_config_buf) + .execute(&mut *tx) .await?; for region in &lobby_group.regions { let region_id = internal_unwrap!(region.region_id).as_uuid(); - sqlx::query( - "INSERT INTO lobby_group_regions (lobby_group_id, region_id, tier_name_id) VALUES ($1, $2, $3)", - ) + sqlx::query(indoc!( + " + INSERT INTO lobby_group_regions ( + lobby_group_id, region_id, tier_name_id + ) + VALUES ($1, $2, $3) + " + )) .bind(lobby_group_id) .bind(region_id) .bind(®ion.tier_name_id) - .execute(&mut tx) + .execute(&mut *tx) .await?; if let Some(idle_lobbies) = ®ion.idle_lobbies { - sqlx::query( - "INSERT INTO lobby_group_idle_lobbies (lobby_group_id, region_id, min_idle_lobbies, max_idle_lobbies) VALUES ($1, $2, $3, $4)", - ) - .bind(lobby_group_id) - .bind(region_id) - .bind(idle_lobbies.min_idle_lobbies as i64).bind(idle_lobbies.max_idle_lobbies as i64) - .execute(&mut tx) - .await?; + sqlx::query(indoc!( + " + INSERT INTO lobby_group_idle_lobbies ( + lobby_group_id, region_id, min_idle_lobbies, max_idle_lobbies + ) + VALUES ($1, $2, $3, $4) + " + )) + .bind(lobby_group_id) + .bind(region_id) + .bind(idle_lobbies.min_idle_lobbies as i64) + .bind(idle_lobbies.max_idle_lobbies as i64) + .execute(&mut *tx) + .await?; } } } @@ -142,7 +179,7 @@ async fn handle( /// /// For example: a docker image with an input of `nginx` would have the tag resolved against the /// registry to `nginx:1.21.1` in order to pin the version. -async fn publish_runtime( +fn publish_runtime( runtime: &backend::matchmaker::lobby_runtime::Runtime, runtime_ctx: &backend::matchmaker::lobby_runtime_ctx::Runtime, ) -> GlobalResult<( diff --git a/svc/pkg/mm-config/ops/version-publish/tests/integration.rs b/svc/pkg/mm-config/ops/version-publish/tests/integration.rs index 0b47ca6b84..c9afa09d85 100644 --- a/svc/pkg/mm-config/ops/version-publish/tests/integration.rs +++ b/svc/pkg/mm-config/ops/version-publish/tests/integration.rs @@ -34,6 +34,7 @@ async fn empty(ctx: TestCtx) { max_players_normal: 8, max_players_direct: 8, max_players_party: 8, + listable: true, runtime: Some(backend::matchmaker::LobbyRuntime { runtime: Some(backend::matchmaker::lobby_runtime::Runtime::Docker( @@ -59,6 +60,10 @@ async fn empty(ctx: TestCtx) { } )), }), + + find_config: None, + join_config: None, + create_config: None, }, ], captcha: None, @@ -85,6 +90,7 @@ async fn empty(ctx: TestCtx) { max_players_normal: 8, max_players_direct: 10, max_players_party: 12, + listable: true, runtime: Some( backend::matchmaker::lobby_runtime::Docker { @@ -109,6 +115,10 @@ async fn empty(ctx: TestCtx) { } .into() ), + + find_config: None, + join_config: None, + create_config: None, }, ], captcha: None, diff --git a/svc/pkg/mm/db/state/migrations/20230714001053_add_creator_user_id.down.sql b/svc/pkg/mm/db/state/migrations/20230714001053_add_creator_user_id.down.sql new file mode 100644 index 0000000000..e69de29bb2 diff --git a/svc/pkg/mm/db/state/migrations/20230714001053_add_creator_user_id.up.sql b/svc/pkg/mm/db/state/migrations/20230714001053_add_creator_user_id.up.sql new file mode 100644 index 0000000000..f48255d291 --- /dev/null +++ b/svc/pkg/mm/db/state/migrations/20230714001053_add_creator_user_id.up.sql @@ -0,0 +1,4 @@ +ALTER TABLE lobbies + ADD COLUMN creator_user_id UUID, + ADD COLUMN is_custom BOOLEAN NOT NULL DEFAULT false, + ADD COLUMN publicity INT NOT NULL DEFAULT 0; diff --git a/svc/pkg/mm/ops/lobby-get/Cargo.toml b/svc/pkg/mm/ops/lobby-get/Cargo.toml index dc98e3031a..79977d367d 100644 --- a/svc/pkg/mm/ops/lobby-get/Cargo.toml +++ b/svc/pkg/mm/ops/lobby-get/Cargo.toml @@ -12,7 +12,7 @@ chrono = "0.4" prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/mm/ops/lobby-get/src/lib.rs b/svc/pkg/mm/ops/lobby-get/src/lib.rs index b9d7e19a44..5eac539d94 100644 --- a/svc/pkg/mm/ops/lobby-get/src/lib.rs +++ b/svc/pkg/mm/ops/lobby-get/src/lib.rs @@ -14,6 +14,9 @@ struct LobbyRow { is_closed: bool, namespace_id: Uuid, create_ray_id: Option, + creator_user_id: Option, + is_custom: bool, + publicity: i64, max_players_normal: i64, max_players_direct: i64, @@ -34,6 +37,9 @@ impl From for backend::matchmaker::Lobby { is_closed: value.is_closed, namespace_id: Some(value.namespace_id.into()), create_ray_id: value.create_ray_id.map(Into::into), + creator_user_id: value.creator_user_id.map(Into::into), + is_custom: value.is_custom, + publicity: value.publicity as i32, max_players_normal: value.max_players_normal as u32, max_players_direct: value.max_players_direct as u32, @@ -68,6 +74,9 @@ async fn handle( is_closed, namespace_id, create_ray_id, + creator_user_id, + is_custom, + publicity, max_players_normal, max_players_direct, @@ -81,6 +90,12 @@ async fn handle( .await? .into_iter() .filter(|x| x.stop_ts.is_none() || ctx.include_stopped) + .filter(|x| { + backend::matchmaker::lobby::Publicity::from_i32(x.publicity as i32) + .map(|publicity| matches!(publicity, backend::matchmaker::lobby::Publicity::Public)) + .unwrap_or_default() + || ctx.include_private + }) .map(Into::::into) .collect(); diff --git a/svc/pkg/mm/ops/lobby-get/tests/integration.rs b/svc/pkg/mm/ops/lobby-get/tests/integration.rs index a8ebf0868d..3e2f90bfb1 100644 --- a/svc/pkg/mm/ops/lobby-get/tests/integration.rs +++ b/svc/pkg/mm/ops/lobby-get/tests/integration.rs @@ -25,6 +25,7 @@ async fn fetch_batch(ctx: TestCtx) { op!([ctx] mm_lobby_get { lobby_ids: lobby_ids, include_stopped: true, + include_private: true, }) .await .unwrap(); diff --git a/svc/pkg/mm/ops/lobby-history/Cargo.toml b/svc/pkg/mm/ops/lobby-history/Cargo.toml index 1d1a1e82b2..eaaad61e40 100644 --- a/svc/pkg/mm/ops/lobby-history/Cargo.toml +++ b/svc/pkg/mm/ops/lobby-history/Cargo.toml @@ -12,7 +12,7 @@ chrono = "0.4" prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/mm/ops/lobby-idle-update/Cargo.toml b/svc/pkg/mm/ops/lobby-idle-update/Cargo.toml index 39bafc58ad..d661f9702e 100644 --- a/svc/pkg/mm/ops/lobby-idle-update/Cargo.toml +++ b/svc/pkg/mm/ops/lobby-idle-update/Cargo.toml @@ -17,7 +17,7 @@ game-namespace-get = { path = "../../../game/ops/namespace-get" } mm-config-version-get = { path = "../../../mm-config/ops/version-get" } [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/mm/ops/lobby-idle-update/src/lib.rs b/svc/pkg/mm/ops/lobby-idle-update/src/lib.rs index 6b196418ec..7c1a90908e 100644 --- a/svc/pkg/mm/ops/lobby-idle-update/src/lib.rs +++ b/svc/pkg/mm/ops/lobby-idle-update/src/lib.rs @@ -74,6 +74,11 @@ async fn handle( region_id: Some(region_id.into()), create_ray_id: Some(ctx.ray_id().into()), preemptively_created: false, + + creator_user_id: None, + is_custom: false, + publicity: None, + lobby_config_json: None, })); } futures_util::future::try_join_all(create_futs).await?; diff --git a/svc/pkg/mm/ops/lobby-idle-update/tests/integration.rs b/svc/pkg/mm/ops/lobby-idle-update/tests/integration.rs index e4b7712e3f..67546a229a 100644 --- a/svc/pkg/mm/ops/lobby-idle-update/tests/integration.rs +++ b/svc/pkg/mm/ops/lobby-idle-update/tests/integration.rs @@ -76,6 +76,7 @@ impl Ctx { max_players_normal: 1, max_players_direct: 1, max_players_party: 1, + listable: true, runtime: Some(backend::matchmaker::lobby_runtime::Docker { build_id: build_res.build_id, @@ -84,6 +85,10 @@ impl Ctx { network_mode: backend::matchmaker::lobby_runtime::NetworkMode::Bridge as i32, ports: Vec::new(), }.into()), + + find_config: None, + join_config: None, + create_config: None, }], }), ..Default::default() @@ -507,7 +512,9 @@ async fn test_find_idle_lobby(ctx: TestCtx) { tracing::info!("finding lobby"); let player_id = Uuid::new_v4(); let query_id = Uuid::new_v4(); - let find_res = msg!([ctx] @notrace mm::msg::lobby_find(test_ctx.namespace_id, query_id) -> Result { + let find_res = msg!([ctx] @notrace mm::msg::lobby_find(test_ctx.namespace_id, query_id) + -> Result + { namespace_id: Some(test_ctx.namespace_id.into()), query_id: Some(query_id.into()), join_kind: backend::matchmaker::query::JoinKind::Normal as i32, @@ -524,9 +531,11 @@ async fn test_find_idle_lobby(ctx: TestCtx) { region_ids: vec![test_ctx.region_id.into()], auto_create: None, })), + ..Default::default() }) .await - .unwrap().unwrap(); + .unwrap() + .unwrap(); let find_lobby_id = find_res.lobby_id.as_ref().unwrap().as_uuid(); assert!( diff --git a/svc/pkg/mm/ops/lobby-list-for-namespace/Cargo.toml b/svc/pkg/mm/ops/lobby-list-for-namespace/Cargo.toml index 9bc3acc1f1..0a47a9e80e 100644 --- a/svc/pkg/mm/ops/lobby-list-for-namespace/Cargo.toml +++ b/svc/pkg/mm/ops/lobby-list-for-namespace/Cargo.toml @@ -12,7 +12,7 @@ prost = "0.10" util-mm = { package = "rivet-util-mm", path = "../../util" } [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/mm/ops/lobby-list-for-user-id/Cargo.toml b/svc/pkg/mm/ops/lobby-list-for-user-id/Cargo.toml new file mode 100644 index 0000000000..8dcb2904b6 --- /dev/null +++ b/svc/pkg/mm/ops/lobby-list-for-user-id/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "mm-lobby-list-for-user-id" +version = "0.0.1" +edition = "2018" +authors = ["Rivet Gaming, LLC "] +license = "Apache-2.0" + +[dependencies] +chirp-client = { path = "../../../../../lib/chirp/client" } +rivet-operation = { path = "../../../../../lib/operation/core" } +prost = "0.10" + +[dependencies.sqlx] +version = "0.7" +default-features = false + +[dev-dependencies] +chirp-worker = { path = "../../../../../lib/chirp/worker" } + +faker-mm-lobby = { path = "../../../faker/ops/mm-lobby" } diff --git a/svc/pkg/mm/ops/lobby-list-for-user-id/README.md b/svc/pkg/mm/ops/lobby-list-for-user-id/README.md new file mode 100644 index 0000000000..7fa275934d --- /dev/null +++ b/svc/pkg/mm/ops/lobby-list-for-user-id/README.md @@ -0,0 +1 @@ +# mm-lobby-list-for-user-id diff --git a/svc/pkg/mm/ops/lobby-list-for-user-id/Service.toml b/svc/pkg/mm/ops/lobby-list-for-user-id/Service.toml new file mode 100644 index 0000000000..fd08011b0c --- /dev/null +++ b/svc/pkg/mm/ops/lobby-list-for-user-id/Service.toml @@ -0,0 +1,7 @@ +[service] +name = "mm-lobby-list-for-user-id" + +[runtime] +kind = "rust" + +[operation] diff --git a/svc/pkg/mm/ops/lobby-list-for-user-id/src/lib.rs b/svc/pkg/mm/ops/lobby-list-for-user-id/src/lib.rs new file mode 100644 index 0000000000..4a1f4d2d2b --- /dev/null +++ b/svc/pkg/mm/ops/lobby-list-for-user-id/src/lib.rs @@ -0,0 +1,51 @@ +use proto::backend::{self, pkg::*}; +use rivet_operation::prelude::*; + +#[derive(sqlx::FromRow)] +struct LobbyRow { + lobby_id: Uuid, + creator_user_id: Uuid, +} + +#[operation(name = "mm-lobby-list-for-user-id")] +async fn handle( + ctx: OperationContext, +) -> GlobalResult { + let crdb = ctx.crdb("db-mm-state").await?; + let user_ids = ctx + .user_ids + .iter() + .map(common::Uuid::as_uuid) + .collect::>(); + + let lobbies = sqlx::query_as::<_, LobbyRow>(indoc!( + " + SELECT + lobby_id, + creator_user_id + FROM lobbies + WHERE creator_user_id = ANY($1) + " + )) + .bind(&user_ids) + .fetch_all(&crdb) + .await?; + + Ok(mm::lobby_list_for_user_id::Response { + users: user_ids + .into_iter() + .map(|user_id| { + let lobby_ids = lobbies + .iter() + .filter(|l| l.creator_user_id == user_id) + .map(|l| l.lobby_id.into()) + .collect::>(); + + mm::lobby_list_for_user_id::response::User { + user_id: Some(user_id.into()), + lobby_ids, + } + }) + .collect::>(), + }) +} diff --git a/svc/pkg/mm/ops/lobby-list-for-user-id/tests/integration.rs b/svc/pkg/mm/ops/lobby-list-for-user-id/tests/integration.rs new file mode 100644 index 0000000000..a1189959a4 --- /dev/null +++ b/svc/pkg/mm/ops/lobby-list-for-user-id/tests/integration.rs @@ -0,0 +1,26 @@ +use chirp_worker::prelude::*; + +#[worker_test] +async fn empty(ctx: TestCtx) { + let user_id = Uuid::new_v4(); + let lobby_res = op!([ctx] faker_mm_lobby { + creator_user_id: Some(user_id.into()), + ..Default::default() + }) + .await + .unwrap(); + + let res = op!([ctx] mm_lobby_list_for_user_id { + user_ids: vec![user_id.into()], + }) + .await + .unwrap(); + let user = res.users.first().unwrap(); + + assert!( + user.lobby_ids + .iter() + .any(|lobby_id| &lobby_res.lobby_id.unwrap() == lobby_id), + "lobby not listed" + ); +} diff --git a/svc/pkg/mm/ops/lobby-player-count/Cargo.toml b/svc/pkg/mm/ops/lobby-player-count/Cargo.toml index 70f25c6427..444f358103 100644 --- a/svc/pkg/mm/ops/lobby-player-count/Cargo.toml +++ b/svc/pkg/mm/ops/lobby-player-count/Cargo.toml @@ -12,7 +12,7 @@ prost = "0.10" util-mm = { package = "rivet-util-mm", path = "../../util" } [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/mm/ops/lobby-player-count/tests/integration.rs b/svc/pkg/mm/ops/lobby-player-count/tests/integration.rs index 71b3d490dc..26177a3d8e 100644 --- a/svc/pkg/mm/ops/lobby-player-count/tests/integration.rs +++ b/svc/pkg/mm/ops/lobby-player-count/tests/integration.rs @@ -67,6 +67,7 @@ async fn empty(ctx: TestCtx) { query: Some(mm::msg::lobby_find::message::Query::Direct(backend::matchmaker::query::Direct { lobby_id: Some(player.lobby_id.into()), })), + ..Default::default() }) .await .unwrap().unwrap(); diff --git a/svc/pkg/mm/ops/lobby-runtime-aggregate/Cargo.toml b/svc/pkg/mm/ops/lobby-runtime-aggregate/Cargo.toml index 3c982285b8..b38c035ffd 100644 --- a/svc/pkg/mm/ops/lobby-runtime-aggregate/Cargo.toml +++ b/svc/pkg/mm/ops/lobby-runtime-aggregate/Cargo.toml @@ -16,7 +16,7 @@ mm-config-lobby-group-resolve-version = { path = "../../../mm-config/ops/lobby-g mm-config-version-get = { path = "../../../mm-config/ops/version-get" } [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/mm/ops/player-count-for-namespace/Cargo.toml b/svc/pkg/mm/ops/player-count-for-namespace/Cargo.toml index 3d6ae46aee..f2d8e76505 100644 --- a/svc/pkg/mm/ops/player-count-for-namespace/Cargo.toml +++ b/svc/pkg/mm/ops/player-count-for-namespace/Cargo.toml @@ -12,7 +12,7 @@ prost = "0.10" util-mm = { package = "rivet-util-mm", path = "../../util" } [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/mm/ops/player-count-for-namespace/tests/integration.rs b/svc/pkg/mm/ops/player-count-for-namespace/tests/integration.rs index 479e532587..c76a35c93c 100644 --- a/svc/pkg/mm/ops/player-count-for-namespace/tests/integration.rs +++ b/svc/pkg/mm/ops/player-count-for-namespace/tests/integration.rs @@ -29,6 +29,7 @@ async fn empty(ctx: TestCtx) { query: Some(mm::msg::lobby_find::message::Query::Direct(backend::matchmaker::query::Direct { lobby_id: Some(lobby_id), })), + ..Default::default() }) .await .unwrap().unwrap(); diff --git a/svc/pkg/mm/ops/player-get/Cargo.toml b/svc/pkg/mm/ops/player-get/Cargo.toml index 9464425cdc..a1fd2d398d 100644 --- a/svc/pkg/mm/ops/player-get/Cargo.toml +++ b/svc/pkg/mm/ops/player-get/Cargo.toml @@ -11,7 +11,7 @@ chirp-client = { path = "../../../../../lib/chirp/client" } prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/mm/ops/player-get/tests/integration.rs b/svc/pkg/mm/ops/player-get/tests/integration.rs index a64c74e0f6..2d72f9747e 100644 --- a/svc/pkg/mm/ops/player-get/tests/integration.rs +++ b/svc/pkg/mm/ops/player-get/tests/integration.rs @@ -27,6 +27,7 @@ async fn basic(ctx: TestCtx) { query: Some(mm::msg::lobby_find::message::Query::Direct(backend::matchmaker::query::Direct { lobby_id: Some(lobby_id.into()), })), + ..Default::default() }).await.unwrap().unwrap(); let res = op!([ctx] mm_player_get { diff --git a/svc/pkg/mm/standalone/gc-full/Cargo.toml b/svc/pkg/mm/standalone/gc-full/Cargo.toml index ac86d49b84..93a3203e02 100644 --- a/svc/pkg/mm/standalone/gc-full/Cargo.toml +++ b/svc/pkg/mm/standalone/gc-full/Cargo.toml @@ -19,14 +19,13 @@ tracing-subscriber = { version = "0.3", default-features = false, features = ["f util-mm = { package = "rivet-util-mm", path = "../../util" } [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false features = [ - "runtime-tokio-native-tls", + "runtime-tokio", "postgres", "uuid", "json", - "tls", "macros", ] diff --git a/svc/pkg/mm/standalone/gc/Cargo.toml b/svc/pkg/mm/standalone/gc/Cargo.toml index d52a2d8d81..173e6b71c5 100644 --- a/svc/pkg/mm/standalone/gc/Cargo.toml +++ b/svc/pkg/mm/standalone/gc/Cargo.toml @@ -17,7 +17,7 @@ rivet-health-checks = { path = "../../../../../lib/health-checks" } rivet-metrics = { path = "../../../../../lib/metrics" } rivet-pools = { path = "../../../../../lib/pools" } rivet-runtime = { path = "../../../../../lib/runtime" } -tokio = { version = "1.21", features = ["full"] } +tokio = { version = "1.29", features = ["full"] } tracing = "0.1" tracing-subscriber = { version = "0.3", default-features = false, features = ["fmt", "json", "ansi"] } util-mm = { package = "rivet-util-mm", path = "../../util" } @@ -25,14 +25,13 @@ util-mm = { package = "rivet-util-mm", path = "../../util" } region-list = { path = "../../../region/ops/list" } [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false features = [ - "runtime-tokio-native-tls", + "runtime-tokio", "postgres", "uuid", "json", - "tls", "macros", ] diff --git a/svc/pkg/mm/standalone/gc/tests/integration.rs b/svc/pkg/mm/standalone/gc/tests/integration.rs index a8d5f7cf26..843d55996b 100644 --- a/svc/pkg/mm/standalone/gc/tests/integration.rs +++ b/svc/pkg/mm/standalone/gc/tests/integration.rs @@ -44,6 +44,7 @@ async fn remove_unready_lobbies(ctx: TestCtx, crdb: CrdbPool) { let get_res = op!([ctx] mm_lobby_get { lobby_ids: vec![lobby_id.into()], include_stopped: true, + include_private: true, }) .await .unwrap(); @@ -73,6 +74,7 @@ async fn remove_unready_lobbies(ctx: TestCtx, crdb: CrdbPool) { let get_res = op!([ctx] mm_lobby_get { lobby_ids: vec![lobby_id.into()], include_stopped: true, + include_private: true, }) .await .unwrap(); @@ -108,6 +110,7 @@ async fn remove_unregistered_players(ctx: TestCtx, crdb: CrdbPool) { query: Some(mm::msg::lobby_find::message::Query::Direct(backend::matchmaker::query::Direct { lobby_id: Some(lobby_id.into()), })), + ..Default::default() }) .await .unwrap().unwrap(); diff --git a/svc/pkg/mm/types/lobby-get.proto b/svc/pkg/mm/types/lobby-get.proto index de7eef6da6..6ef1a122cd 100644 --- a/svc/pkg/mm/types/lobby-get.proto +++ b/svc/pkg/mm/types/lobby-get.proto @@ -8,6 +8,7 @@ import "proto/backend/matchmaker.proto"; message Request { repeated rivet.common.Uuid lobby_ids = 1; bool include_stopped = 2; + bool include_private = 3; } message Response { diff --git a/svc/pkg/mm/types/lobby-list-for-user-id.proto b/svc/pkg/mm/types/lobby-list-for-user-id.proto new file mode 100644 index 0000000000..4aa7531210 --- /dev/null +++ b/svc/pkg/mm/types/lobby-list-for-user-id.proto @@ -0,0 +1,18 @@ +syntax = "proto3"; + +package rivet.backend.pkg.mm.lobby_list_for_user_id; + +import "proto/common.proto"; + +message Request { + repeated rivet.common.Uuid user_ids = 1; +} + +message Response { + message User { + rivet.common.Uuid user_id = 1; + repeated rivet.common.Uuid lobby_ids = 2; + } + + repeated User users = 1; +} diff --git a/svc/pkg/mm/types/msg/lobby-create.proto b/svc/pkg/mm/types/msg/lobby-create.proto index d7baf93874..5b9365c5f6 100644 --- a/svc/pkg/mm/types/msg/lobby-create.proto +++ b/svc/pkg/mm/types/msg/lobby-create.proto @@ -3,6 +3,7 @@ syntax = "proto3"; package rivet.backend.pkg.mm.msg.lobby_create; import "proto/common.proto"; +import "proto/backend/matchmaker.proto"; /// name = "msg-mm-lobby-create" /// parameters = [ @@ -36,5 +37,16 @@ message Message { // If a lobby row was preemptively inserted for this lobby. bool preemptively_created = 7; + + // The user (if any) that triggered this lobby's creation (either by /find or /create). + optional rivet.common.Uuid creator_user_id = 8; + // If this is a custom lobby created by a user. + bool is_custom = 9; + // Publicity of the lobby. Private lobbies do not show up in /list. Defaults to + // public when not set. + optional rivet.backend.matchmaker.Lobby.Publicity publicity = 10; + + // Extra lobby config provided by the user in /create. Sent to the lobby as an env var. + optional string lobby_config_json = 11; } diff --git a/svc/pkg/mm/types/msg/lobby-find-fail.proto b/svc/pkg/mm/types/msg/lobby-find-fail.proto index 01eba4c06b..d4d48e69bf 100644 --- a/svc/pkg/mm/types/msg/lobby-find-fail.proto +++ b/svc/pkg/mm/types/msg/lobby-find-fail.proto @@ -10,7 +10,7 @@ enum ErrorCode { STALE_MESSAGE = 1; TOO_MANY_PLAYERS_FROM_SOURCE = 101; - + LOBBY_STOPPED = 201; LOBBY_CLOSED = 202; LOBBY_NOT_FOUND = 203; @@ -19,8 +19,15 @@ enum ErrorCode { LOBBY_COUNT_OVER_MAX = 206; REGION_NOT_ENABLED = 207; LOBBY_STOPPED_PREMATURELY = 208; - + DEV_TEAM_INVALID_STATUS = 301; + + FIND_DISABLED = 401; + JOIN_DISABLED = 402; + VERIFICATION_FAILED = 403; + VERIFICATION_REQUEST_FAILED = 404; + IDENTITY_REQUIRED = 405; + REGISTRATION_REQUIRED = 406; } /// name = "msg-mm-lobby-find-fail" diff --git a/svc/pkg/mm/types/msg/lobby-find.proto b/svc/pkg/mm/types/msg/lobby-find.proto index 3229dbd509..0321d8e658 100644 --- a/svc/pkg/mm/types/msg/lobby-find.proto +++ b/svc/pkg/mm/types/msg/lobby-find.proto @@ -35,5 +35,12 @@ message Message { rivet.backend.matchmaker.query.Direct direct = 101; rivet.backend.matchmaker.query.LobbyGroup lobby_group = 102; }; + + // The user ID of the game user creating this find request (if there is one). + optional rivet.common.Uuid user_id = 201; + // JSON verification data from the user. + optional string verification_data_json = 202; + // Bypasses user data verification (if the give lobby group has any). + bool bypass_verification = 203; } diff --git a/svc/pkg/mm/util/Cargo.toml b/svc/pkg/mm/util/Cargo.toml index df5b724a59..4d7aa656b3 100644 --- a/svc/pkg/mm/util/Cargo.toml +++ b/svc/pkg/mm/util/Cargo.toml @@ -7,7 +7,15 @@ license = "Apache-2.0" [dependencies] bit-vec = "0.6" +chirp-client = { path = "../../../../lib/chirp/client" } +http = "0.2" +rivet-operation = { path = "../../../../lib/operation/core" } rivet-util = { path = "../../../../lib/util/core" } serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" strum = { version = "0.24", features = ["derive"] } uuid = { version = "1", features = ["v4", "serde"] } + +mm-lobby-list-for-user-id = { path = "../ops/lobby-list-for-user-id" } +region-get = { path = "../../region/ops/get" } +user-identity-get = { path = "../../user-identity/ops/get" } \ No newline at end of file diff --git a/svc/pkg/mm/util/src/consts.rs b/svc/pkg/mm/util/src/consts.rs index c1cc3c6373..7b5f235385 100644 --- a/svc/pkg/mm/util/src/consts.rs +++ b/svc/pkg/mm/util/src/consts.rs @@ -1,6 +1,7 @@ use rivet_util as util; -pub const LOBBY_READY_TIMEOUT: i64 = util::duration::minutes(5); // Also see mm-gc.LOBBY_READY_TIMEOUT +// TODO: Lower this again +pub const LOBBY_READY_TIMEOUT: i64 = util::duration::minutes(10); // Also see mm-gc.LOBBY_READY_TIMEOUT pub const PLAYER_READY_TIMEOUT: i64 = util::duration::minutes(2); // Also see mm-gc.LOBBY_READY_TIMEOUT pub const MIN_HOST_PORT: u16 = 26000; diff --git a/svc/pkg/mm/util/src/key.rs b/svc/pkg/mm/util/src/key.rs index d93bba3970..4a223db278 100644 --- a/svc/pkg/mm/util/src/key.rs +++ b/svc/pkg/mm/util/src/key.rs @@ -53,6 +53,8 @@ pub mod lobby_config { pub ready_ts: Option, #[serde(rename = "c")] pub is_closed: bool, + #[serde(rename = "cu")] + pub is_custom: bool, } pub const NAMESPACE_ID: &str = "ns"; diff --git a/svc/pkg/mm/util/src/lib.rs b/svc/pkg/mm/util/src/lib.rs index 89cef1142d..2c55146a15 100644 --- a/svc/pkg/mm/util/src/lib.rs +++ b/svc/pkg/mm/util/src/lib.rs @@ -2,6 +2,7 @@ pub mod consts; pub mod defaults; pub mod key; pub mod test; +pub mod verification; pub mod version_migrations; pub enum JoinKind { diff --git a/svc/pkg/mm/util/src/verification.rs b/svc/pkg/mm/util/src/verification.rs new file mode 100644 index 0000000000..5586fee980 --- /dev/null +++ b/svc/pkg/mm/util/src/verification.rs @@ -0,0 +1,281 @@ +use http::StatusCode; +use proto::backend::{self, pkg::*}; +use rivet_operation::prelude::*; +use serde::Serialize; +use uuid::Uuid; + +#[derive(Serialize)] +pub struct ExternalVerificationRequest { + pub verification_data: Option, + pub lobby: Lobby, + pub join_kind: JoinKind, + pub kind: ConnectionKind, +} + +#[derive(Serialize)] +pub struct Lobby { + pub namespace_id: Uuid, + pub lobby_group_id: Uuid, + pub lobby_group_name_id: String, + + pub state: Option, + pub config: Option, +} + +#[derive(Serialize)] +pub struct LobbyState { + pub lobby_id: Uuid, + pub region_id: Uuid, + pub region_name_id: String, + pub create_ts: String, + pub is_closed: bool, +} + +#[derive(Serialize)] +pub enum JoinKind { + Normal, + Party, +} + +#[derive(Copy, Clone, Serialize)] +pub enum ConnectionKind { + Find, + Join, + Create, +} + +pub struct VerifyConfigOpts<'a> { + pub kind: ConnectionKind, + pub namespace_id: Uuid, + pub user_id: Option, + + pub lobby_group: &'a backend::matchmaker::LobbyGroup, + pub lobby_group_meta: &'a backend::matchmaker::LobbyGroupMeta, + pub lobby_state: Option<&'a backend::matchmaker::Lobby>, + + pub verification_data_json: Option<&'a String>, + pub lobby_config_json: Option<&'a String>, + pub custom_lobby_publicity: Option, +} + +/// Verifies everything required to make a find request or create a custom lobby. +pub async fn verify_config( + ctx: &OperationContext<()>, + opts: &VerifyConfigOpts<'_>, +) -> GlobalResult<()> { + // Get required verifications + let (identity_requirement, external_request_config) = match ( + opts.kind, + opts.lobby_group.find_config.as_ref(), + opts.lobby_group.join_config.as_ref(), + opts.lobby_group.create_config.as_ref(), + ) { + (ConnectionKind::Find, Some(find_config), _, _) => { + if !find_config.enabled { + panic_with!(MATCHMAKER_FIND_DISABLED); + } + + ( + internal_unwrap_owned!( + backend::matchmaker::IdentityRequirement::from_i32( + find_config.identity_requirement + ), + "invalid identity requirement variant" + ), + find_config.verification_config.as_ref().map(|config| { + backend::net::ExternalRequestConfig { + url: config.url.clone(), + method: backend::net::HttpMethod::Post as i32, + headers: config.headers.clone(), + } + }), + ) + } + (ConnectionKind::Join, _, Some(join_config), _) => { + if !join_config.enabled { + panic_with!(MATCHMAKER_JOIN_DISABLED); + } + + ( + internal_unwrap_owned!( + backend::matchmaker::IdentityRequirement::from_i32( + join_config.identity_requirement + ), + "invalid identity requirement variant" + ), + join_config.verification_config.as_ref().map(|config| { + backend::net::ExternalRequestConfig { + url: config.url.clone(), + method: backend::net::HttpMethod::Post as i32, + headers: config.headers.clone(), + } + }), + ) + } + (ConnectionKind::Create, _, _, Some(create_config)) => { + let publicity = internal_unwrap_owned!(opts.custom_lobby_publicity); + + // Verify publicity + match ( + publicity, + create_config.enable_public, + create_config.enable_private, + ) { + (backend::matchmaker::lobby::Publicity::Public, true, _) => {} + (backend::matchmaker::lobby::Publicity::Private, _, true) => {} + _ => { + panic_with!( + MATCHMAKER_CUSTOM_LOBBY_CONFIG_INVALID, + reason = "given publicity not allowed" + ); + } + } + + // Verify lobby count + if let (Some(max_lobbies_per_identity), Some(user_id)) = + (create_config.max_lobbies_per_identity, opts.user_id) + { + let lobbies_res = op!([ctx] mm_lobby_list_for_user_id { + user_ids: vec![user_id.into()], + }) + .await?; + let user = internal_unwrap_owned!(lobbies_res.users.first()); + assert_with!( + (user.lobby_ids.len() as u64) < max_lobbies_per_identity, + MATCHMAKER_CUSTOM_LOBBY_LIMIT_REACHED + ); + } + + ( + internal_unwrap_owned!( + backend::matchmaker::IdentityRequirement::from_i32( + create_config.identity_requirement + ), + "invalid identity requirement variant" + ), + create_config.verification_config.as_ref().map(|config| { + backend::net::ExternalRequestConfig { + url: config.url.clone(), + method: backend::net::HttpMethod::Post as i32, + headers: config.headers.clone(), + } + }), + ) + } + (ConnectionKind::Create, _, _, None) => { + panic_with!(MATCHMAKER_CUSTOM_LOBBIES_DISABLED); + } + _ => (backend::matchmaker::IdentityRequirement::None, None), + }; + + // Verify identity requirement + match (identity_requirement, opts.user_id) { + (backend::matchmaker::IdentityRequirement::Registered, Some(user_id)) => { + let user_identities_res = op!([ctx] user_identity_get { + user_ids: vec![user_id.into()], + }) + .await?; + let user = internal_unwrap_owned!( + user_identities_res.users.first(), + "could not find user identities" + ); + let is_registered = !user.identities.is_empty(); + + if !is_registered { + panic_with!(MATCHMAKER_REGISTRATION_REQUIRED); + } + } + ( + backend::matchmaker::IdentityRequirement::Guest + | backend::matchmaker::IdentityRequirement::Registered, + None, + ) => { + panic_with!(MATCHMAKER_IDENTITY_REQUIRED); + } + _ => {} + } + + // Verify lobby config + if let Some(lobby_config_json) = opts.lobby_config_json { + assert_with!( + lobby_config_json.len() as u64 <= util::file_size::kibibytes(16), + MATCHMAKER_CUSTOM_LOBBY_CONFIG_INVALID, + reason = "too large (> 16KiB)" + ); + } + + // Verify user data externally + if external_request_config.is_some() { + // Build lobby state + let lobby_state = if let Some(l) = &opts.lobby_state { + // Fetch region data for readable name + let region_id = internal_unwrap_owned!(l.region_id); + let regions_res = op!([ctx] region_get { + region_ids: vec![region_id], + }) + .await?; + let region = internal_unwrap_owned!(regions_res.regions.first()); + + Some(LobbyState { + lobby_id: internal_unwrap!(l.lobby_id).as_uuid(), + region_id: region_id.as_uuid(), + region_name_id: region.name_id.clone(), + create_ts: util::timestamp::to_string(l.create_ts)?, + is_closed: l.is_closed, + }) + } else { + None + }; + + // Build body + let body = ExternalVerificationRequest { + verification_data: opts + .verification_data_json + .as_ref() + .map(|json| serde_json::from_str::(json.as_str())) + .transpose()?, + lobby: Lobby { + lobby_group_id: internal_unwrap!(opts.lobby_group_meta.lobby_group_id).as_uuid(), + lobby_group_name_id: opts.lobby_group.name_id.clone(), + namespace_id: opts.namespace_id, + + state: None, + config: opts + .lobby_config_json + .as_ref() + .map(|json| serde_json::from_str::(json.as_str())) + .transpose()?, + }, + join_kind: JoinKind::Normal, + kind: opts.kind, + }; + + // Send request + let request_id = Uuid::new_v4(); + let external_res = msg!([ctx] external::msg::request_call(request_id) + -> Result + { + request_id: Some(request_id.into()), + config: external_request_config, + timeout: util::duration::seconds(10) as u64, + body: Some(serde_json::to_vec(&body)?), + ..Default::default() + }) + .await?; + + // Handle status code + if let Ok(res) = external_res { + let status = StatusCode::from_u16(res.status_code as u16)?; + + tracing::info!(?status, "user verification response"); + + if !status.is_success() { + panic_with!(MATCHMAKER_VERIFICATION_FAILED); + } + } else { + panic_with!(MATCHMAKER_VERIFICATION_REQUEST_FAILED); + } + } + + Ok(()) +} diff --git a/svc/pkg/mm/worker/Cargo.toml b/svc/pkg/mm/worker/Cargo.toml index b4c5541306..dae9d686de 100644 --- a/svc/pkg/mm/worker/Cargo.toml +++ b/svc/pkg/mm/worker/Cargo.toml @@ -35,6 +35,7 @@ mm-config-version-get = { path = "../../mm-config/ops/version-get" } mm-lobby-find-fail = { path = "../ops/lobby-find-fail" } mm-lobby-find-lobby-query-list = { path = "../ops/lobby-find-lobby-query-list" } mm-lobby-find-try-complete = { path = "../ops/lobby-find-try-complete" } +mm-lobby-get = { path = "../ops/lobby-get" } mm-lobby-idle-update = { path = "../ops/lobby-idle-update" } region-get = { path = "../../region/ops/get" } team-dev-get = { path = "../../team-dev/ops/get" } @@ -45,7 +46,7 @@ upload-get = { path = "../../upload/ops/get" } upload-prepare = { path = "../../upload/ops/prepare" } [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] @@ -56,8 +57,11 @@ faker-game = { path = "../../faker/ops/game" } faker-game-version = { path = "../../faker/ops/game-version" } faker-mm-lobby = { path = "../../faker/ops/mm-lobby" } faker-region = { path = "../../faker/ops/region" } +faker-user = { path = "../../faker/ops/user" } game-namespace-version-set = { path = "../../game/ops/namespace-version-set" } mm-config-namespace-config-set = { path = "../../mm-config/ops/namespace-config-set" } mm-config-version-get = { path = "../../mm-config/ops/version-get" } -mm-lobby-player-count = { path = "../ops/lobby-player-count" } mm-lobby-get = { path = "../ops/lobby-get" } +mm-lobby-player-count = { path = "../ops/lobby-player-count" } +region-list = { path = "../../region/ops/list" } +user-identity-create = { path = "../../user-identity/ops/create" } diff --git a/svc/pkg/mm/worker/redis-scripts/lobby_create.lua b/svc/pkg/mm/worker/redis-scripts/lobby_create.lua index 16ee91a7e1..41635457d4 100644 --- a/svc/pkg/mm/worker/redis-scripts/lobby_create.lua +++ b/svc/pkg/mm/worker/redis-scripts/lobby_create.lua @@ -22,7 +22,8 @@ redis.call('ZADD', key_lobby_available_spots_party, lobby_config['mpp'] - player redis.call('ZADD', key_lobby_unready, tonumber(ready_expire_ts), lobby_id) -- Add to idle lobbies if needed -if player_count == 0 then +local is_custom = lobby_config['cu'] +if player_count == 0 and not is_custom then redis.call('ZADD', key_idle_lobby_ids, ts, lobby_id) redis.call('HSET', key_idle_lobby_lobby_group_ids, lobby_id, lobby_config['lg']) end diff --git a/svc/pkg/mm/worker/redis-scripts/lobby_find.lua b/svc/pkg/mm/worker/redis-scripts/lobby_find.lua index eca22568ba..555ab12300 100644 --- a/svc/pkg/mm/worker/redis-scripts/lobby_find.lua +++ b/svc/pkg/mm/worker/redis-scripts/lobby_find.lua @@ -22,14 +22,14 @@ if query.kind.direct ~= nil then -- Check lobby exists if redis.call('EXISTS', key_direct_lobby_config) == 0 then - return {'err', 'LOBBY_NOT_FOUND'} + return { 'err', 'LOBBY_NOT_FOUND' } end -- Check lobby is not closed - local is_closed = redis.call('HGET', key_direct_lobby_config, 'c') == '1' - if is_closed then - return {'err', 'LOBBY_CLOSED'} - end + -- local is_closed = redis.call('HGET', key_direct_lobby_config, 'c') == '1' + -- if is_closed then + -- return {'err', 'LOBBY_CLOSED'} + -- end -- Get max player count local max_player_count = nil @@ -44,7 +44,7 @@ if query.kind.direct ~= nil then -- Validate player count local player_count = redis.call('ZCARD', key_direct_lobby_player_ids) if player_count + table.getn(query.players) > max_player_count then - return {'err', 'LOBBY_FULL'} + return { 'err', 'LOBBY_FULL' } end lobby_id = query.kind.direct.lobby_id @@ -63,7 +63,8 @@ elseif query.kind.lobby_group ~= nil then -- instead of `max_players_party` because `max_players_party` is -- only relevant when joining a lobby with the exact lobby ID (i.e. -- where `max_players_direct` would normally be used). - local lobby = redis.call('ZRANGEBYSCORE', key_available_spots, table.getn(query.players), '+inf', 'WITHSCORES', 'LIMIT', '0', '1') + local lobby = redis.call('ZRANGEBYSCORE', key_available_spots, table.getn(query.players), '+inf', 'WITHSCORES', + 'LIMIT', '0', '1') if table.getn(lobby) > 0 then local lobby_id = lobby[1] local available_spots = tonumber(lobby[2]) @@ -93,8 +94,10 @@ elseif query.kind.lobby_group ~= nil then redis.call('HSET', key_auto_create_lobby_config, k, tostring(v)) end redis.call('ZADD', key_auto_create_ns_lobby_ids, ts, auto_create.lobby_id) - redis.call('ZADD', key_auto_create_lobby_available_spots_normal, auto_create.lobby_config['mpn'], auto_create.lobby_id) - redis.call('ZADD', key_auto_create_lobby_available_spots_party, auto_create.lobby_config['mpp'], auto_create.lobby_id) + redis.call('ZADD', key_auto_create_lobby_available_spots_normal, auto_create.lobby_config['mpn'], + auto_create.lobby_id) + redis.call('ZADD', key_auto_create_lobby_available_spots_party, auto_create.lobby_config['mpp'], + auto_create.lobby_id) redis.call('ZADD', key_lobby_unready, tonumber(auto_create.ready_expire_ts), auto_create.lobby_id) end @@ -104,7 +107,7 @@ elseif query.kind.lobby_group ~= nil then elseif auto_create ~= nil then lobby_id = auto_create.lobby_id else - return {'err', 'NO_AVAILABLE_LOBBIES'} + return { 'err', 'NO_AVAILABLE_LOBBIES' } end else return redis.error_reply('Invalid query kind') @@ -131,10 +134,14 @@ local max_players_party = tonumber(redis.call('HGET', key_lobby_config, 'mpp')) -- Build keys for the given lobby ID local key_lobby_find_queries = 'mm:lobby:' .. lobby_id .. ':find_queries' local key_lobby_player_ids = 'mm:lobby:' .. lobby_id .. ':player_ids' -local key_lobby_available_spots_normal = 'mm:ns:' .. namespace_id .. ':region:' .. region_id .. ':lg:' .. lobby_group_id .. ':lobby:available_spots:normal' -local key_lobby_available_spots_party = 'mm:ns:' .. namespace_id .. ':region:' .. region_id .. ':lg:' .. lobby_group_id .. ':lobby:available_spots:party' -local key_idle_lobby_ids = 'mm:ns:' .. namespace_id .. ':region:' .. region_id .. ':lg:' .. lobby_group_id .. ':idle_lobby_ids' -local key_idle_lobby_lobby_group_ids = 'mm:ns:' .. namespace_id .. ':region:' .. region_id .. ':lobby:idle:lobby_group_ids' +local key_lobby_available_spots_normal = 'mm:ns:' .. +namespace_id .. ':region:' .. region_id .. ':lg:' .. lobby_group_id .. ':lobby:available_spots:normal' +local key_lobby_available_spots_party = 'mm:ns:' .. +namespace_id .. ':region:' .. region_id .. ':lg:' .. lobby_group_id .. ':lobby:available_spots:party' +local key_idle_lobby_ids = 'mm:ns:' .. +namespace_id .. ':region:' .. region_id .. ':lg:' .. lobby_group_id .. ':idle_lobby_ids' +local key_idle_lobby_lobby_group_ids = 'mm:ns:' .. +namespace_id .. ':region:' .. region_id .. ':lobby:idle:lobby_group_ids' -- Assert lobby state if #lobby_id ~= 36 then @@ -201,5 +208,4 @@ for _, player in ipairs(query.players) do end -return {'ok', {lobby_id, region_id, lobby_group_id}} - +return { 'ok', { lobby_id, region_id, lobby_group_id } } diff --git a/svc/pkg/mm/worker/src/workers/lobby_cleanup.rs b/svc/pkg/mm/worker/src/workers/lobby_cleanup.rs index 28766599e8..afc556c6e2 100644 --- a/svc/pkg/mm/worker/src/workers/lobby_cleanup.rs +++ b/svc/pkg/mm/worker/src/workers/lobby_cleanup.rs @@ -15,7 +15,7 @@ struct LobbyRow { } #[worker(name = "mm-lobby-cleanup")] -async fn worker(ctx: OperationContext) -> GlobalResult<()> { +async fn worker(ctx: &OperationContext) -> GlobalResult<()> { // NOTE: Idempotent let lobby_id = internal_unwrap!(ctx.lobby_id).as_uuid(); diff --git a/svc/pkg/mm/worker/src/workers/lobby_closed_set.rs b/svc/pkg/mm/worker/src/workers/lobby_closed_set.rs index 6d5a4b7f5a..7e5659c980 100644 --- a/svc/pkg/mm/worker/src/workers/lobby_closed_set.rs +++ b/svc/pkg/mm/worker/src/workers/lobby_closed_set.rs @@ -15,7 +15,7 @@ struct LobbyRow { } #[worker(name = "mm-lobby-closed-set")] -async fn worker(ctx: OperationContext) -> GlobalResult<()> { +async fn worker(ctx: &OperationContext) -> GlobalResult<()> { let crdb = ctx.crdb("db-mm-state").await?; let lobby_id = internal_unwrap!(ctx.lobby_id).as_uuid(); diff --git a/svc/pkg/mm/worker/src/workers/lobby_create/mod.rs b/svc/pkg/mm/worker/src/workers/lobby_create/mod.rs index 4a26ff9f5b..190967a04e 100644 --- a/svc/pkg/mm/worker/src/workers/lobby_create/mod.rs +++ b/svc/pkg/mm/worker/src/workers/lobby_create/mod.rs @@ -52,7 +52,7 @@ async fn fail( } #[worker(name = "mm-lobby-create")] -async fn worker(ctx: OperationContext) -> GlobalResult<()> { +async fn worker(ctx: &OperationContext) -> GlobalResult<()> { let crdb = ctx.crdb("db-mm-state").await?; let lobby_id = internal_unwrap!(ctx.lobby_id).as_uuid(); @@ -60,6 +60,7 @@ async fn worker(ctx: OperationContext) -> Global let lobby_group_id = internal_unwrap!(ctx.lobby_group_id).as_uuid(); let region_id = internal_unwrap!(ctx.region_id).as_uuid(); let create_ray_id = ctx.region_id.as_ref().map(common::Uuid::as_uuid); + let creator_user_id = ctx.creator_user_id.as_ref().map(common::Uuid::as_uuid); // Check for stale message if ctx.req_dt() > util::duration::seconds(60) { @@ -168,6 +169,11 @@ async fn worker(ctx: OperationContext) -> Global run_id, create_ray_id: ctx.ray_id(), lobby_group: lobby_group.clone(), + creator_user_id, + is_custom: ctx.is_custom, + publicity: ctx + .publicity + .and_then(backend::matchmaker::lobby::Publicity::from_i32), }; rivet_pools::utils::crdb::tx(&crdb, |tx| { Box::pin(update_db(ctx.ts(), tx, insert_opts.clone())) @@ -191,6 +197,7 @@ async fn worker(ctx: OperationContext) -> Global preemptive: false, is_closed: false, ready_ts: None, + is_custom: ctx.is_custom, })?) .arg(ctx.ts() + util_mm::consts::LOBBY_READY_TIMEOUT) .key(key::lobby_config(lobby_id)) @@ -295,7 +302,7 @@ async fn fetch_region( .await?; let cdn_region = internal_unwrap_owned!(cdn_get_res.regions.first()); - Ok((region.deref().clone(), cdn_region.deref().clone())) + Ok((region.clone(), cdn_region.clone())) } #[tracing::instrument] @@ -322,9 +329,8 @@ async fn fetch_namespace( }) .await?; - let namespace = internal_unwrap!(get_res.namespaces.first(), "namespace not found") - .deref() - .clone(); + let namespace = + internal_unwrap_owned!(get_res.namespaces.first(), "namespace not found").clone(); Ok(namespace) } @@ -340,7 +346,7 @@ async fn fetch_mm_namespace_config( .await?; let namespace = internal_unwrap!( - internal_unwrap!(get_res.namespaces.first(), "namespace not found").config + internal_unwrap_owned!(get_res.namespaces.first(), "namespace not found").config ) .deref() .clone(); @@ -479,6 +485,9 @@ struct UpdateDbOpts { run_id: Uuid, create_ray_id: Uuid, lobby_group: backend::matchmaker::LobbyGroup, + creator_user_id: Option, + is_custom: bool, + publicity: Option, } #[tracing::instrument(skip_all)] @@ -497,7 +506,7 @@ async fn update_db( "SELECT stop_ts, preemptive_create_ts FROM lobbies WHERE lobby_id = $1 FOR UPDATE", ) .bind(opts.lobby_id) - .fetch_optional(&mut *tx) + .fetch_optional(&mut **tx) .await?; if let Some((stop_ts, preemptive_create_ts)) = lobby_row { if preemptive_create_ts.is_none() { @@ -528,9 +537,12 @@ async fn update_db( max_players_direct, max_players_party, - is_closed + is_closed, + creator_user_id, + is_custom, + publicity ) - VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, false) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, false, $12, $13, $14) " )) .bind(opts.lobby_id) @@ -544,7 +556,10 @@ async fn update_db( .bind(opts.lobby_group.max_players_normal as i64) .bind(opts.lobby_group.max_players_direct as i64) .bind(opts.lobby_group.max_players_party as i64) - .execute(&mut *tx) + .bind(opts.creator_user_id) + .bind(opts.is_custom) + .bind(opts.publicity.map(|p| p as i32 as i64)) + .execute(&mut **tx) .await?; Ok(()) @@ -585,7 +600,12 @@ async fn create_docker_job( let build = internal_unwrap_owned!(build_get.builds.first()); // Generate the Docker job - let job_spec = nomad_job::gen_lobby_docker_job(runtime, &build.image_tag, tier)?; + let job_spec = nomad_job::gen_lobby_docker_job( + runtime, + &build.image_tag, + tier, + ctx.lobby_config_json.as_ref(), + )?; let job_spec_json = serde_json::to_string(&job_spec)?; // Build proxied ports for each exposed port @@ -725,6 +745,17 @@ async fn resolve_image_artifact_url( .await?; let upload = internal_unwrap_owned!(upload_res.uploads.first()); + // Get provider + let proto_provider = internal_unwrap_owned!( + backend::upload::Provider::from_i32(upload.provider as i32), + "invalid upload provider" + ); + let provider = match proto_provider { + backend::upload::Provider::Minio => s3_util::Provider::Minio, + backend::upload::Provider::Backblaze => s3_util::Provider::Backblaze, + backend::upload::Provider::Aws => s3_util::Provider::Aws, + }; + match DELIVERY_METHOD { DeliveryMethod::Ats => { // TODO: Auto-generate password for this & encode in to infra/salt/salt/traffic_server/files/consul/traffic_server.hcl.j2 diff --git a/svc/pkg/mm/worker/src/workers/lobby_create/nomad_job.rs b/svc/pkg/mm/worker/src/workers/lobby_create/nomad_job.rs index 4452791ebb..1b80fadb22 100644 --- a/svc/pkg/mm/worker/src/workers/lobby_create/nomad_job.rs +++ b/svc/pkg/mm/worker/src/workers/lobby_create/nomad_job.rs @@ -44,6 +44,7 @@ pub fn gen_lobby_docker_job( runtime: &backend::matchmaker::lobby_runtime::Docker, image_tag: &str, tier: &backend::region::Tier, + lobby_config_json: Option<&String>, ) -> GlobalResult { // IMPORTANT: This job spec must be deterministic. Do not pass in parameters // that change with every run, such as the lobby ID. Ensure the @@ -115,6 +116,13 @@ pub fn gen_lobby_docker_job( v.value.replace('$', "$$"), ) }) + .chain(lobby_config_json.map(|config| { + ( + "RIVET_LOBBY_CONFIG".to_string(), + // Escape all interpolation + config.replace('$', "$$"), + ) + })) .chain( [ ("RIVET_CHAT_API_URL", "api-chat"), @@ -122,7 +130,6 @@ pub fn gen_lobby_docker_job( ("RIVET_IDENTITY_API_URL", "api-identity"), ("RIVET_KV_API_URL", "api-kv"), ("RIVET_MATCHMAKER_API_URL", "api-matchmaker"), - ("RIVET_PARTY_API_URL", "api-party"), ] .iter() .map(|(env, service)| (env.to_string(), util::env::svc_router_url(service))), diff --git a/svc/pkg/mm/worker/src/workers/lobby_find/find.rs b/svc/pkg/mm/worker/src/workers/lobby_find/find.rs index 9b137bbd93..772fbad7fe 100644 --- a/svc/pkg/mm/worker/src/workers/lobby_find/find.rs +++ b/svc/pkg/mm/worker/src/workers/lobby_find/find.rs @@ -1,6 +1,11 @@ use chirp_worker::prelude::*; use proto::backend::{ - self, matchmaker::query::JoinKind, pkg::mm::msg::lobby_find::message::Query, pkg::*, + self, + matchmaker::query::JoinKind, + pkg::{ + mm::{msg::lobby_find::message::Query, msg::lobby_find_fail::ErrorCode}, + *, + }, }; use rand::seq::SliceRandom; use redis_util::RedisResult; @@ -78,7 +83,7 @@ pub struct FindOpts<'a> { pub join_kind: JoinKind, pub players: &'a [super::Player], pub query: &'a Query, - pub lobby_group_config: Option<&'a LobbyGroupConfig>, + pub lobby_group_config: &'a LobbyGroupConfig, pub auto_create_lobby_id: Uuid, } @@ -148,9 +153,7 @@ pub async fn find( .collect::>(); // Update config for auto create lobbies - let auto_create = if let (Some(auto_create), Some(lobby_group_config)) = - (auto_create, lobby_group_config) - { + let auto_create = if let Some(auto_create) = auto_create { let region_id = internal_unwrap!(auto_create.region_id).as_uuid(); let lobby_group_id = internal_unwrap!(auto_create.lobby_group_id).as_uuid(); @@ -186,6 +189,7 @@ pub async fn find( preemptive: true, ready_ts: None, is_closed: false, + is_custom: false, }, ready_expire_ts: ctx.ts() + util_mm::consts::LOBBY_READY_TIMEOUT, }) @@ -324,17 +328,17 @@ pub async fn find( .fetch_optional(crdb) .await? { - mm::msg::lobby_find_fail::ErrorCode::LobbyStopped + ErrorCode::LobbyStopped } else { - mm::msg::lobby_find_fail::ErrorCode::LobbyNotFound + ErrorCode::LobbyNotFound } } else { - mm::msg::lobby_find_fail::ErrorCode::LobbyNotFound + ErrorCode::LobbyNotFound } } - Err("LOBBY_CLOSED") => mm::msg::lobby_find_fail::ErrorCode::LobbyClosed, - Err("LOBBY_FULL") => mm::msg::lobby_find_fail::ErrorCode::LobbyFull, - Err("NO_AVAILABLE_LOBBIES") => mm::msg::lobby_find_fail::ErrorCode::NoAvailableLobbies, + Err("LOBBY_CLOSED") => ErrorCode::LobbyClosed, + Err("LOBBY_FULL") => ErrorCode::LobbyFull, + Err("NO_AVAILABLE_LOBBIES") => ErrorCode::NoAvailableLobbies, Err(_) => internal_panic!("unknown redis error"), }; diff --git a/svc/pkg/mm/worker/src/workers/lobby_find/limit.rs b/svc/pkg/mm/worker/src/workers/lobby_find/limit.rs index 07b447b8fd..dcee8a5f80 100644 --- a/svc/pkg/mm/worker/src/workers/lobby_find/limit.rs +++ b/svc/pkg/mm/worker/src/workers/lobby_find/limit.rs @@ -1,5 +1,5 @@ use chirp_worker::prelude::*; -use proto::backend::{self, pkg::*}; +use proto::backend::{self, pkg::mm::msg::lobby_find_fail::ErrorCode, pkg::*}; use serde_json::json; use super::fail; @@ -79,7 +79,7 @@ pub async fn check_remote_addresses( ctx, namespace_id, query_id, - mm::msg::lobby_find_fail::ErrorCode::TooManyPlayersFromSource, + ErrorCode::TooManyPlayersFromSource, true, ) .await diff --git a/svc/pkg/mm/worker/src/workers/lobby_find/mod.rs b/svc/pkg/mm/worker/src/workers/lobby_find/mod.rs index 4ca64b9ba0..b45944b55f 100644 --- a/svc/pkg/mm/worker/src/workers/lobby_find/mod.rs +++ b/svc/pkg/mm/worker/src/workers/lobby_find/mod.rs @@ -1,7 +1,10 @@ use chirp_worker::prelude::*; use proto::backend::{ self, - pkg::{mm::msg::lobby_find::message::Query, *}, + pkg::{ + mm::{msg::lobby_find::message::Query, msg::lobby_find_fail::ErrorCode}, + *, + }, }; use serde_json::json; use tracing::Instrument; @@ -23,7 +26,7 @@ async fn fail( ctx: &OperationContext, namespace_id: Uuid, query_id: Uuid, - error_code: mm::msg::lobby_find_fail::ErrorCode, + error_code: ErrorCode, force_fail: bool, ) -> GlobalResult<()> { tracing::warn!(%namespace_id, ?query_id, ?error_code, ?force_fail, "player create failed"); @@ -68,7 +71,7 @@ async fn complete_request( } #[worker(name = "mm-lobby-find")] -async fn worker(ctx: OperationContext) -> GlobalResult<()> { +async fn worker(ctx: &OperationContext) -> GlobalResult<()> { // TODO: Fetch all sessions for the current IP // TODO: Map to all players matching the given sessions @@ -88,34 +91,14 @@ async fn worker(ctx: OperationContext) -> GlobalRe // Check for stale message if ctx.req_dt() > util::duration::seconds(60) { tracing::warn!("discarding stale message"); - fail( - ctx, - namespace_id, - query_id, - mm::msg::lobby_find_fail::ErrorCode::StaleMessage, - true, - ) - .await?; + fail(ctx, namespace_id, query_id, ErrorCode::StaleMessage, true).await?; return complete_request(ctx.chirp(), analytics_events).await; } let ((_namespace, mm_ns_config, dev_team), lobby_group_config) = tokio::try_join!( // Namespace and dev team fetch_ns_config_and_dev_team(ctx.base(), namespace_id), - // Fetch lobby group config if auto-creating lobby - async { - if let Query::LobbyGroup(backend::matchmaker::query::LobbyGroup { - auto_create: Some(auto_create), - .. - }) = &query - { - let lobby_group_id = internal_unwrap!(auto_create.lobby_group_id).as_uuid(); - let config = fetch_lobby_group_config(ctx.base(), lobby_group_id).await?; - Ok(Some(config)) - } else { - Ok(None) - } - }, + fetch_lobby_group_config(ctx.base(), query), )?; // Verify dev team status @@ -124,10 +107,56 @@ async fn worker(ctx: OperationContext) -> GlobalRe ctx, namespace_id, query_id, - mm::msg::lobby_find_fail::ErrorCode::DevTeamInvalidStatus, + ErrorCode::DevTeamInvalidStatus, true, ) .await?; + return complete_request(ctx.chirp(), analytics_events).await; + } + + // Verify user data + let verification_res = util_mm::verification::verify_config( + &ctx.base(), + &util_mm::verification::VerifyConfigOpts { + kind: match query { + Query::LobbyGroup(_) => util_mm::verification::ConnectionKind::Find, + Query::Direct(_) => util_mm::verification::ConnectionKind::Join, + }, + namespace_id, + user_id: ctx.user_id.map(|id| id.as_uuid()), + lobby_group: &lobby_group_config.lobby_group, + lobby_group_meta: &lobby_group_config.lobby_group_meta, + lobby_state: lobby_group_config.lobby_state.as_ref(), + verification_data_json: ctx.verification_data_json.as_ref(), + lobby_config_json: None, + custom_lobby_publicity: None, + }, + ) + .await; + if let Err(err) = verification_res { + // Reduces verbosity + let err_branch = |err_code| async move { + fail(ctx, namespace_id, query_id, err_code, true).await?; + complete_request(ctx.chirp(), analytics_events).await + }; + + let res = if err.is(formatted_error::code::MATCHMAKER_FIND_DISABLED) { + err_branch(ErrorCode::FindDisabled).await + } else if err.is(formatted_error::code::MATCHMAKER_JOIN_DISABLED) { + err_branch(ErrorCode::JoinDisabled).await + } else if err.is(formatted_error::code::MATCHMAKER_REGISTRATION_REQUIRED) { + err_branch(ErrorCode::RegistrationRequired).await + } else if err.is(formatted_error::code::MATCHMAKER_IDENTITY_REQUIRED) { + err_branch(ErrorCode::IdentityRequired).await + } else if err.is(formatted_error::code::MATCHMAKER_VERIFICATION_FAILED) { + err_branch(ErrorCode::VerificationFailed).await + } else if err.is(formatted_error::code::MATCHMAKER_VERIFICATION_REQUEST_FAILED) { + err_branch(ErrorCode::VerificationRequestFailed).await + } else { + Err(err) + }; + + return res; } // Create players @@ -192,7 +221,7 @@ async fn worker(ctx: OperationContext) -> GlobalRe join_kind, players: &players, query, - lobby_group_config: lobby_group_config.as_ref(), + lobby_group_config: &lobby_group_config, auto_create_lobby_id, }, ) @@ -281,6 +310,11 @@ async fn worker(ctx: OperationContext) -> GlobalRe region_id: Some(auto_create_region_id.into()), create_ray_id: Some(ctx.ray_id().into()), preemptively_created: true, + + creator_user_id: ctx.user_id, + is_custom: false, + publicity: None, + lobby_config_json: None, }) .await?; @@ -415,23 +449,46 @@ pub struct LobbyGroupConfig { pub lobby_group: backend::matchmaker::LobbyGroup, #[allow(unused)] pub lobby_group_meta: backend::matchmaker::LobbyGroupMeta, + pub lobby_state: Option, } -/// Fetches the lobby group config. Only used if auto-creating lobby. +/// Fetches the lobby group config (and lobby if direct). #[tracing::instrument] async fn fetch_lobby_group_config( ctx: OperationContext<()>, - lobby_group_id: Uuid, + query: &Query, ) -> GlobalResult { - let lobby_group_id_proto = Some(common::Uuid::from(lobby_group_id)); + // Get lobby group id from query + let (lobby_group_id, lobby_state) = match query { + Query::LobbyGroup(backend::matchmaker::query::LobbyGroup { auto_create, .. }) => { + let auto_create = internal_unwrap!(auto_create); + + (internal_unwrap_owned!(auto_create.lobby_group_id), None) + } + Query::Direct(backend::matchmaker::query::Direct { lobby_id, .. }) => { + let lobby_id = internal_unwrap_owned!(*lobby_id); + + let lobbies_res = op!([ctx] mm_lobby_get { + lobby_ids: vec![lobby_id], + }) + .await?; + let lobby = internal_unwrap_owned!(lobbies_res.lobbies.first(), "lobby not found"); + + ( + internal_unwrap_owned!(lobby.lobby_group_id), + Some(lobby.clone()), + ) + } + }; + let lobby_group_id_proto = Some(lobby_group_id); // Resolve the version ID let resolve_version_res = op!([ctx] mm_config_lobby_group_resolve_version { - lobby_group_ids: vec![lobby_group_id.into()], + lobby_group_ids: vec![lobby_group_id], }) .await?; let version_id = internal_unwrap!( - internal_unwrap!( + internal_unwrap_owned!( resolve_version_res.versions.first(), "lobby group not found" ) @@ -464,6 +521,7 @@ async fn fetch_lobby_group_config( version_id, lobby_group: (*lobby_group).clone(), lobby_group_meta: (*lobby_group_meta).clone(), + lobby_state, }) } @@ -477,7 +535,7 @@ struct InsertCrdbOpts { lobby_id: Uuid, region_id: Uuid, lobby_group_id: Uuid, - lobby_group_config: Option, + lobby_group_config: LobbyGroupConfig, auto_create_lobby: bool, now_ts: i64, ray_id: Uuid, @@ -503,9 +561,6 @@ async fn insert_to_crdb( ) -> GlobalResult<()> { // Insert preemptive lobby row if needed if auto_create_lobby { - // Lobby group config will exist if the lobby was auto created - let lobby_group_config = internal_unwrap!(lobby_group_config); - // Insert lobby if needed sqlx::query(indoc!( " @@ -537,7 +592,7 @@ async fn insert_to_crdb( .bind(lobby_group_config.lobby_group.max_players_normal as i64) .bind(lobby_group_config.lobby_group.max_players_direct as i64) .bind(lobby_group_config.lobby_group.max_players_party as i64) - .execute(&mut *tx) + .execute(&mut **tx) .await?; } @@ -561,7 +616,7 @@ async fn insert_to_crdb( .bind(lobby_id) .bind(auto_create_lobby) .bind(util_mm::FindQueryStatus::Pending as i64) - .execute(&mut *tx) + .execute(&mut **tx) .await?; // Insert players @@ -592,7 +647,7 @@ async fn insert_to_crdb( ) .bind(now_ts) .bind(ray_id) - .execute(&mut *tx) + .execute(&mut **tx) .await?; } diff --git a/svc/pkg/mm/worker/src/workers/lobby_find_job_run_fail.rs b/svc/pkg/mm/worker/src/workers/lobby_find_job_run_fail.rs index 6aba8fec1c..580fab9e94 100644 --- a/svc/pkg/mm/worker/src/workers/lobby_find_job_run_fail.rs +++ b/svc/pkg/mm/worker/src/workers/lobby_find_job_run_fail.rs @@ -8,7 +8,7 @@ struct LobbyRow { } #[worker(name = "mm-lobby-find-job-run-fail")] -async fn worker(ctx: OperationContext) -> GlobalResult<()> { +async fn worker(ctx: &OperationContext) -> GlobalResult<()> { let crdb = ctx.crdb("db-mm-state").await?; let run_id = internal_unwrap!(ctx.run_id).as_uuid(); diff --git a/svc/pkg/mm/worker/src/workers/lobby_find_lobby_cleanup.rs b/svc/pkg/mm/worker/src/workers/lobby_find_lobby_cleanup.rs index ebef8b7c5c..ea74229937 100644 --- a/svc/pkg/mm/worker/src/workers/lobby_find_lobby_cleanup.rs +++ b/svc/pkg/mm/worker/src/workers/lobby_find_lobby_cleanup.rs @@ -1,8 +1,8 @@ use chirp_worker::prelude::*; -use proto::backend::pkg::*; +use proto::backend::pkg::{mm::msg::lobby_find_fail::ErrorCode, *}; #[worker(name = "mm-lobby-find-lobby-cleanup")] -async fn worker(ctx: OperationContext) -> GlobalResult<()> { +async fn worker(ctx: &OperationContext) -> GlobalResult<()> { let lobby_id = internal_unwrap!(ctx.lobby_id).as_uuid(); // TODO: Is there a race condition here for new queries? @@ -16,7 +16,7 @@ async fn worker(ctx: OperationContext) -> Globa .await?; op!([ctx] mm_lobby_find_fail { query_ids: query_list.query_ids.clone(), - error_code: mm::msg::lobby_find_fail::ErrorCode::LobbyStoppedPrematurely as i32, + error_code: ErrorCode::LobbyStoppedPrematurely as i32, ..Default::default() }) .await?; diff --git a/svc/pkg/mm/worker/src/workers/lobby_find_lobby_create_fail.rs b/svc/pkg/mm/worker/src/workers/lobby_find_lobby_create_fail.rs index af1ca69326..babebe6aaa 100644 --- a/svc/pkg/mm/worker/src/workers/lobby_find_lobby_create_fail.rs +++ b/svc/pkg/mm/worker/src/workers/lobby_find_lobby_create_fail.rs @@ -2,7 +2,7 @@ use chirp_worker::prelude::*; use proto::backend::pkg::*; #[worker(name = "mm-lobby-find-lobby-create-fail")] -async fn worker(ctx: OperationContext) -> GlobalResult<()> { +async fn worker(ctx: &OperationContext) -> GlobalResult<()> { let lobby_id = internal_unwrap!(ctx.lobby_id).as_uuid(); let error_code = match mm::msg::lobby_create_fail::ErrorCode::from_i32(ctx.error_code) { diff --git a/svc/pkg/mm/worker/src/workers/lobby_find_lobby_ready.rs b/svc/pkg/mm/worker/src/workers/lobby_find_lobby_ready.rs index e5d7446fe2..5d90529727 100644 --- a/svc/pkg/mm/worker/src/workers/lobby_find_lobby_ready.rs +++ b/svc/pkg/mm/worker/src/workers/lobby_find_lobby_ready.rs @@ -2,7 +2,9 @@ use chirp_worker::prelude::*; use proto::backend::pkg::*; #[worker(name = "mm-lobby-find-lobby-ready")] -async fn worker(ctx: OperationContext) -> GlobalResult<()> { +async fn worker( + ctx: &OperationContext, +) -> GlobalResult<()> { let lobby_id = internal_unwrap!(ctx.lobby_id).as_uuid(); // TODO: Is there a race condition here for new queries? diff --git a/svc/pkg/mm/worker/src/workers/lobby_history_export.rs b/svc/pkg/mm/worker/src/workers/lobby_history_export.rs index ec3d388e7c..811e170ea4 100644 --- a/svc/pkg/mm/worker/src/workers/lobby_history_export.rs +++ b/svc/pkg/mm/worker/src/workers/lobby_history_export.rs @@ -48,7 +48,9 @@ struct LobbyGroupCache { } #[worker(name = "mm-lobby-history-export")] -async fn worker(ctx: OperationContext) -> GlobalResult<()> { +async fn worker( + ctx: &OperationContext, +) -> GlobalResult<()> { let crdb = ctx.crdb("db-mm-state").await?; let request_id = internal_unwrap!(ctx.request_id).as_uuid(); diff --git a/svc/pkg/mm/worker/src/workers/lobby_job_run_cleanup.rs b/svc/pkg/mm/worker/src/workers/lobby_job_run_cleanup.rs index 7eb82d813b..adc375a3fb 100644 --- a/svc/pkg/mm/worker/src/workers/lobby_job_run_cleanup.rs +++ b/svc/pkg/mm/worker/src/workers/lobby_job_run_cleanup.rs @@ -2,7 +2,7 @@ use chirp_worker::prelude::*; use proto::backend::pkg::*; #[worker(name = "mm-lobby-job-run-cleanup")] -async fn worker(ctx: OperationContext) -> GlobalResult<()> { +async fn worker(ctx: &OperationContext) -> GlobalResult<()> { let crdb = ctx.crdb("db-mm-state").await?; let run_id = internal_unwrap!(ctx.run_id).as_uuid(); diff --git a/svc/pkg/mm/worker/src/workers/lobby_ready_set.rs b/svc/pkg/mm/worker/src/workers/lobby_ready_set.rs index c4bd051238..9f5f779e43 100644 --- a/svc/pkg/mm/worker/src/workers/lobby_ready_set.rs +++ b/svc/pkg/mm/worker/src/workers/lobby_ready_set.rs @@ -16,7 +16,7 @@ struct LobbyRow { } #[worker(name = "mm-lobby-ready-set")] -async fn worker(ctx: OperationContext) -> GlobalResult<()> { +async fn worker(ctx: &OperationContext) -> GlobalResult<()> { let crdb = ctx.crdb("db-mm-state").await?; let mut redis_mm = ctx.redis_mm().await?; diff --git a/svc/pkg/mm/worker/src/workers/lobby_stop.rs b/svc/pkg/mm/worker/src/workers/lobby_stop.rs index 06f3715064..ed777c4d3a 100644 --- a/svc/pkg/mm/worker/src/workers/lobby_stop.rs +++ b/svc/pkg/mm/worker/src/workers/lobby_stop.rs @@ -8,7 +8,7 @@ struct LobbyRow { } #[worker(name = "mm-lobby-stop")] -async fn worker(ctx: OperationContext) -> GlobalResult<()> { +async fn worker(ctx: &OperationContext) -> GlobalResult<()> { let lobby_id = internal_unwrap!(ctx.lobby_id).as_uuid(); let crdb = ctx.crdb("db-mm-state").await?; diff --git a/svc/pkg/mm/worker/src/workers/player_register.rs b/svc/pkg/mm/worker/src/workers/player_register.rs index 675492de39..6902625486 100644 --- a/svc/pkg/mm/worker/src/workers/player_register.rs +++ b/svc/pkg/mm/worker/src/workers/player_register.rs @@ -12,7 +12,7 @@ struct PlayerRow { } #[worker(name = "mm-player-register")] -async fn worker(ctx: OperationContext) -> GlobalResult<()> { +async fn worker(ctx: &OperationContext) -> GlobalResult<()> { let crdb = ctx.crdb("db-mm-state").await?; let player_id = internal_unwrap!(ctx.player_id).as_uuid(); diff --git a/svc/pkg/mm/worker/src/workers/player_remove.rs b/svc/pkg/mm/worker/src/workers/player_remove.rs index a394400cd4..a4ff54cdde 100644 --- a/svc/pkg/mm/worker/src/workers/player_remove.rs +++ b/svc/pkg/mm/worker/src/workers/player_remove.rs @@ -29,7 +29,7 @@ struct PlayerRow { struct LobbyRow {} #[worker(name = "mm-player-remove")] -async fn worker(ctx: OperationContext) -> GlobalResult<()> { +async fn worker(ctx: &OperationContext) -> GlobalResult<()> { // NOTE: Idempotent let crdb = ctx.crdb("db-mm-state").await?; diff --git a/svc/pkg/mm/worker/tests/lobby_create.rs b/svc/pkg/mm/worker/tests/lobby_create.rs index c7a7435a66..b629a92b17 100644 --- a/svc/pkg/mm/worker/tests/lobby_create.rs +++ b/svc/pkg/mm/worker/tests/lobby_create.rs @@ -34,11 +34,16 @@ async fn setup(ctx: &TestCtx) -> Setup { regions: vec![backend::matchmaker::lobby_group::Region { region_id: Some(region_id.into()), tier_name_id: util_mm::test::TIER_NAME_ID.to_owned(), - idle_lobbies: None, + idle_lobbies: Some(backend::matchmaker::lobby_group::IdleLobbies { + min_idle_lobbies: 0, + // Don't auto-destory lobbies from tests + max_idle_lobbies: 32, + }), }], max_players_normal: 8, max_players_direct: 10, max_players_party: 12, + listable: true, runtime: Some(backend::matchmaker::lobby_runtime::Docker { build_id: build_res.build_id, @@ -80,6 +85,10 @@ async fn setup(ctx: &TestCtx) -> Setup { ], }.into()), + + find_config: None, + join_config: None, + create_config: None, }, backend::matchmaker::LobbyGroup { name_id: "test-2".into(), @@ -87,11 +96,16 @@ async fn setup(ctx: &TestCtx) -> Setup { regions: vec![backend::matchmaker::lobby_group::Region { region_id: Some(region_id.into()), tier_name_id: util_mm::test::TIER_NAME_ID.to_owned(), - idle_lobbies: None, + idle_lobbies: Some(backend::matchmaker::lobby_group::IdleLobbies { + min_idle_lobbies: 0, + // See above + max_idle_lobbies: 32, + }), }], max_players_normal: 8, max_players_direct: 10, max_players_party: 12, + listable: true, runtime: Some(backend::matchmaker::lobby_runtime::Docker { build_id: build_res.build_id, @@ -122,6 +136,10 @@ async fn setup(ctx: &TestCtx) -> Setup { ], }.into()), + + find_config: None, + join_config: None, + create_config: None, }], }), ..Default::default() @@ -175,6 +193,11 @@ async fn lobby_create(ctx: TestCtx) { region_id: Some(setup.region_id.into()), create_ray_id: None, preemptively_created: false, + + creator_user_id: None, + is_custom: false, + publicity: None, + lobby_config_json: None, }) .await .unwrap(); @@ -195,6 +218,46 @@ async fn lobby_create(ctx: TestCtx) { assert_eq!(12, sql_mpp); } +#[worker_test] +async fn custom_private_lobby_create(ctx: TestCtx) { + let setup = setup(&ctx).await; + + let lobby_id = Uuid::new_v4(); + msg!([ctx] mm::msg::lobby_create(lobby_id) -> mm::msg::lobby_create_complete { + lobby_id: Some(lobby_id.into()), + namespace_id: Some(setup.namespace_id.into()), + lobby_group_id: Some(setup.lobby_group_id.into()), + region_id: Some(setup.region_id.into()), + create_ray_id: None, + preemptively_created: false, + + creator_user_id: None, + is_custom: true, + publicity: Some(backend::matchmaker::lobby::Publicity::Private as i32), + lobby_config_json: Some(r#"{ "foo": "bar" }"#.to_string()), + }) + .await + .unwrap(); + + let (is_custom, publicity) = sqlx::query_as::<_, (bool, i64)>(indoc!( + " + SELECT is_custom, publicity + FROM lobbies + WHERE lobby_id = $1 + " + )) + .bind(lobby_id) + .fetch_one(&ctx.crdb("db-mm-state").await.unwrap()) + .await + .unwrap(); + + assert!(is_custom); + assert_eq!( + backend::matchmaker::lobby::Publicity::Private as i32 as i64, + publicity + ); +} + #[worker_test] async fn lobby_create_max_lobby_count(ctx: TestCtx) { let setup = setup(&ctx).await; @@ -222,6 +285,11 @@ async fn lobby_create_max_lobby_count(ctx: TestCtx) { region_id: Some(setup.region_id.into()), create_ray_id: None, preemptively_created: false, + + creator_user_id: None, + is_custom: false, + publicity: None, + lobby_config_json: None, }) .await .unwrap(); @@ -236,6 +304,11 @@ async fn lobby_create_max_lobby_count(ctx: TestCtx) { region_id: Some(setup.region_id.into()), create_ray_id: None, preemptively_created: false, + + creator_user_id: None, + is_custom: false, + publicity: None, + lobby_config_json: None, }) .await .unwrap(); @@ -257,6 +330,11 @@ async fn lobby_create_reuse_job_id(ctx: TestCtx) { region_id: Some(setup.region_id.into()), create_ray_id: None, preemptively_created: false, + + creator_user_id: None, + is_custom: false, + publicity: None, + lobby_config_json: None, }) .await .unwrap(); @@ -269,6 +347,11 @@ async fn lobby_create_reuse_job_id(ctx: TestCtx) { region_id: Some(setup.region_id.into()), create_ray_id: None, preemptively_created: false, + + creator_user_id: None, + is_custom: false, + publicity: None, + lobby_config_json: None, }) .await .unwrap(); @@ -303,6 +386,8 @@ async fn lobby_create_reuse_job_id(ctx: TestCtx) { assert_eq!(job_a, job_b, "these runs were dispatched from different jobs. this means the nomad job is not deterministic."); } +// TODO: Write test verifying that lobby config data shows up in lobby env + // #[worker_test] // async fn lobby_create_stress_test(ctx: TestCtx) { // let setup = setup(&ctx).await; @@ -316,6 +401,11 @@ async fn lobby_create_reuse_job_id(ctx: TestCtx) { // region_id: Some(setup.region_id.into()), // create_ray_id: None, // preemptively_created: false, + +// creator_user_id: None, +// is_custom: false, +// publicity: None, +// lobby_config_json: None, // }) // .await // .unwrap(); diff --git a/svc/pkg/mm/worker/tests/lobby_find.rs b/svc/pkg/mm/worker/tests/lobby_find.rs index 9d3afe7d4c..08c248cd01 100644 --- a/svc/pkg/mm/worker/tests/lobby_find.rs +++ b/svc/pkg/mm/worker/tests/lobby_find.rs @@ -1,3 +1,5 @@ +use std::collections::HashMap; + use chirp_worker::prelude::*; use proto::backend::{self, pkg::*}; @@ -44,6 +46,7 @@ async fn create_lobby_group(ctx: &TestCtx, image: Option) - max_players_normal: 8, max_players_direct: 10, max_players_party: 12, + listable: true, runtime: Some(backend::matchmaker::lobby_runtime::Docker { // We can't use `curlimages/curl` here because it doesn't allow for @@ -64,6 +67,10 @@ async fn create_lobby_group(ctx: &TestCtx, image: Option) - proxy_kind: backend::matchmaker::lobby_runtime::ProxyKind::GameGuard as i32, }], }.into()), + + find_config: None, + join_config: None, + create_config: None, }], }), ..Default::default() @@ -107,11 +114,18 @@ async fn direct(ctx: TestCtx) { let find_res = find( &ctx, - lobby_res.namespace_id.as_ref().unwrap().as_uuid(), - gen_players(1), - mm::msg::lobby_find::message::Query::Direct(backend::matchmaker::query::Direct { - lobby_id: lobby_res.lobby_id, - }), + FindRequest { + namespace_id: lobby_res.namespace_id.as_ref().unwrap().as_uuid(), + players: gen_players(1), + query: mm::msg::lobby_find::message::Query::Direct( + backend::matchmaker::query::Direct { + lobby_id: lobby_res.lobby_id, + }, + ), + user_id: None, + verification_data_json: None, + bypass_verification: false, + }, ) .await .unwrap(); @@ -129,16 +143,23 @@ async fn lobby_group_existing(ctx: TestCtx) { let find_res = find( &ctx, - lobby_res.namespace_id.as_ref().unwrap().as_uuid(), - gen_players(1), - mm::msg::lobby_find::message::Query::LobbyGroup(backend::matchmaker::query::LobbyGroup { - lobby_group_ids: vec![lobby_res.lobby_group_id.unwrap()], - region_ids: vec![lobby_res.region_id.unwrap()], - auto_create: Some(backend::matchmaker::query::AutoCreate { - lobby_group_id: lobby_res.lobby_group_id, - region_id: lobby_res.region_id, - }), - }), + FindRequest { + namespace_id: lobby_res.namespace_id.as_ref().unwrap().as_uuid(), + players: gen_players(1), + query: mm::msg::lobby_find::message::Query::LobbyGroup( + backend::matchmaker::query::LobbyGroup { + lobby_group_ids: vec![lobby_res.lobby_group_id.unwrap()], + region_ids: vec![lobby_res.region_id.unwrap()], + auto_create: Some(backend::matchmaker::query::AutoCreate { + lobby_group_id: lobby_res.lobby_group_id, + region_id: lobby_res.region_id, + }), + }, + ), + user_id: None, + verification_data_json: None, + bypass_verification: false, + }, ) .await .unwrap(); @@ -164,11 +185,18 @@ async fn direct_closed(ctx: TestCtx) { let err = find( &ctx, - lobby_res.namespace_id.as_ref().unwrap().as_uuid(), - gen_players(1), - mm::msg::lobby_find::message::Query::Direct(backend::matchmaker::query::Direct { - lobby_id: lobby_res.lobby_id, - }), + FindRequest { + namespace_id: lobby_res.namespace_id.as_ref().unwrap().as_uuid(), + players: gen_players(1), + query: mm::msg::lobby_find::message::Query::Direct( + backend::matchmaker::query::Direct { + lobby_id: lobby_res.lobby_id, + }, + ), + user_id: None, + verification_data_json: None, + bypass_verification: false, + }, ) .await .unwrap_err(); @@ -197,13 +225,20 @@ async fn lobby_group_closed(ctx: TestCtx) { let err = find( &ctx, - lobby_res.namespace_id.as_ref().unwrap().as_uuid(), - gen_players(1), - mm::msg::lobby_find::message::Query::LobbyGroup(backend::matchmaker::query::LobbyGroup { - lobby_group_ids: vec![lobby_res.lobby_group_id.unwrap()], - region_ids: vec![lobby_res.region_id.unwrap()], - auto_create: None, - }), + FindRequest { + namespace_id: lobby_res.namespace_id.as_ref().unwrap().as_uuid(), + players: gen_players(1), + query: mm::msg::lobby_find::message::Query::LobbyGroup( + backend::matchmaker::query::LobbyGroup { + lobby_group_ids: vec![lobby_res.lobby_group_id.unwrap()], + region_ids: vec![lobby_res.region_id.unwrap()], + auto_create: None, + }, + ), + user_id: None, + verification_data_json: None, + bypass_verification: false, + }, ) .await .unwrap_err(); @@ -220,16 +255,23 @@ async fn lobby_crash_immediate(ctx: TestCtx) { let err = find( &ctx, - lobby_group.namespace_id, - gen_players(1), - mm::msg::lobby_find::message::Query::LobbyGroup(backend::matchmaker::query::LobbyGroup { - lobby_group_ids: vec![lobby_group.lobby_group_id.into()], - region_ids: vec![lobby_group.region_id.into()], - auto_create: Some(backend::matchmaker::query::AutoCreate { - lobby_group_id: Some(lobby_group.lobby_group_id.into()), - region_id: Some(lobby_group.region_id.into()), - }), - }), + FindRequest { + namespace_id: lobby_group.namespace_id, + players: gen_players(1), + query: mm::msg::lobby_find::message::Query::LobbyGroup( + backend::matchmaker::query::LobbyGroup { + lobby_group_ids: vec![lobby_group.lobby_group_id.into()], + region_ids: vec![lobby_group.region_id.into()], + auto_create: Some(backend::matchmaker::query::AutoCreate { + lobby_group_id: Some(lobby_group.lobby_group_id.into()), + region_id: Some(lobby_group.region_id.into()), + }), + }, + ), + user_id: None, + verification_data_json: None, + bypass_verification: false, + }, ) .await .unwrap_err(); @@ -269,18 +311,25 @@ async fn max_players_per_client(ctx: TestCtx) { let res = find( &ctx, - lobby_res.namespace_id.as_ref().unwrap().as_uuid(), - vec![mm::msg::lobby_find::Player { - player_id: Some(Uuid::new_v4().into()), - token_session_id: Some(Uuid::new_v4().into()), - client_info: Some(backend::net::ClientInfo { - user_agent: Some("Test".into()), - remote_address: Some(fake_ip.to_string()), - }), - }], - mm::msg::lobby_find::message::Query::Direct(backend::matchmaker::query::Direct { - lobby_id: lobby_res.lobby_id, - }), + FindRequest { + namespace_id: lobby_res.namespace_id.as_ref().unwrap().as_uuid(), + players: vec![mm::msg::lobby_find::Player { + player_id: Some(Uuid::new_v4().into()), + token_session_id: Some(Uuid::new_v4().into()), + client_info: Some(backend::net::ClientInfo { + user_agent: Some("Test".into()), + remote_address: Some(fake_ip.to_string()), + }), + }], + query: mm::msg::lobby_find::message::Query::Direct( + backend::matchmaker::query::Direct { + lobby_id: lobby_res.lobby_id, + }, + ), + user_id: None, + verification_data_json: None, + bypass_verification: false, + }, ) .await; if i >= max_players_per_client { @@ -301,16 +350,23 @@ async fn lobby_group_auto_create(ctx: TestCtx) { find( &ctx, - lobby_group.namespace_id, - gen_players(1), - mm::msg::lobby_find::message::Query::LobbyGroup(backend::matchmaker::query::LobbyGroup { - lobby_group_ids: vec![lobby_group.lobby_group_id.into()], - region_ids: vec![lobby_group.region_id.into()], - auto_create: Some(backend::matchmaker::query::AutoCreate { - lobby_group_id: Some(lobby_group.lobby_group_id.into()), - region_id: Some(lobby_group.region_id.into()), - }), - }), + FindRequest { + namespace_id: lobby_group.namespace_id, + players: gen_players(1), + query: mm::msg::lobby_find::message::Query::LobbyGroup( + backend::matchmaker::query::LobbyGroup { + lobby_group_ids: vec![lobby_group.lobby_group_id.into()], + region_ids: vec![lobby_group.region_id.into()], + auto_create: Some(backend::matchmaker::query::AutoCreate { + lobby_group_id: Some(lobby_group.lobby_group_id.into()), + region_id: Some(lobby_group.region_id.into()), + }), + }, + ), + user_id: None, + verification_data_json: None, + bypass_verification: false, + }, ) .await .unwrap(); @@ -322,13 +378,20 @@ async fn lobby_group_no_auto_create(ctx: TestCtx) { let err = find( &ctx, - lobby_group.namespace_id, - gen_players(1), - mm::msg::lobby_find::message::Query::LobbyGroup(backend::matchmaker::query::LobbyGroup { - lobby_group_ids: vec![lobby_group.lobby_group_id.into()], - region_ids: vec![lobby_group.region_id.into()], - auto_create: None, - }), + FindRequest { + namespace_id: lobby_group.namespace_id, + players: gen_players(1), + query: mm::msg::lobby_find::message::Query::LobbyGroup( + backend::matchmaker::query::LobbyGroup { + lobby_group_ids: vec![lobby_group.lobby_group_id.into()], + region_ids: vec![lobby_group.region_id.into()], + auto_create: None, + }, + ), + user_id: None, + verification_data_json: None, + bypass_verification: false, + }, ) .await .unwrap_err(); @@ -339,6 +402,275 @@ async fn lobby_group_no_auto_create(ctx: TestCtx) { ); } +#[worker_test] +async fn join_disabled(ctx: TestCtx) { + let user_id = Uuid::new_v4(); + + let (namespace_id, lobby_id) = gen_disabled_lobby(&ctx).await; + + let err = find( + &ctx, + FindRequest { + namespace_id, + players: gen_players(1), + query: mm::msg::lobby_find::message::Query::Direct( + backend::matchmaker::query::Direct { + lobby_id: Some(lobby_id.into()), + }, + ), + user_id: None, + verification_data_json: None, + bypass_verification: false, + }, + ) + .await + .unwrap_err(); + + assert_eq!( + mm::msg::lobby_find_fail::ErrorCode::JoinDisabled as i32, + err.error_code + ); +} + +#[worker_test] +async fn guest_verification(ctx: TestCtx) { + let user_id = Uuid::new_v4(); + + let (namespace_id, lobby_id) = + gen_verification_lobby(&ctx, backend::matchmaker::IdentityRequirement::Guest, None).await; + + let err = find( + &ctx, + FindRequest { + namespace_id, + players: gen_players(1), + query: mm::msg::lobby_find::message::Query::Direct( + backend::matchmaker::query::Direct { + lobby_id: Some(lobby_id.into()), + }, + ), + user_id: None, + verification_data_json: None, + bypass_verification: false, + }, + ) + .await + .unwrap_err(); + + assert_eq!( + mm::msg::lobby_find_fail::ErrorCode::IdentityRequired as i32, + err.error_code + ); + + let _find_res = find( + &ctx, + FindRequest { + namespace_id, + players: gen_players(1), + query: mm::msg::lobby_find::message::Query::Direct( + backend::matchmaker::query::Direct { + lobby_id: Some(lobby_id.into()), + }, + ), + user_id: Some(user_id), + verification_data_json: None, + bypass_verification: false, + }, + ) + .await + .unwrap(); +} + +#[worker_test] +async fn registered_verification(ctx: TestCtx) { + let user_res = op!([ctx] faker_user {}).await.unwrap(); + let user_id = user_res.user_id.unwrap().as_uuid(); + + let (namespace_id, lobby_id) = gen_verification_lobby( + &ctx, + backend::matchmaker::IdentityRequirement::Registered, + None, + ) + .await; + + let err = find( + &ctx, + FindRequest { + namespace_id, + players: gen_players(1), + query: mm::msg::lobby_find::message::Query::Direct( + backend::matchmaker::query::Direct { + lobby_id: Some(lobby_id.into()), + }, + ), + user_id: None, + verification_data_json: None, + bypass_verification: false, + }, + ) + .await + .unwrap_err(); + + assert_eq!( + mm::msg::lobby_find_fail::ErrorCode::IdentityRequired as i32, + err.error_code + ); + + let err = find( + &ctx, + FindRequest { + namespace_id, + players: gen_players(1), + query: mm::msg::lobby_find::message::Query::Direct( + backend::matchmaker::query::Direct { + lobby_id: Some(lobby_id.into()), + }, + ), + user_id: Some(user_id), + verification_data_json: None, + bypass_verification: false, + }, + ) + .await + .unwrap_err(); + + assert_eq!( + mm::msg::lobby_find_fail::ErrorCode::RegistrationRequired as i32, + err.error_code + ); + + let email = util::faker::email(); + op!([ctx] user_identity_create { + user_id: user_res.user_id, + identity: Some(backend::user_identity::Identity { + kind: Some(backend::user_identity::identity::Kind::Email( + backend::user_identity::identity::Email { + email: email.clone(), + } + )), + }), + }) + .await + .unwrap(); + + let _find_res = find( + &ctx, + FindRequest { + namespace_id, + players: gen_players(1), + query: mm::msg::lobby_find::message::Query::Direct( + backend::matchmaker::query::Direct { + lobby_id: Some(lobby_id.into()), + }, + ), + user_id: Some(user_id), + verification_data_json: None, + bypass_verification: false, + }, + ) + .await + .unwrap(); +} + +#[worker_test] +async fn bypass_verification(ctx: TestCtx) { + let user_id = Uuid::new_v4(); + + let (namespace_id, lobby_id) = gen_verification_lobby( + &ctx, + backend::matchmaker::IdentityRequirement::Registered, + None, + ) + .await; + + let _find_res = find( + &ctx, + FindRequest { + namespace_id, + players: gen_players(1), + query: mm::msg::lobby_find::message::Query::Direct( + backend::matchmaker::query::Direct { + lobby_id: Some(lobby_id.into()), + }, + ), + user_id: None, + verification_data_json: None, + bypass_verification: true, + }, + ) + .await + .unwrap(); +} + +// TODO: Find way to actually verify user data +#[worker_test] +async fn external_verification(ctx: TestCtx) { + let user_id = Uuid::new_v4(); + + let (namespace_id, lobby_id) = gen_verification_lobby( + &ctx, + backend::matchmaker::IdentityRequirement::None, + Some(backend::matchmaker::VerificationConfig { + url: "https://httpstat.us/403".to_string(), + headers: IntoIterator::into_iter([("accept".to_string(), "text/plain".to_string())]) + .collect::>(), + }), + ) + .await; + + let err = find( + &ctx, + FindRequest { + namespace_id, + players: gen_players(1), + query: mm::msg::lobby_find::message::Query::Direct( + backend::matchmaker::query::Direct { + lobby_id: Some(lobby_id.into()), + }, + ), + user_id: None, + verification_data_json: None, + bypass_verification: false, + }, + ) + .await + .unwrap_err(); + + assert_eq!( + mm::msg::lobby_find_fail::ErrorCode::VerificationFailed as i32, + err.error_code + ); + + let (namespace_id, lobby_id) = gen_verification_lobby( + &ctx, + backend::matchmaker::IdentityRequirement::None, + Some(backend::matchmaker::VerificationConfig { + url: "https://httpstat.us/200".to_string(), + headers: IntoIterator::into_iter([("accept".to_string(), "text/plain".to_string())]) + .collect::>(), + }), + ) + .await; + + let _find_res = find( + &ctx, + FindRequest { + namespace_id, + players: gen_players(1), + query: mm::msg::lobby_find::message::Query::Direct( + backend::matchmaker::query::Direct { + lobby_id: Some(lobby_id.into()), + }, + ), + user_id: Some(user_id), + verification_data_json: None, + bypass_verification: false, + }, + ) + .await + .unwrap(); +} + fn gen_players(count: usize) -> Vec { let mut players = Vec::new(); for _ in 0..count { @@ -354,22 +686,211 @@ fn gen_players(count: usize) -> Vec { players } -async fn find( +async fn gen_verification_lobby( ctx: &TestCtx, + identity_requirement: backend::matchmaker::IdentityRequirement, + verification_config: Option, +) -> (Uuid, Uuid) { + let region_list_res = op!([ctx] region_list { + ..Default::default() + }) + .await + .unwrap(); + + let game_res = op!([ctx] faker_game { + ..Default::default() + }) + .await + .unwrap(); + let namespace_id = game_res.namespace_ids.first().unwrap(); + + let build_res = op!([ctx] faker_build { + game_id: game_res.game_id, + image: faker::build::Image::MmLobbyAutoReady as i32, + }) + .await + .unwrap(); + + let version_create_res = op!([ctx] faker_game_version { + game_id: game_res.game_id, + override_lobby_groups: Some(faker::game_version::request::OverrideLobbyGroups { + lobby_groups: vec![backend::matchmaker::LobbyGroup { + name_id: "test-1".into(), + + regions: region_list_res + .region_ids + .iter() + .cloned() + .map(|region_id| backend::matchmaker::lobby_group::Region { + region_id: Some(region_id), + tier_name_id: util_mm::test::TIER_NAME_ID.to_owned(), + idle_lobbies: None, + }) + .collect(), + + max_players_normal: 8, + max_players_direct: 10, + max_players_party: 12, + listable: true, + + runtime: Some( + backend::matchmaker::lobby_runtime::Docker { + build_id: build_res.build_id, + args: Vec::new(), + env_vars: Vec::new(), + network_mode: + backend::matchmaker::lobby_runtime::NetworkMode::Bridge + as i32, + ports: Vec::new(), + } + .into(), + ), + + find_config: Some(backend::matchmaker::FindConfig { + enabled: true, + identity_requirement: identity_requirement as i32, + verification_config: verification_config.clone(), + }), + join_config: Some(backend::matchmaker::JoinConfig { + enabled: true, + identity_requirement: identity_requirement as i32, + verification_config, + }), + create_config: None, + }], + }), + }) + .await + .unwrap(); + + let lobby_res = op!([ctx] faker_mm_lobby { + namespace_id: Some(*namespace_id), + version_id: version_create_res.version_id, + ..Default::default() + }) + .await + .unwrap(); + + ( + lobby_res.namespace_id.unwrap().as_uuid(), + lobby_res.lobby_id.unwrap().as_uuid(), + ) +} + +async fn gen_disabled_lobby(ctx: &TestCtx) -> (Uuid, Uuid) { + let region_list_res = op!([ctx] region_list { + ..Default::default() + }) + .await + .unwrap(); + + let game_res = op!([ctx] faker_game { + ..Default::default() + }) + .await + .unwrap(); + let namespace_id = game_res.namespace_ids.first().unwrap(); + + let build_res = op!([ctx] faker_build { + game_id: game_res.game_id, + image: faker::build::Image::MmLobbyAutoReady as i32, + }) + .await + .unwrap(); + + let version_create_res = op!([ctx] faker_game_version { + game_id: game_res.game_id, + override_lobby_groups: Some(faker::game_version::request::OverrideLobbyGroups { + lobby_groups: vec![backend::matchmaker::LobbyGroup { + name_id: "test-1".into(), + + regions: region_list_res + .region_ids + .iter() + .cloned() + .map(|region_id| backend::matchmaker::lobby_group::Region { + region_id: Some(region_id), + tier_name_id: util_mm::test::TIER_NAME_ID.to_owned(), + idle_lobbies: None, + }) + .collect(), + + max_players_normal: 8, + max_players_direct: 10, + max_players_party: 12, + listable: true, + + runtime: Some( + backend::matchmaker::lobby_runtime::Docker { + build_id: build_res.build_id, + args: Vec::new(), + env_vars: Vec::new(), + network_mode: + backend::matchmaker::lobby_runtime::NetworkMode::Bridge + as i32, + ports: Vec::new(), + } + .into(), + ), + + find_config: Some(backend::matchmaker::FindConfig { + enabled: false, + identity_requirement: backend::matchmaker::IdentityRequirement::None as i32, + verification_config: None, + }), + join_config: Some(backend::matchmaker::JoinConfig { + enabled: false, + identity_requirement: backend::matchmaker::IdentityRequirement::None as i32, + verification_config: None, + }), + create_config: None, + }], + }), + }) + .await + .unwrap(); + + let lobby_res = op!([ctx] faker_mm_lobby { + namespace_id: Some(*namespace_id), + version_id: version_create_res.version_id, + ..Default::default() + }) + .await + .unwrap(); + + ( + lobby_res.namespace_id.unwrap().as_uuid(), + lobby_res.lobby_id.unwrap().as_uuid(), + ) +} + +struct FindRequest { namespace_id: Uuid, players: Vec, query: mm::msg::lobby_find::message::Query, + user_id: Option, + verification_data_json: Option, + bypass_verification: bool, +} + +async fn find( + ctx: &TestCtx, + req: FindRequest, ) -> Result< chirp_client::message::ReceivedMessage, chirp_client::message::ReceivedMessage, > { let query_id = Uuid::new_v4(); - msg!([ctx] @notrace mm::msg::lobby_find(namespace_id, query_id) -> Result { - namespace_id: Some(namespace_id.into()), + msg!([ctx] @notrace mm::msg::lobby_find(req.namespace_id, query_id) -> Result { + namespace_id: Some(req.namespace_id.into()), query_id: Some(query_id.into()), join_kind: backend::matchmaker::query::JoinKind::Normal as i32, - players: players, - query: Some(query), + players: req.players, + query: Some(req.query), + + user_id: req.user_id.map(Into::into), + verification_data_json: req.verification_data_json, + bypass_verification: req.bypass_verification, }) .await .unwrap() diff --git a/svc/pkg/mm/worker/tests/player_register.rs b/svc/pkg/mm/worker/tests/player_register.rs index 9c539fc647..5ae27a108f 100644 --- a/svc/pkg/mm/worker/tests/player_register.rs +++ b/svc/pkg/mm/worker/tests/player_register.rs @@ -25,6 +25,7 @@ async fn empty(ctx: TestCtx) { query: Some(mm::msg::lobby_find::message::Query::Direct(backend::matchmaker::query::Direct { lobby_id: Some(lobby_id.into()), })), + ..Default::default() }) .await .unwrap().unwrap(); @@ -97,6 +98,7 @@ async fn wrong_lobby(ctx: TestCtx) { query: Some(mm::msg::lobby_find::message::Query::Direct(backend::matchmaker::query::Direct { lobby_id: Some(lobby_id.into()), })), + ..Default::default() }) .await .unwrap().unwrap(); diff --git a/svc/pkg/mm/worker/tests/player_remove.rs b/svc/pkg/mm/worker/tests/player_remove.rs index 983d920385..36f675aa57 100644 --- a/svc/pkg/mm/worker/tests/player_remove.rs +++ b/svc/pkg/mm/worker/tests/player_remove.rs @@ -34,6 +34,7 @@ async fn basic(ctx: TestCtx) { query: Some(mm::msg::lobby_find::message::Query::Direct(backend::matchmaker::query::Direct { lobby_id: Some(lobby_id.into()), })), + ..Default::default() }) .await .unwrap().unwrap(); diff --git a/svc/pkg/module/ops/game-version-get/Cargo.toml b/svc/pkg/module/ops/game-version-get/Cargo.toml index 75c4b96400..d34bcb0810 100644 --- a/svc/pkg/module/ops/game-version-get/Cargo.toml +++ b/svc/pkg/module/ops/game-version-get/Cargo.toml @@ -11,7 +11,7 @@ chirp-client = { path = "../../../../../lib/chirp/client" } prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/module/ops/game-version-publish/Cargo.toml b/svc/pkg/module/ops/game-version-publish/Cargo.toml index f66c938c6f..6247971b6a 100644 --- a/svc/pkg/module/ops/game-version-publish/Cargo.toml +++ b/svc/pkg/module/ops/game-version-publish/Cargo.toml @@ -13,7 +13,7 @@ unzip-n = "0.1.2" itertools = "0.10.5" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/module/ops/get/Cargo.toml b/svc/pkg/module/ops/get/Cargo.toml index a4b31a8bf2..411fc6a8cf 100644 --- a/svc/pkg/module/ops/get/Cargo.toml +++ b/svc/pkg/module/ops/get/Cargo.toml @@ -11,7 +11,7 @@ prost = "0.10" rivet-operation = { path = "../../../../../lib/operation/core" } [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/module/ops/instance-call/Cargo.toml b/svc/pkg/module/ops/instance-call/Cargo.toml index edb84d378c..f517394032 100644 --- a/svc/pkg/module/ops/instance-call/Cargo.toml +++ b/svc/pkg/module/ops/instance-call/Cargo.toml @@ -16,7 +16,7 @@ serde = { version = "1.0", features = ["derive"] } reqwest = { version = "0.11", features = ["json"] } [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/module/ops/instance-get/Cargo.toml b/svc/pkg/module/ops/instance-get/Cargo.toml index 2ab74c9491..25cce92fb6 100644 --- a/svc/pkg/module/ops/instance-get/Cargo.toml +++ b/svc/pkg/module/ops/instance-get/Cargo.toml @@ -11,7 +11,7 @@ prost = "0.10" rivet-operation = { path = "../../../../../lib/operation/core" } [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/module/ops/ns-instance-get/Cargo.toml b/svc/pkg/module/ops/ns-instance-get/Cargo.toml index 0cb0e13fc0..8b08930c34 100644 --- a/svc/pkg/module/ops/ns-instance-get/Cargo.toml +++ b/svc/pkg/module/ops/ns-instance-get/Cargo.toml @@ -11,7 +11,7 @@ prost = "0.10" rivet-operation = { path = "../../../../../lib/operation/core" } [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/module/ops/version-get/Cargo.toml b/svc/pkg/module/ops/version-get/Cargo.toml index e1c9fc8613..3e208ee6d3 100644 --- a/svc/pkg/module/ops/version-get/Cargo.toml +++ b/svc/pkg/module/ops/version-get/Cargo.toml @@ -13,7 +13,7 @@ rivet-operation = { path = "../../../../../lib/operation/core" } module-get = { path = "../get" } [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/module/worker/Cargo.toml b/svc/pkg/module/worker/Cargo.toml index 500082973a..7838139ff7 100644 --- a/svc/pkg/module/worker/Cargo.toml +++ b/svc/pkg/module/worker/Cargo.toml @@ -22,15 +22,14 @@ module-instance-get = { path = "../ops/instance-get" } module-game-version-get = { path = "../ops/game-version-get" } [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false features = [ - "runtime-tokio-native-tls", + "runtime-tokio", "postgres", "macros", "uuid", "json", - "tls", ] [dev-dependencies] diff --git a/svc/pkg/module/worker/Service.toml b/svc/pkg/module/worker/Service.toml index 67e38c5305..36e10767e5 100644 --- a/svc/pkg/module/worker/Service.toml +++ b/svc/pkg/module/worker/Service.toml @@ -7,4 +7,4 @@ kind = "rust" [consumer] [secrets] -"fly/auth_token" = {} +"fly/auth_token" = { optional = true } diff --git a/svc/pkg/module/worker/src/workers/create.rs b/svc/pkg/module/worker/src/workers/create.rs index a84120be3a..160b754413 100644 --- a/svc/pkg/module/worker/src/workers/create.rs +++ b/svc/pkg/module/worker/src/workers/create.rs @@ -3,7 +3,7 @@ use proto::backend::pkg::*; use serde_json::json; #[worker(name = "module-create")] -async fn worker(ctx: OperationContext) -> Result<(), GlobalError> { +async fn worker(ctx: &OperationContext) -> Result<(), GlobalError> { let crdb = ctx.crdb("db-module").await?; let module_id = internal_unwrap!(ctx.module_id).as_uuid(); diff --git a/svc/pkg/module/worker/src/workers/instance_create.rs b/svc/pkg/module/worker/src/workers/instance_create.rs index db3968a5f9..e68821acf0 100644 --- a/svc/pkg/module/worker/src/workers/instance_create.rs +++ b/svc/pkg/module/worker/src/workers/instance_create.rs @@ -94,7 +94,7 @@ struct CheckStatus { #[worker(name = "module-instance-create")] async fn worker( - ctx: OperationContext, + ctx: &OperationContext, ) -> Result<(), GlobalError> { let crdb = ctx.crdb("db-module").await?; @@ -196,7 +196,7 @@ async fn insert_instance( .bind(instance_id) .bind(version_id) .bind(now) - .execute(&mut *tx) + .execute(&mut **tx) .await?; match internal_unwrap!(msg.driver) { @@ -208,7 +208,7 @@ async fn insert_instance( " )) .bind(instance_id) - .execute(&mut *tx) + .execute(&mut **tx) .await?; } module::msg::instance_create::message::Driver::Fly(_) => { @@ -219,7 +219,7 @@ async fn insert_instance( " )) .bind(instance_id) - .execute(&mut *tx) + .execute(&mut **tx) .await?; } } diff --git a/svc/pkg/module/worker/src/workers/instance_destroy.rs b/svc/pkg/module/worker/src/workers/instance_destroy.rs index b7c97969ee..e15eb9b15b 100644 --- a/svc/pkg/module/worker/src/workers/instance_destroy.rs +++ b/svc/pkg/module/worker/src/workers/instance_destroy.rs @@ -3,7 +3,7 @@ use proto::backend::{self, pkg::*}; #[worker(name = "module-instance-destroy")] async fn worker( - ctx: OperationContext, + ctx: &OperationContext, ) -> Result<(), GlobalError> { let crdb = ctx.crdb("db-module").await?; diff --git a/svc/pkg/module/worker/src/workers/instance_version_set.rs b/svc/pkg/module/worker/src/workers/instance_version_set.rs index e9f4cdda3a..b80f49cc39 100644 --- a/svc/pkg/module/worker/src/workers/instance_version_set.rs +++ b/svc/pkg/module/worker/src/workers/instance_version_set.rs @@ -5,7 +5,7 @@ use serde_json::json; #[worker(name = "module-instance-version-set")] async fn worker( - ctx: OperationContext, + ctx: &OperationContext, ) -> Result<(), GlobalError> { let crdb = ctx.crdb("db-module").await?; diff --git a/svc/pkg/module/worker/src/workers/ns_version_set.rs b/svc/pkg/module/worker/src/workers/ns_version_set.rs index 30f14c5e79..9a89d1d5bd 100644 --- a/svc/pkg/module/worker/src/workers/ns_version_set.rs +++ b/svc/pkg/module/worker/src/workers/ns_version_set.rs @@ -19,7 +19,7 @@ struct NamespaceInstances { #[worker(name = "module-ns-version-set")] async fn worker( - ctx: OperationContext, + ctx: &OperationContext, ) -> Result<(), GlobalError> { let crdb = ctx.crdb("db-module").await?; @@ -33,10 +33,13 @@ async fn worker( version_ids: vec![version_id.into()], }) .await?; - let game_version = internal_unwrap_owned!(game_versions + let Some(game_version) = game_versions .versions .first() - .and_then(|x| x.config.as_ref())); + .and_then(|x| x.config.as_ref()) else { + tracing::info!("no game version found"); + return Ok(()); + }; let new_version_keys = game_version .dependencies diff --git a/svc/pkg/module/worker/src/workers/version_create.rs b/svc/pkg/module/worker/src/workers/version_create.rs index d6d2423cef..6d82e21fc6 100644 --- a/svc/pkg/module/worker/src/workers/version_create.rs +++ b/svc/pkg/module/worker/src/workers/version_create.rs @@ -5,7 +5,7 @@ use std::convert::TryInto; #[worker(name = "module-version-create")] async fn worker( - ctx: OperationContext, + ctx: &OperationContext, ) -> Result<(), GlobalError> { let crdb = ctx.crdb("db-module").await?; @@ -61,7 +61,7 @@ async fn update_db( .bind(TryInto::::try_into(msg.major)?) .bind(TryInto::::try_into(msg.minor)?) .bind(TryInto::::try_into(msg.patch)?) - .execute(&mut *tx) + .execute(&mut **tx) .await?; match internal_unwrap!(msg.image) { @@ -74,7 +74,7 @@ async fn update_db( )) .bind(version_id) .bind(&docker.image_tag) - .execute(&mut *tx) + .execute(&mut **tx) .await?; } } @@ -90,7 +90,7 @@ async fn update_db( .bind(&script.name) .bind(&script.request_schema) .bind(&script.response_schema) - .execute(&mut *tx) + .execute(&mut **tx) .await?; if script.callable.is_some() { @@ -102,7 +102,7 @@ async fn update_db( )) .bind(version_id) .bind(&script.name) - .execute(&mut *tx) + .execute(&mut **tx) .await?; } } diff --git a/svc/pkg/nomad-log/standalone/follower/Cargo.toml b/svc/pkg/nomad-log/standalone/follower/Cargo.toml index 8b1f47e06e..f5db65e106 100644 --- a/svc/pkg/nomad-log/standalone/follower/Cargo.toml +++ b/svc/pkg/nomad-log/standalone/follower/Cargo.toml @@ -22,7 +22,7 @@ rivet-pools = { path = "../../../../../lib/pools" } rivet-runtime = { path = "../../../../../lib/runtime" } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -tokio = { version = "1.21", features = ["full"] } +tokio = { version = "1.29", features = ["full"] } tracing = "0.1" tracing-subscriber = { version = "0.3", default-features = false, features = ["fmt", "json", "ansi"] } util-job = { package = "rivet-util-job", path = "../../../job/util" } diff --git a/svc/pkg/nomad-log/worker/src/workers/export.rs b/svc/pkg/nomad-log/worker/src/workers/export.rs index 971b0b697d..a3cce0269d 100644 --- a/svc/pkg/nomad-log/worker/src/workers/export.rs +++ b/svc/pkg/nomad-log/worker/src/workers/export.rs @@ -8,7 +8,7 @@ struct LogEntry { } #[worker(name = "nomad-log-export")] -async fn worker(ctx: OperationContext) -> GlobalResult<()> { +async fn worker(ctx: &OperationContext) -> GlobalResult<()> { let clickhouse = clickhouse::Client::default() .with_url("http://http.clickhouse.service.consul:8123") .with_user("chirp") diff --git a/svc/pkg/nomad-log/worker/src/workers/write.rs b/svc/pkg/nomad-log/worker/src/workers/write.rs index 0b41ad9c0d..17ff1cddf7 100644 --- a/svc/pkg/nomad-log/worker/src/workers/write.rs +++ b/svc/pkg/nomad-log/worker/src/workers/write.rs @@ -12,7 +12,7 @@ struct LogEntry<'a> { } #[worker(name = "nomad-log-write")] -async fn worker(ctx: OperationContext) -> GlobalResult<()> { +async fn worker(ctx: &OperationContext) -> GlobalResult<()> { let client = clickhouse::Client::default() .with_url("http://http.clickhouse.service.consul:8123") .with_user("chirp") diff --git a/svc/pkg/push-notification/worker/src/workers/send.rs b/svc/pkg/push-notification/worker/src/workers/send.rs index 29558df3fb..3ad465a604 100644 --- a/svc/pkg/push-notification/worker/src/workers/send.rs +++ b/svc/pkg/push-notification/worker/src/workers/send.rs @@ -13,7 +13,7 @@ struct NotificationData { #[worker(name = "push-notification-send")] async fn worker( - ctx: OperationContext, + ctx: &OperationContext, ) -> GlobalResult<()> { let user_id = internal_unwrap!(ctx.user_id).as_uuid(); let thread_id = internal_unwrap!(ctx.thread_id).as_uuid(); diff --git a/svc/pkg/region/ops/get/Cargo.toml b/svc/pkg/region/ops/get/Cargo.toml index b49c30c467..40db38d8a9 100644 --- a/svc/pkg/region/ops/get/Cargo.toml +++ b/svc/pkg/region/ops/get/Cargo.toml @@ -12,7 +12,7 @@ prost = "0.10" util-region = { package = "rivet-util-region", path = "../../util" } [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/region/ops/list/Cargo.toml b/svc/pkg/region/ops/list/Cargo.toml index 7832a3cfc2..bced1f244c 100644 --- a/svc/pkg/region/ops/list/Cargo.toml +++ b/svc/pkg/region/ops/list/Cargo.toml @@ -12,7 +12,7 @@ prost = "0.10" util-region = { package = "rivet-util-region", path = "../../util" } [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/region/ops/recommend/Cargo.toml b/svc/pkg/region/ops/recommend/Cargo.toml index f5206d92d1..4e404562a4 100644 --- a/svc/pkg/region/ops/recommend/Cargo.toml +++ b/svc/pkg/region/ops/recommend/Cargo.toml @@ -15,7 +15,7 @@ ip-info = { path = "../../../ip/ops/info" } region-get = { path = "../get" } [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/region/ops/resolve/Cargo.toml b/svc/pkg/region/ops/resolve/Cargo.toml index 3a88e14d30..fd5ad3ed92 100644 --- a/svc/pkg/region/ops/resolve/Cargo.toml +++ b/svc/pkg/region/ops/resolve/Cargo.toml @@ -12,7 +12,7 @@ prost = "0.10" util-region = { package = "rivet-util-region", path = "../../util" } [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/region/util/Cargo.toml b/svc/pkg/region/util/Cargo.toml index e2e4ed07f7..fbf58d6e40 100644 --- a/svc/pkg/region/util/Cargo.toml +++ b/svc/pkg/region/util/Cargo.toml @@ -8,5 +8,5 @@ license = "Apache-2.0" [dependencies] serde = { version = "1.0", features = ["derive"] } uuid = { version = "1", features = ["v4", "serde"] } -tokio = { version = "1.21", features = ["sync"] } +tokio = { version = "1.29", features = ["sync"] } serde_json = "1.0" diff --git a/svc/pkg/team-dev/ops/game-list/Cargo.toml b/svc/pkg/team-dev/ops/game-list/Cargo.toml index 1cf6674d22..d7befcd43f 100644 --- a/svc/pkg/team-dev/ops/game-list/Cargo.toml +++ b/svc/pkg/team-dev/ops/game-list/Cargo.toml @@ -11,7 +11,7 @@ chirp-client = { path = "../../../../../lib/chirp/client" } prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/team-dev/ops/get/Cargo.toml b/svc/pkg/team-dev/ops/get/Cargo.toml index 7fb6fecc06..ab92b162b0 100644 --- a/svc/pkg/team-dev/ops/get/Cargo.toml +++ b/svc/pkg/team-dev/ops/get/Cargo.toml @@ -11,7 +11,7 @@ chirp-client = { path = "../../../../../lib/chirp/client" } prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/team-dev/ops/halt/Cargo.toml b/svc/pkg/team-dev/ops/halt/Cargo.toml index 96ab475820..cad1eefa2c 100644 --- a/svc/pkg/team-dev/ops/halt/Cargo.toml +++ b/svc/pkg/team-dev/ops/halt/Cargo.toml @@ -14,7 +14,7 @@ mm-lobby-list-for-namespace = { path = "../../../mm/ops/lobby-list-for-namespace game-namespace-list = { path = "../../../game/ops/namespace-list" } [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/team-dev/standalone/halt-collect/Cargo.toml b/svc/pkg/team-dev/standalone/halt-collect/Cargo.toml index 413c74f026..6b69fac489 100644 --- a/svc/pkg/team-dev/standalone/halt-collect/Cargo.toml +++ b/svc/pkg/team-dev/standalone/halt-collect/Cargo.toml @@ -16,21 +16,19 @@ rivet-connection = { path = "../../../../../lib/connection" } chrono = "0.4" rivet-pools = { path = "../../../../../lib/pools" } rivet-runtime = { path = "../../../../../lib/runtime" } -tokio = { version = "1.21", features = ["full"] } +tokio = { version = "1.29", features = ["full"] } tracing = "0.1" tracing-subscriber = { version = "0.3", default-features = false, features = ["fmt", "json", "ansi"] } team-dev-halt = { path = "../../ops/halt" } [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false features = [ - "runtime-tokio-native-tls", "postgres", "uuid", "json", - "tls", "macros", ] diff --git a/svc/pkg/team-dev/worker/src/workers/create.rs b/svc/pkg/team-dev/worker/src/workers/create.rs index e7487ca13f..c423cf0a55 100644 --- a/svc/pkg/team-dev/worker/src/workers/create.rs +++ b/svc/pkg/team-dev/worker/src/workers/create.rs @@ -3,7 +3,7 @@ use proto::backend::{self, pkg::*}; use serde_json::json; #[worker(name = "team-dev-create")] -async fn worker(ctx: OperationContext) -> GlobalResult<()> { +async fn worker(ctx: &OperationContext) -> GlobalResult<()> { let team_id = internal_unwrap!(ctx.team_id).as_uuid(); // Get the team diff --git a/svc/pkg/team-dev/worker/src/workers/halt_team_dev_update.rs b/svc/pkg/team-dev/worker/src/workers/halt_team_dev_update.rs index c922306e32..8ec63a5d58 100644 --- a/svc/pkg/team-dev/worker/src/workers/halt_team_dev_update.rs +++ b/svc/pkg/team-dev/worker/src/workers/halt_team_dev_update.rs @@ -2,7 +2,7 @@ use chirp_worker::prelude::*; use proto::backend::{self, pkg::*}; #[worker(name = "team-dev-halt-team-dev-update")] -async fn worker(ctx: OperationContext) -> GlobalResult<()> { +async fn worker(ctx: &OperationContext) -> GlobalResult<()> { let team_id = internal_unwrap!(ctx.team_id).as_uuid(); let team_dev_res = op!([ctx] team_dev_get { diff --git a/svc/pkg/team-dev/worker/src/workers/status_update.rs b/svc/pkg/team-dev/worker/src/workers/status_update.rs index dc6053b950..be8e825db9 100644 --- a/svc/pkg/team-dev/worker/src/workers/status_update.rs +++ b/svc/pkg/team-dev/worker/src/workers/status_update.rs @@ -2,7 +2,7 @@ use chirp_worker::prelude::*; use proto::backend::pkg::*; #[worker(name = "team-dev-status-update")] -async fn worker(ctx: OperationContext) -> GlobalResult<()> { +async fn worker(ctx: &OperationContext) -> GlobalResult<()> { let team_id = if let Some(setup_complete) = ctx.setup_complete { let (team_id,) = sqlx::query_as::<_, (Uuid,)>(indoc!( " diff --git a/svc/pkg/team-invite/ops/get/Cargo.toml b/svc/pkg/team-invite/ops/get/Cargo.toml index 0db1fb3b23..447c6629b9 100644 --- a/svc/pkg/team-invite/ops/get/Cargo.toml +++ b/svc/pkg/team-invite/ops/get/Cargo.toml @@ -12,7 +12,7 @@ chrono = "0.4" prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/team-invite/worker/Cargo.toml b/svc/pkg/team-invite/worker/Cargo.toml index 948060affe..ef4ba13ffa 100644 --- a/svc/pkg/team-invite/worker/Cargo.toml +++ b/svc/pkg/team-invite/worker/Cargo.toml @@ -17,7 +17,7 @@ team-member-list = { path = "../../team/ops/member-list" } team-user-ban-get = { path = "../../team/ops/user-ban-get" } [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/team-invite/worker/src/workers/consume.rs b/svc/pkg/team-invite/worker/src/workers/consume.rs index 7c7acb5f9e..58fc4c10f5 100644 --- a/svc/pkg/team-invite/worker/src/workers/consume.rs +++ b/svc/pkg/team-invite/worker/src/workers/consume.rs @@ -12,7 +12,7 @@ struct InvitationRow { } #[worker(name = "team-invite-consume")] -async fn worker(ctx: OperationContext) -> GlobalResult<()> { +async fn worker(ctx: &OperationContext) -> GlobalResult<()> { let crdb = ctx.crdb("db-team-invite").await?; let user_id = internal_unwrap!(ctx.user_id).as_uuid(); @@ -111,7 +111,7 @@ async fn update_db( ", ) .bind(&code) - .fetch_optional(&mut *tx) + .fetch_optional(&mut **tx) .await?; let invitation_row = if let Some(invitation) = invitation_row { tracing::info!(?invitation, "found invitation"); @@ -188,13 +188,13 @@ async fn update_db( // Insert consumption sqlx::query("UPDATE invitations SET use_counter = use_counter + 1 WHERE code = $1") .bind(&code) - .execute(&mut *tx) + .execute(&mut **tx) .await?; sqlx::query("INSERT INTO invitation_uses (code, user_id, create_ts) VALUES ($1, $2, $3)") .bind(&code) .bind(user_id) .bind(now) - .execute(&mut *tx) + .execute(&mut **tx) .await?; Ok(DbOutput::Success { invitation_row }) diff --git a/svc/pkg/team-invite/worker/src/workers/create.rs b/svc/pkg/team-invite/worker/src/workers/create.rs index 9cefb94a54..9874e1ea7b 100644 --- a/svc/pkg/team-invite/worker/src/workers/create.rs +++ b/svc/pkg/team-invite/worker/src/workers/create.rs @@ -3,7 +3,7 @@ use proto::backend::pkg::*; use serde_json::json; #[worker(name = "team-invite-create")] -async fn worker(ctx: OperationContext) -> GlobalResult<()> { +async fn worker(ctx: &OperationContext) -> GlobalResult<()> { let crdb = ctx.crdb("db-team-invite").await?; let team_id = internal_unwrap!(ctx.team_id).as_uuid(); diff --git a/svc/pkg/team/ops/avatar-upload-complete/Cargo.toml b/svc/pkg/team/ops/avatar-upload-complete/Cargo.toml index 64f50d8359..e7f69ccbb7 100644 --- a/svc/pkg/team/ops/avatar-upload-complete/Cargo.toml +++ b/svc/pkg/team/ops/avatar-upload-complete/Cargo.toml @@ -13,7 +13,7 @@ prost = "0.10" upload-complete = { path = "../../../upload/ops/complete" } [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/team/ops/get/Cargo.toml b/svc/pkg/team/ops/get/Cargo.toml index a01438c969..6f297432cc 100644 --- a/svc/pkg/team/ops/get/Cargo.toml +++ b/svc/pkg/team/ops/get/Cargo.toml @@ -14,7 +14,7 @@ upload-file-list = { path = "../../../upload/ops/file-list" } upload-get = { path = "../../../upload/ops/get" } [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/team/ops/join-request-list/Cargo.toml b/svc/pkg/team/ops/join-request-list/Cargo.toml index 5ad23c13d4..4c650cfb07 100644 --- a/svc/pkg/team/ops/join-request-list/Cargo.toml +++ b/svc/pkg/team/ops/join-request-list/Cargo.toml @@ -11,7 +11,7 @@ chirp-client = { path = "../../../../../lib/chirp/client" } prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/team/ops/member-count/Cargo.toml b/svc/pkg/team/ops/member-count/Cargo.toml index 6630d66f9e..4146ef167c 100644 --- a/svc/pkg/team/ops/member-count/Cargo.toml +++ b/svc/pkg/team/ops/member-count/Cargo.toml @@ -11,7 +11,7 @@ chirp-client = { path = "../../../../../lib/chirp/client" } prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/team/ops/member-get/Cargo.toml b/svc/pkg/team/ops/member-get/Cargo.toml index 6e1f864616..3ce19b0550 100644 --- a/svc/pkg/team/ops/member-get/Cargo.toml +++ b/svc/pkg/team/ops/member-get/Cargo.toml @@ -11,7 +11,7 @@ chirp-client = { path = "../../../../../lib/chirp/client" } prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/team/ops/member-list/Cargo.toml b/svc/pkg/team/ops/member-list/Cargo.toml index e519d638a1..5067e3f5c1 100644 --- a/svc/pkg/team/ops/member-list/Cargo.toml +++ b/svc/pkg/team/ops/member-list/Cargo.toml @@ -11,7 +11,7 @@ chirp-client = { path = "../../../../../lib/chirp/client" } prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/team/ops/profile-validate/Cargo.toml b/svc/pkg/team/ops/profile-validate/Cargo.toml index 7aa30240ac..45c6282462 100644 --- a/svc/pkg/team/ops/profile-validate/Cargo.toml +++ b/svc/pkg/team/ops/profile-validate/Cargo.toml @@ -11,7 +11,7 @@ chirp-client = { path = "../../../../../lib/chirp/client" } prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/team/ops/recommend/Cargo.toml b/svc/pkg/team/ops/recommend/Cargo.toml index d754d931a0..9ec1520972 100644 --- a/svc/pkg/team/ops/recommend/Cargo.toml +++ b/svc/pkg/team/ops/recommend/Cargo.toml @@ -11,7 +11,7 @@ chirp-client = { path = "../../../../../lib/chirp/client" } prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/team/ops/resolve-display-name/Cargo.toml b/svc/pkg/team/ops/resolve-display-name/Cargo.toml index 13e70c1922..514534e47d 100644 --- a/svc/pkg/team/ops/resolve-display-name/Cargo.toml +++ b/svc/pkg/team/ops/resolve-display-name/Cargo.toml @@ -11,7 +11,7 @@ chirp-client = { path = "../../../../../lib/chirp/client" } prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/team/ops/search/Cargo.toml b/svc/pkg/team/ops/search/Cargo.toml index 0f12433c84..3307ff84ac 100644 --- a/svc/pkg/team/ops/search/Cargo.toml +++ b/svc/pkg/team/ops/search/Cargo.toml @@ -13,7 +13,7 @@ lazy_static = "1.4" regex = "1.4" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/team/ops/user-ban-get/Cargo.toml b/svc/pkg/team/ops/user-ban-get/Cargo.toml index 334301676a..33496d6b2b 100644 --- a/svc/pkg/team/ops/user-ban-get/Cargo.toml +++ b/svc/pkg/team/ops/user-ban-get/Cargo.toml @@ -11,7 +11,7 @@ chirp-client = { path = "../../../../../lib/chirp/client" } prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/team/ops/user-ban-list/Cargo.toml b/svc/pkg/team/ops/user-ban-list/Cargo.toml index 2108b01c8a..eed6d77042 100644 --- a/svc/pkg/team/ops/user-ban-list/Cargo.toml +++ b/svc/pkg/team/ops/user-ban-list/Cargo.toml @@ -11,7 +11,7 @@ chirp-client = { path = "../../../../../lib/chirp/client" } prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/team/standalone/billing-collect/Cargo.toml b/svc/pkg/team/standalone/billing-collect/Cargo.toml index 5c068e9bcc..faf28b3aed 100644 --- a/svc/pkg/team/standalone/billing-collect/Cargo.toml +++ b/svc/pkg/team/standalone/billing-collect/Cargo.toml @@ -15,7 +15,7 @@ rivet-connection = { path = "../../../../../lib/connection" } chrono = "0.4" rivet-pools = { path = "../../../../../lib/pools" } rivet-runtime = { path = "../../../../../lib/runtime" } -tokio = { version = "1.21", features = ["full"] } +tokio = { version = "1.29", features = ["full"] } tracing = "0.1" tracing-subscriber = { version = "0.3", default-features = false, features = ["fmt", "json", "ansi"] } @@ -23,14 +23,12 @@ game-get = { path = "../../../game/ops/get" } team-billing-aggregate = { path = "../../ops/billing-aggregate" } [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false features = [ - "runtime-tokio-native-tls", "postgres", "uuid", "json", - "tls", "macros", ] diff --git a/svc/pkg/team/worker/src/workers/create.rs b/svc/pkg/team/worker/src/workers/create.rs index e03e6e40b3..18bb4e4832 100644 --- a/svc/pkg/team/worker/src/workers/create.rs +++ b/svc/pkg/team/worker/src/workers/create.rs @@ -3,7 +3,7 @@ use proto::backend::pkg::*; use serde_json::json; #[worker(name = "team-create")] -async fn worker(ctx: OperationContext) -> GlobalResult<()> { +async fn worker(ctx: &OperationContext) -> GlobalResult<()> { let team_id = internal_unwrap!(ctx.team_id).as_uuid(); // Validate team diff --git a/svc/pkg/team/worker/src/workers/create_complete_chat_message_create.rs b/svc/pkg/team/worker/src/workers/create_complete_chat_message_create.rs index 1762dee94b..7da040082c 100644 --- a/svc/pkg/team/worker/src/workers/create_complete_chat_message_create.rs +++ b/svc/pkg/team/worker/src/workers/create_complete_chat_message_create.rs @@ -2,7 +2,7 @@ use chirp_worker::prelude::*; use proto::backend::{self, pkg::*}; #[worker(name = "team-create-complete-chat-message-create")] -async fn worker(ctx: OperationContext) -> GlobalResult<()> { +async fn worker(ctx: &OperationContext) -> GlobalResult<()> { // Create new chat with team op!([ctx] chat_message_create_with_topic { chat_message_id: Some(Uuid::new_v4().into()), diff --git a/svc/pkg/team/worker/src/workers/join_request_create.rs b/svc/pkg/team/worker/src/workers/join_request_create.rs index 03432d65a1..9de8d70b5b 100644 --- a/svc/pkg/team/worker/src/workers/join_request_create.rs +++ b/svc/pkg/team/worker/src/workers/join_request_create.rs @@ -35,7 +35,7 @@ async fn fail( #[worker(name = "team-join-request-create")] async fn worker( - ctx: OperationContext, + ctx: &OperationContext, ) -> GlobalResult<()> { let crdb = ctx.crdb("db-team").await?; let team_id: Uuid = internal_unwrap!(ctx.team_id).as_uuid(); diff --git a/svc/pkg/team/worker/src/workers/join_request_resolve.rs b/svc/pkg/team/worker/src/workers/join_request_resolve.rs index 917d1d53e5..aa8c51e8a3 100644 --- a/svc/pkg/team/worker/src/workers/join_request_resolve.rs +++ b/svc/pkg/team/worker/src/workers/join_request_resolve.rs @@ -4,7 +4,7 @@ use serde_json::json; #[worker(name = "team-join-request-resolve")] async fn worker( - ctx: OperationContext, + ctx: &OperationContext, ) -> GlobalResult<()> { let team_id: Uuid = internal_unwrap!(ctx.team_id).as_uuid(); let user_id: Uuid = internal_unwrap!(ctx.user_id).as_uuid(); diff --git a/svc/pkg/team/worker/src/workers/member_create.rs b/svc/pkg/team/worker/src/workers/member_create.rs index b0fa627464..eb74ab09c2 100644 --- a/svc/pkg/team/worker/src/workers/member_create.rs +++ b/svc/pkg/team/worker/src/workers/member_create.rs @@ -5,7 +5,7 @@ use serde_json::json; const MAX_TEAM_SIZE: i64 = 256; #[worker(name = "team-member-create")] -async fn worker(ctx: OperationContext) -> GlobalResult<()> { +async fn worker(ctx: &OperationContext) -> GlobalResult<()> { // Idempotent let team_id: Uuid = internal_unwrap!(ctx.team_id).as_uuid(); diff --git a/svc/pkg/team/worker/src/workers/member_kick.rs b/svc/pkg/team/worker/src/workers/member_kick.rs index 6ab04e055f..bd49283a51 100644 --- a/svc/pkg/team/worker/src/workers/member_kick.rs +++ b/svc/pkg/team/worker/src/workers/member_kick.rs @@ -3,7 +3,7 @@ use proto::backend::{self, pkg::*}; use serde_json::json; #[worker(name = "team-member-kick")] -async fn worker(ctx: OperationContext) -> GlobalResult<()> { +async fn worker(ctx: &OperationContext) -> GlobalResult<()> { let team_id = internal_unwrap!(ctx.team_id).as_uuid(); let user_id = internal_unwrap!(ctx.user_id).as_uuid(); diff --git a/svc/pkg/team/worker/src/workers/member_remove.rs b/svc/pkg/team/worker/src/workers/member_remove.rs index 393cab500e..cf09153995 100644 --- a/svc/pkg/team/worker/src/workers/member_remove.rs +++ b/svc/pkg/team/worker/src/workers/member_remove.rs @@ -3,7 +3,7 @@ use proto::backend::{self, pkg::*}; use serde_json::json; #[worker(name = "team-member-remove")] -async fn worker(ctx: OperationContext) -> GlobalResult<()> { +async fn worker(ctx: &OperationContext) -> GlobalResult<()> { let team_id: Uuid = internal_unwrap!(ctx.team_id).as_uuid(); let user_id: Uuid = internal_unwrap!(ctx.user_id).as_uuid(); diff --git a/svc/pkg/team/worker/src/workers/owner_transfer.rs b/svc/pkg/team/worker/src/workers/owner_transfer.rs index cdae782249..e0617c20bd 100644 --- a/svc/pkg/team/worker/src/workers/owner_transfer.rs +++ b/svc/pkg/team/worker/src/workers/owner_transfer.rs @@ -3,7 +3,7 @@ use proto::backend::{self, pkg::*}; use serde_json::json; #[worker(name = "team-owner-transfer")] -async fn worker(ctx: OperationContext) -> GlobalResult<()> { +async fn worker(ctx: &OperationContext) -> GlobalResult<()> { let raw_team_id = internal_unwrap!(ctx.team_id); let team_id = raw_team_id.as_uuid(); let new_owner_user_id = internal_unwrap!(ctx.new_owner_user_id).as_uuid(); diff --git a/svc/pkg/team/worker/src/workers/profile_set.rs b/svc/pkg/team/worker/src/workers/profile_set.rs index 2c9720b664..fd51db1cc9 100644 --- a/svc/pkg/team/worker/src/workers/profile_set.rs +++ b/svc/pkg/team/worker/src/workers/profile_set.rs @@ -4,7 +4,7 @@ use proto::backend::{self, pkg::*}; use serde_json::json; #[worker(name = "team-profile-set")] -async fn worker(ctx: OperationContext) -> GlobalResult<()> { +async fn worker(ctx: &OperationContext) -> GlobalResult<()> { let team::msg::profile_set::Message { team_id, display_name, diff --git a/svc/pkg/team/worker/src/workers/user_ban.rs b/svc/pkg/team/worker/src/workers/user_ban.rs index 6c83fb6a63..430ac267ef 100644 --- a/svc/pkg/team/worker/src/workers/user_ban.rs +++ b/svc/pkg/team/worker/src/workers/user_ban.rs @@ -3,7 +3,7 @@ use proto::backend::{self, pkg::*}; use serde_json::json; #[worker(name = "team-user-ban")] -async fn worker(ctx: OperationContext) -> GlobalResult<()> { +async fn worker(ctx: &OperationContext) -> GlobalResult<()> { let team_id = internal_unwrap!(ctx.team_id).as_uuid(); let user_id = internal_unwrap!(ctx.user_id).as_uuid(); diff --git a/svc/pkg/team/worker/src/workers/user_unban.rs b/svc/pkg/team/worker/src/workers/user_unban.rs index 212df1383d..041b7a3f3a 100644 --- a/svc/pkg/team/worker/src/workers/user_unban.rs +++ b/svc/pkg/team/worker/src/workers/user_unban.rs @@ -3,7 +3,7 @@ use proto::backend::pkg::*; use serde_json::json; #[worker(name = "team-user-unban")] -async fn worker(ctx: OperationContext) -> GlobalResult<()> { +async fn worker(ctx: &OperationContext) -> GlobalResult<()> { let team_id = internal_unwrap!(ctx.team_id).as_uuid(); let user_id = internal_unwrap!(ctx.user_id).as_uuid(); diff --git a/svc/pkg/telemetry/standalone/beacon/Cargo.toml b/svc/pkg/telemetry/standalone/beacon/Cargo.toml index e76b60e0d8..0d68ffde62 100644 --- a/svc/pkg/telemetry/standalone/beacon/Cargo.toml +++ b/svc/pkg/telemetry/standalone/beacon/Cargo.toml @@ -16,7 +16,7 @@ rivet-connection = { path = "../../../../../lib/connection" } rivet-operation = { path = "../../../../../lib/operation/core" } rivet-pools = { path = "../../../../../lib/pools" } rivet-runtime = { path = "../../../../../lib/runtime" } -tokio = { version = "1.21", features = ["full"] } +tokio = { version = "1.29", features = ["full"] } tracing = "0.1" tracing-subscriber = { version = "0.3", default-features = false, features = ["fmt", "json", "ansi"] } @@ -29,7 +29,7 @@ team-get = { path = "../../../team/ops/get" } team-member-count = { path = "../../../team/ops/member-count" } [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/token/ops/create/Cargo.toml b/svc/pkg/token/ops/create/Cargo.toml index 6946964b99..d4770d2872 100644 --- a/svc/pkg/token/ops/create/Cargo.toml +++ b/svc/pkg/token/ops/create/Cargo.toml @@ -16,7 +16,7 @@ jsonwebtoken = "8.2.0" lazy_static = "1.4" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/token/ops/exchange/Cargo.toml b/svc/pkg/token/ops/exchange/Cargo.toml index fdea99362f..76c14c120e 100644 --- a/svc/pkg/token/ops/exchange/Cargo.toml +++ b/svc/pkg/token/ops/exchange/Cargo.toml @@ -12,7 +12,7 @@ chrono = "0.4" prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false diff --git a/svc/pkg/token/ops/get/Cargo.toml b/svc/pkg/token/ops/get/Cargo.toml index ee285ffdf8..3bf9f18b04 100644 --- a/svc/pkg/token/ops/get/Cargo.toml +++ b/svc/pkg/token/ops/get/Cargo.toml @@ -12,7 +12,7 @@ chrono = "0.4" prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/token/ops/revoke/Cargo.toml b/svc/pkg/token/ops/revoke/Cargo.toml index ba2ff26780..e58f206ba7 100644 --- a/svc/pkg/token/ops/revoke/Cargo.toml +++ b/svc/pkg/token/ops/revoke/Cargo.toml @@ -12,7 +12,7 @@ chrono = "0.4" prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/upload/ops/complete/Cargo.toml b/svc/pkg/upload/ops/complete/Cargo.toml index 12f80d085d..ae42fe8886 100644 --- a/svc/pkg/upload/ops/complete/Cargo.toml +++ b/svc/pkg/upload/ops/complete/Cargo.toml @@ -16,7 +16,7 @@ url = "2.2" nsfw-image-score = { path = "../../../nsfw/ops/image-score" } [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/upload/ops/file-list/Cargo.toml b/svc/pkg/upload/ops/file-list/Cargo.toml index 753e73fc5e..d3e82e24fe 100644 --- a/svc/pkg/upload/ops/file-list/Cargo.toml +++ b/svc/pkg/upload/ops/file-list/Cargo.toml @@ -12,7 +12,7 @@ prost = "0.10" rivet-operation = { path = "../../../../../lib/operation/core" } [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/upload/ops/get/Cargo.toml b/svc/pkg/upload/ops/get/Cargo.toml index 713509d86f..0214a08afc 100644 --- a/svc/pkg/upload/ops/get/Cargo.toml +++ b/svc/pkg/upload/ops/get/Cargo.toml @@ -12,7 +12,7 @@ chrono = "0.4" prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/upload/ops/list-for-user/Cargo.toml b/svc/pkg/upload/ops/list-for-user/Cargo.toml index a1dcb7ee7c..0776b37550 100644 --- a/svc/pkg/upload/ops/list-for-user/Cargo.toml +++ b/svc/pkg/upload/ops/list-for-user/Cargo.toml @@ -12,7 +12,7 @@ chrono = "0.4" prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/upload/ops/prepare/Cargo.toml b/svc/pkg/upload/ops/prepare/Cargo.toml index 3cc57144ba..f5579967c5 100644 --- a/svc/pkg/upload/ops/prepare/Cargo.toml +++ b/svc/pkg/upload/ops/prepare/Cargo.toml @@ -13,7 +13,7 @@ prost = "0.10" s3-util = { path = "../../../../../lib/s3-util" } [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/upload/standalone/provider-fill/Cargo.toml b/svc/pkg/upload/standalone/provider-fill/Cargo.toml index 32be469eca..41497aac98 100644 --- a/svc/pkg/upload/standalone/provider-fill/Cargo.toml +++ b/svc/pkg/upload/standalone/provider-fill/Cargo.toml @@ -15,19 +15,18 @@ rivet-connection = { path = "../../../../../lib/connection" } rivet-operation = { path = "../../../../../lib/operation/core" } rivet-pools = { path = "../../../../../lib/pools" } s3-util = { path = "../../../../../lib/s3-util" } -tokio = { version = "1.21", features = ["full"] } +tokio = { version = "1.29", features = ["full"] } tracing = "0.1" tracing-subscriber = { version = "0.3", default-features = false, features = ["fmt", "json", "ansi"] } [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false features = [ - "runtime-tokio-native-tls", + "runtime-tokio", "postgres", "uuid", "json", - "tls", ] [dev-dependencies] diff --git a/svc/pkg/upload/worker/Cargo.toml b/svc/pkg/upload/worker/Cargo.toml index fba60abe1e..72426aab80 100644 --- a/svc/pkg/upload/worker/Cargo.toml +++ b/svc/pkg/upload/worker/Cargo.toml @@ -14,7 +14,7 @@ rivet-runtime = { path = "../../../../lib/runtime" } s3-util = { path = "../../../../lib/s3-util" } [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/upload/worker/src/workers/delete.rs b/svc/pkg/upload/worker/src/workers/delete.rs index b767ba7a93..239567dca9 100644 --- a/svc/pkg/upload/worker/src/workers/delete.rs +++ b/svc/pkg/upload/worker/src/workers/delete.rs @@ -23,7 +23,7 @@ struct BucketDeletions { } #[worker(name = "upload-delete")] -async fn worker(ctx: OperationContext) -> GlobalResult<()> { +async fn worker(ctx: &OperationContext) -> GlobalResult<()> { let crdb = ctx.crdb("db-upload").await?; let request_id = internal_unwrap!(ctx.request_id).as_uuid(); diff --git a/svc/pkg/user-dev/worker/src/workers/game_update.rs b/svc/pkg/user-dev/worker/src/workers/game_update.rs index e3cdb7ed6b..45e30c0784 100644 --- a/svc/pkg/user-dev/worker/src/workers/game_update.rs +++ b/svc/pkg/user-dev/worker/src/workers/game_update.rs @@ -6,7 +6,7 @@ use futures_util::{ use proto::backend::pkg::*; #[worker(name = "user-dev-game-update")] -async fn worker(ctx: OperationContext) -> GlobalResult<()> { +async fn worker(ctx: &OperationContext) -> GlobalResult<()> { let game_id = internal_unwrap!(ctx.game_id).as_uuid(); let game_res = op!([ctx] game_get { diff --git a/svc/pkg/user-follow/ops/count/Cargo.toml b/svc/pkg/user-follow/ops/count/Cargo.toml index 42a26dd34a..b2ef3ca729 100644 --- a/svc/pkg/user-follow/ops/count/Cargo.toml +++ b/svc/pkg/user-follow/ops/count/Cargo.toml @@ -11,7 +11,7 @@ chirp-client = { path = "../../../../../lib/chirp/client" } prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/user-follow/ops/get/Cargo.toml b/svc/pkg/user-follow/ops/get/Cargo.toml index 487c68db13..9c7bae4970 100644 --- a/svc/pkg/user-follow/ops/get/Cargo.toml +++ b/svc/pkg/user-follow/ops/get/Cargo.toml @@ -11,7 +11,7 @@ chirp-client = { path = "../../../../../lib/chirp/client" } prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/user-follow/ops/list/Cargo.toml b/svc/pkg/user-follow/ops/list/Cargo.toml index 3db4d51f8f..42fa219363 100644 --- a/svc/pkg/user-follow/ops/list/Cargo.toml +++ b/svc/pkg/user-follow/ops/list/Cargo.toml @@ -11,7 +11,7 @@ chirp-client = { path = "../../../../../lib/chirp/client" } prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/user-follow/ops/relationship-get/Cargo.toml b/svc/pkg/user-follow/ops/relationship-get/Cargo.toml index f448945b02..d2b31b5986 100644 --- a/svc/pkg/user-follow/ops/relationship-get/Cargo.toml +++ b/svc/pkg/user-follow/ops/relationship-get/Cargo.toml @@ -11,7 +11,7 @@ chirp-client = { path = "../../../../../lib/chirp/client" } prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/user-follow/ops/request-list/Cargo.toml b/svc/pkg/user-follow/ops/request-list/Cargo.toml index 3258dc328f..5a4d372972 100644 --- a/svc/pkg/user-follow/ops/request-list/Cargo.toml +++ b/svc/pkg/user-follow/ops/request-list/Cargo.toml @@ -11,7 +11,7 @@ chirp-client = { path = "../../../../../lib/chirp/client" } prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/user-follow/ops/toggle/Cargo.toml b/svc/pkg/user-follow/ops/toggle/Cargo.toml index 3049ed814d..a82e08aab0 100644 --- a/svc/pkg/user-follow/ops/toggle/Cargo.toml +++ b/svc/pkg/user-follow/ops/toggle/Cargo.toml @@ -11,7 +11,7 @@ chirp-client = { path = "../../../../../lib/chirp/client" } prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/user-follow/worker/src/workers/request_ignore.rs b/svc/pkg/user-follow/worker/src/workers/request_ignore.rs index 440c3c312f..491d4b62f4 100644 --- a/svc/pkg/user-follow/worker/src/workers/request_ignore.rs +++ b/svc/pkg/user-follow/worker/src/workers/request_ignore.rs @@ -3,7 +3,7 @@ use proto::backend::pkg::*; #[worker(name = "user-follow-request-ignore")] async fn worker( - ctx: OperationContext, + ctx: &OperationContext, ) -> GlobalResult<()> { let follower_user_id = internal_unwrap!(ctx.follower_user_id).as_uuid(); let following_user_id = internal_unwrap!(ctx.following_user_id).as_uuid(); diff --git a/svc/pkg/user-identity/ops/create/tests/integration.rs b/svc/pkg/user-identity/ops/create/tests/integration.rs index 5b691c78c9..5609d5c0d5 100644 --- a/svc/pkg/user-identity/ops/create/tests/integration.rs +++ b/svc/pkg/user-identity/ops/create/tests/integration.rs @@ -15,7 +15,7 @@ async fn empty(ctx: TestCtx) { identity: Some(backend::user_identity::Identity { kind: Some(backend::user_identity::identity::Kind::Email( backend::user_identity::identity::Email { - email: email.clone() + email: email.clone(), } )), }), diff --git a/svc/pkg/user-identity/ops/delete/Cargo.toml b/svc/pkg/user-identity/ops/delete/Cargo.toml index 45efce3532..2abbb93fce 100644 --- a/svc/pkg/user-identity/ops/delete/Cargo.toml +++ b/svc/pkg/user-identity/ops/delete/Cargo.toml @@ -11,7 +11,7 @@ chirp-client = { path = "../../../../../lib/chirp/client" } prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/user-identity/ops/get/Cargo.toml b/svc/pkg/user-identity/ops/get/Cargo.toml index e131f3d9ce..70eb42b195 100644 --- a/svc/pkg/user-identity/ops/get/Cargo.toml +++ b/svc/pkg/user-identity/ops/get/Cargo.toml @@ -11,7 +11,7 @@ chirp-client = { path = "../../../../../lib/chirp/client" } prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/user-notification-auth/ops/register/Cargo.toml b/svc/pkg/user-notification-auth/ops/register/Cargo.toml index a2ca68ddcf..1274b0313f 100644 --- a/svc/pkg/user-notification-auth/ops/register/Cargo.toml +++ b/svc/pkg/user-notification-auth/ops/register/Cargo.toml @@ -11,7 +11,7 @@ chirp-client = { path = "../../../../../lib/chirp/client" } prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/user-notification-auth/ops/unregister/Cargo.toml b/svc/pkg/user-notification-auth/ops/unregister/Cargo.toml index 856e25f424..8565a4b192 100644 --- a/svc/pkg/user-notification-auth/ops/unregister/Cargo.toml +++ b/svc/pkg/user-notification-auth/ops/unregister/Cargo.toml @@ -11,7 +11,7 @@ chirp-client = { path = "../../../../../lib/chirp/client" } prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/user-presence/db/redis-user-presence/Service.toml b/svc/pkg/user-presence/db/redis-user-presence/Service.toml index 9e1c930cb5..b8039e7266 100644 --- a/svc/pkg/user-presence/db/redis-user-presence/Service.toml +++ b/svc/pkg/user-presence/db/redis-user-presence/Service.toml @@ -3,7 +3,7 @@ name = "redis-user-presence" [runtime] kind = "redis" -index = 6 +index = 5 persistent = true [cache] diff --git a/svc/pkg/user-presence/standalone/gc/Cargo.toml b/svc/pkg/user-presence/standalone/gc/Cargo.toml index 9454a09c61..30d7747f6c 100644 --- a/svc/pkg/user-presence/standalone/gc/Cargo.toml +++ b/svc/pkg/user-presence/standalone/gc/Cargo.toml @@ -17,7 +17,7 @@ rivet-metrics = { path = "../../../../../lib/metrics" } rivet-operation = { path = "../../../../../lib/operation/core" } rivet-pools = { path = "../../../../../lib/pools" } rivet-runtime = { path = "../../../../../lib/runtime" } -tokio = { version = "1.21", features = ["full"] } +tokio = { version = "1.29", features = ["full"] } tracing = "0.1" tracing-subscriber = { version = "0.3", default-features = false, features = ["fmt", "json", "ansi"] } util-user-presence = { package = "rivet-util-user-presence", path = "../../util" } diff --git a/svc/pkg/user-presence/worker/Cargo.toml b/svc/pkg/user-presence/worker/Cargo.toml index 0b08a6374f..ec920fa6d3 100644 --- a/svc/pkg/user-presence/worker/Cargo.toml +++ b/svc/pkg/user-presence/worker/Cargo.toml @@ -14,7 +14,7 @@ rivet-runtime = { path = "../../../../lib/runtime" } util-user-presence = { package = "rivet-util-user-presence", path = "../util" } [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/user-presence/worker/src/workers/arrive.rs b/svc/pkg/user-presence/worker/src/workers/arrive.rs index bbf18e54fd..e6ff4c76c3 100644 --- a/svc/pkg/user-presence/worker/src/workers/arrive.rs +++ b/svc/pkg/user-presence/worker/src/workers/arrive.rs @@ -4,7 +4,7 @@ use proto::backend::{self, pkg::*}; const DEFAULT_USER_SET_STATUS: i32 = backend::user::Status::Online as i32; #[worker(name = "user-presence-arrive")] -async fn worker(ctx: OperationContext) -> GlobalResult<()> { +async fn worker(ctx: &OperationContext) -> GlobalResult<()> { let crdb = ctx.crdb("db-user-presence").await?; let user_id = internal_unwrap!(ctx.user_id).as_uuid(); diff --git a/svc/pkg/user-presence/worker/src/workers/game_activity_set.rs b/svc/pkg/user-presence/worker/src/workers/game_activity_set.rs index f659849a48..01586c4184 100644 --- a/svc/pkg/user-presence/worker/src/workers/game_activity_set.rs +++ b/svc/pkg/user-presence/worker/src/workers/game_activity_set.rs @@ -4,7 +4,7 @@ use redis::AsyncCommands; #[worker(name = "user-presence-game-activity-set")] async fn worker( - ctx: OperationContext, + ctx: &OperationContext, ) -> GlobalResult<()> { let mut redis = ctx.redis_user_presence().await?; diff --git a/svc/pkg/user-presence/worker/src/workers/leave.rs b/svc/pkg/user-presence/worker/src/workers/leave.rs index b3605f48a2..cf92295f7d 100644 --- a/svc/pkg/user-presence/worker/src/workers/leave.rs +++ b/svc/pkg/user-presence/worker/src/workers/leave.rs @@ -5,20 +5,22 @@ use redis::AsyncCommands; const DEFAULT_USER_SET_STATUS: i32 = backend::user::Status::Online as i32; #[worker(name = "user-presence-leave")] -async fn worker(ctx: OperationContext) -> GlobalResult<()> { +async fn worker(ctx: &OperationContext) -> GlobalResult<()> { let crdb = ctx.crdb("db-user-presence").await?; let mut redis = ctx.redis_user_presence().await?; let user_id = internal_unwrap!(ctx.user_id).as_uuid(); - let user_set_status = - sqlx::query_as::<_, (Option,)>("SELECT user_set_status FROM user_presences") - .fetch_optional(&crdb) - .await? - .and_then(|x| x.0) - .map(|x| x as i32) - .unwrap_or(DEFAULT_USER_SET_STATUS); + let user_set_status = sqlx::query_as::<_, (Option,)>( + "SELECT user_set_status FROM user_presences WHERE user_id = $1", + ) + .bind(user_id) + .fetch_optional(&crdb) + .await? + .and_then(|x| x.0) + .map(|x| x as i32) + .unwrap_or(DEFAULT_USER_SET_STATUS); // Remove the user from Redis. // diff --git a/svc/pkg/user-presence/worker/src/workers/status_set.rs b/svc/pkg/user-presence/worker/src/workers/status_set.rs index 1eb6ab0e0c..1640a9c3c7 100644 --- a/svc/pkg/user-presence/worker/src/workers/status_set.rs +++ b/svc/pkg/user-presence/worker/src/workers/status_set.rs @@ -10,7 +10,7 @@ enum Error { #[worker(name = "user-presence-status-set")] async fn worker( - ctx: OperationContext, + ctx: &OperationContext, ) -> GlobalResult<()> { let crdb = ctx.crdb("db-user-presence").await?; diff --git a/svc/pkg/user-report/worker/src/workers/create.rs b/svc/pkg/user-report/worker/src/workers/create.rs index c0d9f5c6ca..9a87320c01 100644 --- a/svc/pkg/user-report/worker/src/workers/create.rs +++ b/svc/pkg/user-report/worker/src/workers/create.rs @@ -2,7 +2,7 @@ use chirp_worker::prelude::*; use proto::backend::pkg::*; #[worker(name = "user-report-create")] -async fn worker(ctx: OperationContext) -> GlobalResult<()> { +async fn worker(ctx: &OperationContext) -> GlobalResult<()> { let reporter_user_id = internal_unwrap!(ctx.reporter_user_id).as_uuid(); let subject_user_id = internal_unwrap!(ctx.subject_user_id).as_uuid(); let namespace_id = ctx.subject_user_id.as_ref().map(common::Uuid::as_uuid); diff --git a/svc/pkg/user/db/user/migrations/20230515194135_search.up.sql b/svc/pkg/user/db/user/migrations/20230515194135_search.up.sql index 2464a763f8..d7e05c69b5 100644 --- a/svc/pkg/user/db/user/migrations/20230515194135_search.up.sql +++ b/svc/pkg/user/db/user/migrations/20230515194135_search.up.sql @@ -1,3 +1,3 @@ ALTER TABLE users - ADD COLUMN is_searchable BOOLEAN NOT NULL DEFAULT TRUE, + ADD COLUMN is_searchable BOOLEAN NOT NULL DEFAULT FALSE, DROP COLUMN display_name_len; diff --git a/svc/pkg/user/ops/avatar-upload-complete/Cargo.toml b/svc/pkg/user/ops/avatar-upload-complete/Cargo.toml index 6273ec563d..89d7ec0201 100644 --- a/svc/pkg/user/ops/avatar-upload-complete/Cargo.toml +++ b/svc/pkg/user/ops/avatar-upload-complete/Cargo.toml @@ -13,7 +13,7 @@ prost = "0.10" upload-complete = { path = "../../../upload/ops/complete" } [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/user/ops/get/Cargo.toml b/svc/pkg/user/ops/get/Cargo.toml index 263fe0a09e..b5c9e0fad0 100644 --- a/svc/pkg/user/ops/get/Cargo.toml +++ b/svc/pkg/user/ops/get/Cargo.toml @@ -14,7 +14,7 @@ upload-file-list = { path = "../../../upload/ops/file-list" } upload-get = { path = "../../../upload/ops/get" } [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/user/ops/mutual-friend-list/Cargo.toml b/svc/pkg/user/ops/mutual-friend-list/Cargo.toml index 07ace882f0..e3db3ec8b3 100644 --- a/svc/pkg/user/ops/mutual-friend-list/Cargo.toml +++ b/svc/pkg/user/ops/mutual-friend-list/Cargo.toml @@ -11,7 +11,7 @@ chirp-client = { path = "../../../../../lib/chirp/client" } prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/user/ops/pending-delete-toggle/Cargo.toml b/svc/pkg/user/ops/pending-delete-toggle/Cargo.toml index 1b3c73b317..451299d5bb 100644 --- a/svc/pkg/user/ops/pending-delete-toggle/Cargo.toml +++ b/svc/pkg/user/ops/pending-delete-toggle/Cargo.toml @@ -13,7 +13,7 @@ prost = "0.10" user-identity-get = { path = "../../../user-identity/ops/get" } [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/user/ops/profile-validate/Cargo.toml b/svc/pkg/user/ops/profile-validate/Cargo.toml index 7ae1fa55cd..9420a0015c 100644 --- a/svc/pkg/user/ops/profile-validate/Cargo.toml +++ b/svc/pkg/user/ops/profile-validate/Cargo.toml @@ -14,7 +14,7 @@ user-get = { path = "../get" } profanity-check = { path = "../../../profanity/ops/check" } [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/user/ops/resolve-email/Cargo.toml b/svc/pkg/user/ops/resolve-email/Cargo.toml index ebef26efc1..f53b73a2f9 100644 --- a/svc/pkg/user/ops/resolve-email/Cargo.toml +++ b/svc/pkg/user/ops/resolve-email/Cargo.toml @@ -11,7 +11,7 @@ chirp-client = { path = "../../../../../lib/chirp/client" } prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/user/ops/search/Cargo.toml b/svc/pkg/user/ops/search/Cargo.toml index 7cdbd738a9..4b8f193d6a 100644 --- a/svc/pkg/user/ops/search/Cargo.toml +++ b/svc/pkg/user/ops/search/Cargo.toml @@ -13,7 +13,7 @@ prost = "0.10" regex = "1.4" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/user/ops/team-list/Cargo.toml b/svc/pkg/user/ops/team-list/Cargo.toml index c26c74e4e0..23eb6cf9b6 100644 --- a/svc/pkg/user/ops/team-list/Cargo.toml +++ b/svc/pkg/user/ops/team-list/Cargo.toml @@ -11,7 +11,7 @@ chirp-client = { path = "../../../../../lib/chirp/client" } prost = "0.10" [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/user/ops/thread-typing-status-set/Cargo.toml b/svc/pkg/user/ops/thread-typing-status-set/Cargo.toml index 213e1555da..e852a2870c 100644 --- a/svc/pkg/user/ops/thread-typing-status-set/Cargo.toml +++ b/svc/pkg/user/ops/thread-typing-status-set/Cargo.toml @@ -13,7 +13,7 @@ prost = "0.10" util-chat = { package = "rivet-util-chat", path = "../../../chat/util" } [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/user/ops/token-create/Cargo.toml b/svc/pkg/user/ops/token-create/Cargo.toml index fb99538b82..9489b5c4d2 100644 --- a/svc/pkg/user/ops/token-create/Cargo.toml +++ b/svc/pkg/user/ops/token-create/Cargo.toml @@ -13,7 +13,7 @@ prost = "0.10" token-create = { path = "../../../token/ops/create" } [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false [dev-dependencies] diff --git a/svc/pkg/user/standalone/delete-pending/Cargo.toml b/svc/pkg/user/standalone/delete-pending/Cargo.toml index 23bd8a7c8f..57486342fa 100644 --- a/svc/pkg/user/standalone/delete-pending/Cargo.toml +++ b/svc/pkg/user/standalone/delete-pending/Cargo.toml @@ -15,7 +15,7 @@ prost = "0.10" rivet-connection = { path = "../../../../../lib/connection" } rivet-pools = { path = "../../../../../lib/pools" } rivet-runtime = { path = "../../../../../lib/runtime" } -tokio = { version = "1.21", features = ["full"] } +tokio = { version = "1.29", features = ["full"] } tracing = "0.1" tracing-subscriber = { version = "0.3", default-features = false, features = ["fmt", "json", "ansi"] } diff --git a/svc/pkg/user/standalone/search-user-gc/Cargo.toml b/svc/pkg/user/standalone/search-user-gc/Cargo.toml index 0a9253f34f..8ca7fd9dc8 100644 --- a/svc/pkg/user/standalone/search-user-gc/Cargo.toml +++ b/svc/pkg/user/standalone/search-user-gc/Cargo.toml @@ -14,7 +14,7 @@ indoc = "1.0" prost = "0.10" rivet-connection = { path = "../../../../../lib/connection" } rivet-runtime = { path = "../../../../../lib/runtime" } -tokio = { version = "1.21", features = ["full"] } +tokio = { version = "1.29", features = ["full"] } tracing = "0.1" tracing-subscriber = { version = "0.3", default-features = false, features = ["fmt", "json", "ansi"] } diff --git a/svc/pkg/user/worker/src/workers/create.rs b/svc/pkg/user/worker/src/workers/create.rs index 2aef91217e..39e09d9db9 100644 --- a/svc/pkg/user/worker/src/workers/create.rs +++ b/svc/pkg/user/worker/src/workers/create.rs @@ -14,7 +14,7 @@ lazy_static! { } #[worker(name = "user-create")] -async fn worker(ctx: OperationContext) -> GlobalResult<()> { +async fn worker(ctx: &OperationContext) -> GlobalResult<()> { let user_id = internal_unwrap!(ctx.user_id).as_uuid(); let join_ts = ctx.ts(); diff --git a/svc/pkg/user/worker/src/workers/delete.rs b/svc/pkg/user/worker/src/workers/delete.rs index 5439d3dd90..b8bb869583 100644 --- a/svc/pkg/user/worker/src/workers/delete.rs +++ b/svc/pkg/user/worker/src/workers/delete.rs @@ -8,7 +8,7 @@ const MESSAGE_BATCH_SIZE: usize = 256; const UPLOAD_BATCH_SIZE: usize = 256; #[worker(name = "user-delete")] -async fn worker(ctx: OperationContext) -> GlobalResult<()> { +async fn worker(ctx: &OperationContext) -> GlobalResult<()> { let user_id = internal_unwrap!(ctx.user_id).as_uuid(); let crdb = ctx.crdb("db-user").await?; diff --git a/svc/pkg/user/worker/src/workers/event_chat_last_read_ts_update.rs b/svc/pkg/user/worker/src/workers/event_chat_last_read_ts_update.rs index 90ab71fa08..5633e0a69c 100644 --- a/svc/pkg/user/worker/src/workers/event_chat_last_read_ts_update.rs +++ b/svc/pkg/user/worker/src/workers/event_chat_last_read_ts_update.rs @@ -3,7 +3,7 @@ use proto::backend::{self, pkg::*}; #[worker(name = "user-event-chat-last-read-ts-update")] async fn worker( - ctx: OperationContext, + ctx: &OperationContext, ) -> GlobalResult<()> { let user_id = internal_unwrap!(ctx.user_id).as_uuid(); diff --git a/svc/pkg/user/worker/src/workers/event_chat_message_create_complete.rs b/svc/pkg/user/worker/src/workers/event_chat_message_create_complete.rs index 72b1e147e6..2d6ec1d8f8 100644 --- a/svc/pkg/user/worker/src/workers/event_chat_message_create_complete.rs +++ b/svc/pkg/user/worker/src/workers/event_chat_message_create_complete.rs @@ -3,7 +3,7 @@ use proto::backend::{self, pkg::*}; #[worker(name = "user-event-chat-message-create-complete")] async fn worker( - ctx: OperationContext, + ctx: &OperationContext, ) -> GlobalResult<()> { for user_id in &ctx.participant_user_ids { msg!([ctx] user::msg::event(user_id) { diff --git a/svc/pkg/user/worker/src/workers/event_party_member_update.rs b/svc/pkg/user/worker/src/workers/event_party_member_update.rs new file mode 100644 index 0000000000..5a2017bd81 --- /dev/null +++ b/svc/pkg/user/worker/src/workers/event_party_member_update.rs @@ -0,0 +1,17 @@ +use chirp_worker::prelude::*; +use proto::backend::{self, pkg::*}; + +#[worker(name = "user-event-party-member-update")] +async fn worker(ctx: &OperationContext) -> GlobalResult<()> { + let user_id = internal_unwrap!(ctx.user_id).as_uuid(); + + msg!([ctx] user::msg::event(user_id) { + user_id: Some(user_id.into()), + event: Some(backend::user::event::Event { + kind: Some(backend::user::event::event::Kind::PartyUpdate(backend::user::event::PartyUpdate {})), + }), + }) + .await?; + + Ok(()) +} diff --git a/svc/pkg/user/worker/src/workers/event_party_update.rs b/svc/pkg/user/worker/src/workers/event_party_update.rs new file mode 100644 index 0000000000..7b877e3bb9 --- /dev/null +++ b/svc/pkg/user/worker/src/workers/event_party_update.rs @@ -0,0 +1,25 @@ +use chirp_worker::prelude::*; +use proto::backend::{self, pkg::*}; + +#[worker(name = "user-event-party-update")] +async fn worker(ctx: &OperationContext) -> GlobalResult<()> { + let party_id = internal_unwrap!(ctx.party_id).as_uuid(); + + let member_list = op!([ctx] party_member_list { + party_ids: vec![party_id.into()], + }) + .await?; + let party = internal_unwrap_owned!(member_list.parties.first()); + + for user_id in &party.user_ids { + msg!([ctx] user::msg::event(user_id) { + user_id: Some(*user_id), + event: Some(backend::user::event::Event { + kind: Some(backend::user::event::event::Kind::PartyUpdate(backend::user::event::PartyUpdate {})), + }), + }) + .await?; + } + + Ok(()) +} diff --git a/svc/pkg/user/worker/src/workers/event_team_member_remove.rs b/svc/pkg/user/worker/src/workers/event_team_member_remove.rs index 365b9342f2..a73acc10d8 100644 --- a/svc/pkg/user/worker/src/workers/event_team_member_remove.rs +++ b/svc/pkg/user/worker/src/workers/event_team_member_remove.rs @@ -2,7 +2,7 @@ use chirp_worker::prelude::*; use proto::backend::{self, pkg::*}; #[worker(name = "user-event-team-member-remove")] -async fn worker(ctx: OperationContext) -> GlobalResult<()> { +async fn worker(ctx: &OperationContext) -> GlobalResult<()> { let user_id = internal_unwrap!(ctx.user_id); msg!([ctx] user::msg::event(user_id) { diff --git a/svc/pkg/user/worker/src/workers/event_user_mm_lobby_join.rs b/svc/pkg/user/worker/src/workers/event_user_mm_lobby_join.rs index 3af00a00fa..bd4b3bda04 100644 --- a/svc/pkg/user/worker/src/workers/event_user_mm_lobby_join.rs +++ b/svc/pkg/user/worker/src/workers/event_user_mm_lobby_join.rs @@ -2,7 +2,7 @@ use chirp_worker::prelude::*; use proto::backend::{self, pkg::*}; #[worker(name = "user-event-user-mm-lobby-join")] -async fn worker(ctx: OperationContext) -> GlobalResult<()> { +async fn worker(ctx: &OperationContext) -> GlobalResult<()> { let user_id = internal_unwrap!(ctx.user_id).as_uuid(); msg!([ctx] user::msg::event(user_id) { diff --git a/svc/pkg/user/worker/src/workers/event_user_presence_update.rs b/svc/pkg/user/worker/src/workers/event_user_presence_update.rs index d00a48f447..ff08ab9cf4 100644 --- a/svc/pkg/user/worker/src/workers/event_user_presence_update.rs +++ b/svc/pkg/user/worker/src/workers/event_user_presence_update.rs @@ -3,7 +3,7 @@ use proto::backend::{self, pkg::*}; use rivet_convert::ApiInto; #[worker(name = "user-event-user-presence-update")] -async fn worker(ctx: OperationContext) -> GlobalResult<()> { +async fn worker(ctx: &OperationContext) -> GlobalResult<()> { let user_id = internal_unwrap!(ctx.user_id); msg!([ctx] user::msg::event(user_id) { diff --git a/svc/pkg/user/worker/src/workers/event_user_update.rs b/svc/pkg/user/worker/src/workers/event_user_update.rs index 4aeb16384b..6741631464 100644 --- a/svc/pkg/user/worker/src/workers/event_user_update.rs +++ b/svc/pkg/user/worker/src/workers/event_user_update.rs @@ -2,7 +2,7 @@ use chirp_worker::prelude::*; use proto::backend::{self, pkg::*}; #[worker(name = "user-event-user-update")] -async fn worker(ctx: OperationContext) -> GlobalResult<()> { +async fn worker(ctx: &OperationContext) -> GlobalResult<()> { let user_id = internal_unwrap!(ctx.user_id); msg!([ctx] user::msg::event(user_id) { diff --git a/svc/pkg/user/worker/src/workers/profile_set.rs b/svc/pkg/user/worker/src/workers/profile_set.rs index 6eb380c3af..a1a0fc872d 100644 --- a/svc/pkg/user/worker/src/workers/profile_set.rs +++ b/svc/pkg/user/worker/src/workers/profile_set.rs @@ -2,7 +2,7 @@ use chirp_worker::prelude::*; use proto::backend::pkg::*; #[worker(name = "user-profile-set")] -async fn worker(ctx: OperationContext) -> GlobalResult<()> { +async fn worker(ctx: &OperationContext) -> GlobalResult<()> { let body = ctx.body(); let user::msg::profile_set::Message { user_id, diff --git a/svc/pkg/user/worker/src/workers/search_update.rs b/svc/pkg/user/worker/src/workers/search_update.rs index f129982519..5118f9c421 100644 --- a/svc/pkg/user/worker/src/workers/search_update.rs +++ b/svc/pkg/user/worker/src/workers/search_update.rs @@ -2,7 +2,7 @@ use chirp_worker::prelude::*; use proto::backend::pkg::*; #[worker(name = "user-search-update")] -async fn worker(ctx: OperationContext) -> GlobalResult<()> { +async fn worker(ctx: &OperationContext) -> GlobalResult<()> { let crdb = ctx.crdb("db-user").await?; let user_id = internal_unwrap_owned!(ctx.user_id).as_uuid(); diff --git a/svc/pkg/user/worker/src/workers/search_update_user_follow_create.rs b/svc/pkg/user/worker/src/workers/search_update_user_follow_create.rs index bcbd0b7cb3..d5b3de79ab 100644 --- a/svc/pkg/user/worker/src/workers/search_update_user_follow_create.rs +++ b/svc/pkg/user/worker/src/workers/search_update_user_follow_create.rs @@ -2,7 +2,7 @@ use chirp_worker::prelude::*; use proto::backend::pkg::*; #[worker(name = "user-search-update-user-follow-create")] -async fn worker(ctx: OperationContext) -> GlobalResult<()> { +async fn worker(ctx: &OperationContext) -> GlobalResult<()> { let user_id = internal_unwrap_owned!(ctx.following_user_id).as_uuid(); msg!([ctx] user::msg::search_update(user_id) { diff --git a/svc/pkg/user/worker/src/workers/search_update_user_update.rs b/svc/pkg/user/worker/src/workers/search_update_user_update.rs index dc3552a0f4..77f45fef87 100644 --- a/svc/pkg/user/worker/src/workers/search_update_user_update.rs +++ b/svc/pkg/user/worker/src/workers/search_update_user_update.rs @@ -2,7 +2,7 @@ use chirp_worker::prelude::*; use proto::backend::pkg::*; #[worker(name = "user-search-update-user-update")] -async fn worker(ctx: OperationContext) -> GlobalResult<()> { +async fn worker(ctx: &OperationContext) -> GlobalResult<()> { let user_id = internal_unwrap_owned!(ctx.user_id); msg!([ctx] user::msg::search_update(user_id) { diff --git a/svc/pkg/user/worker/src/workers/updated_party_update.rs b/svc/pkg/user/worker/src/workers/updated_party_update.rs new file mode 100644 index 0000000000..9d2eaa43ce --- /dev/null +++ b/svc/pkg/user/worker/src/workers/updated_party_update.rs @@ -0,0 +1,25 @@ +use chirp_worker::prelude::*; +use proto::backend::{self, pkg::*}; + +#[worker(name = "user-updated-party-update")] +async fn worker(ctx: &OperationContext) -> GlobalResult<()> { + let party_id = internal_unwrap!(ctx.party_id); + + let member_list = op!([ctx] party_member_list { + party_ids: vec![*party_id], + }) + .await?; + let party = internal_unwrap_owned!(member_list.parties.first()); + + for user_id in &party.user_ids { + msg!([ctx] user::msg::updated(user_id) { + user_id: Some(*user_id), + update: Some(backend::user::update::Update { + kind: Some(backend::user::update::update::Kind::PartyUpdate(backend::user::update::PartyUpdate {})), + }), + }) + .await?; + } + + Ok(()) +} diff --git a/svc/pkg/user/worker/src/workers/updated_user_follow_create.rs b/svc/pkg/user/worker/src/workers/updated_user_follow_create.rs index 8cf04d09d2..2a9171463f 100644 --- a/svc/pkg/user/worker/src/workers/updated_user_follow_create.rs +++ b/svc/pkg/user/worker/src/workers/updated_user_follow_create.rs @@ -2,7 +2,7 @@ use chirp_worker::prelude::*; use proto::backend::{self, pkg::*}; #[worker(name = "user-updated-user-follow-create")] -async fn worker(ctx: OperationContext) -> GlobalResult<()> { +async fn worker(ctx: &OperationContext) -> GlobalResult<()> { let follower_user_id = internal_unwrap!(ctx.follower_user_id); let following_user_id = internal_unwrap!(ctx.following_user_id); diff --git a/svc/pkg/user/worker/src/workers/updated_user_follow_delete.rs b/svc/pkg/user/worker/src/workers/updated_user_follow_delete.rs index cbee28c855..7756f3dc99 100644 --- a/svc/pkg/user/worker/src/workers/updated_user_follow_delete.rs +++ b/svc/pkg/user/worker/src/workers/updated_user_follow_delete.rs @@ -2,7 +2,7 @@ use chirp_worker::prelude::*; use proto::backend::{self, pkg::*}; #[worker(name = "user-updated-user-follow-delete")] -async fn worker(ctx: OperationContext) -> GlobalResult<()> { +async fn worker(ctx: &OperationContext) -> GlobalResult<()> { let follower_user_id = internal_unwrap!(ctx.follower_user_id); let following_user_id = internal_unwrap!(ctx.following_user_id); diff --git a/svc/pkg/user/worker/src/workers/updated_user_presence_update.rs b/svc/pkg/user/worker/src/workers/updated_user_presence_update.rs index b9b4ad5864..b13ce1986a 100644 --- a/svc/pkg/user/worker/src/workers/updated_user_presence_update.rs +++ b/svc/pkg/user/worker/src/workers/updated_user_presence_update.rs @@ -3,7 +3,7 @@ use proto::backend::{self, pkg::*}; use rivet_convert::ApiInto; #[worker(name = "user-updated-user-presence-update")] -async fn worker(ctx: OperationContext) -> GlobalResult<()> { +async fn worker(ctx: &OperationContext) -> GlobalResult<()> { let user_id = internal_unwrap!(ctx.user_id); msg!([ctx] user::msg::updated(user_id) { diff --git a/svc/pkg/user/worker/src/workers/updated_user_update.rs b/svc/pkg/user/worker/src/workers/updated_user_update.rs index 0f994808b7..bd6e01251c 100644 --- a/svc/pkg/user/worker/src/workers/updated_user_update.rs +++ b/svc/pkg/user/worker/src/workers/updated_user_update.rs @@ -2,7 +2,7 @@ use chirp_worker::prelude::*; use proto::backend::{self, pkg::*}; #[worker(name = "user-updated-user-update")] -async fn worker(ctx: OperationContext) -> GlobalResult<()> { +async fn worker(ctx: &OperationContext) -> GlobalResult<()> { let user_id = internal_unwrap!(ctx.user_id); msg!([ctx] user::msg::updated(user_id) { diff --git a/svc/templates/api/Cargo.toml b/svc/templates/api/Cargo.toml index 51af8a5e8e..849d857349 100644 --- a/svc/templates/api/Cargo.toml +++ b/svc/templates/api/Cargo.toml @@ -20,7 +20,7 @@ rivet-pools = { path = "../../../lib/pools" } s3-util = { path = "../../../lib/s3-util" } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -tokio = { version = "1.21" } +tokio = { version = "1.29" } tracing = "0.1" tracing-futures = "0.2" tracing-subscriber = { version = "0.3", default-features = false, features = ["fmt", "json", "ansi"] } diff --git a/svc/templates/operation/Cargo.toml b/svc/templates/operation/Cargo.toml index e618941319..19049267c2 100644 --- a/svc/templates/operation/Cargo.toml +++ b/svc/templates/operation/Cargo.toml @@ -10,5 +10,5 @@ chirp-client = { path = "../../../../../lib/chirp/client" } rivet-operation = { path = "../../../../../lib/operation/core" } [dependencies.sqlx] -version = "0.6" +version = "0.7" default-features = false diff --git a/svc/templates/standalone/Cargo.toml b/svc/templates/standalone/Cargo.toml index 366e87d193..a791a00db1 100644 --- a/svc/templates/standalone/Cargo.toml +++ b/svc/templates/standalone/Cargo.toml @@ -10,7 +10,7 @@ chirp-client = { path = "../../../../../lib/chirp/client" } rivet-operation = { path = "../../../../../lib/operation/core" } rivet-connection = { path = "../../../../../lib/connection" } rivet-runtime = { path = "../../../../../lib/runtime" } -tokio = { version = "1.21", features = ["full"] } +tokio = { version = "1.29", features = ["full"] } tracing = "0.1" tracing-subscriber = { version = "0.3", default-features = false, features = ["fmt", "json", "ansi"] } diff --git a/svc/templates/worker/src/workers/{{ snake name }}.rs b/svc/templates/worker/src/workers/{{ snake name }}.rs index 855fde8b73..75ac2afe16 100644 --- a/svc/templates/worker/src/workers/{{ snake name }}.rs +++ b/svc/templates/worker/src/workers/{{ snake name }}.rs @@ -2,7 +2,7 @@ use chirp_worker::prelude::*; use proto::backend::pkg::*; #[worker(name = "{{pkg}}-{{name}}")] -async fn worker(ctx: OperationContext<{{snake pkg}}::msg::{{snake name}}::Message>) -> GlobalResult<()> { +async fn worker(ctx: &OperationContext<{{snake pkg}}::msg::{{snake name}}::Message>) -> GlobalResult<()> { todo!(); Ok(())