Skip to content

feat: improve profile deployment#358

Merged
LautaroPetaccio merged 9 commits intomainfrom
feat/improve-profile-deployment
Mar 23, 2026
Merged

feat: improve profile deployment#358
LautaroPetaccio merged 9 commits intomainfrom
feat/improve-profile-deployment

Conversation

@LautaroPetaccio
Copy link
Copy Markdown
Collaborator

@LautaroPetaccio LautaroPetaccio commented Mar 18, 2026

Profile deployment had several issues:

  1. Silent failures on HTTP errors: client.deploy() from dcl-catalyst-client returns the raw Response without throwing on non-2xx status codes. The existing code never checked response.ok, so a 400 or 500 from the catalyst was silently treated as a success.

  2. Duplicated deployment logic: Catalyst rotation with retry logic was implemented independently in three places (AvatarSetupPage/utils.ts, SetupPage/utils.ts, and modules/profile/index.ts), each with different behavior. The AvatarSetupPage was missing isRetryableError checks (retrying on 4xx when it shouldn't), and the SetupPage had no catalyst rotation at all.

  3. Missing disabled catalysts: The AvatarSetupPage and SetupPage were not passing the disabledCatalysts feature flag list, potentially deploying to catalysts that were intentionally disabled.

  4. No useful data in Sentry: When deployment errors were caught, the HTTP status code and response body were not included, making it difficult to diagnose failures.

How

Shared deployment function (src/modules/profile/deploy.ts)

Extracted a single deployWithCatalystRotation function that all deployment paths now use. It:

  • Checks response.ok after each client.deploy() call
  • Throws a DeploymentError (new class in src/modules/profile/errors.ts) on non-2xx responses, carrying statusCode, responseBody, and catalystUrl
  • Wraps network errors (e.g. Failed to fetch) in DeploymentError as well, so the catalystUrl is always preserved for Sentry logging even when there's no HTTP response
  • Uses isRetryableError to skip retries on 4xx client errors and retry on 5xx / network errors
  • Internally resolves catalyst URLs via getCatalystUrlsForRotation and creates its own fetcher, so callers only need to pass the deployment entity and optionally disabledCatalysts

Catalyst URL utilities (src/modules/profile/utils.ts)

Extracted getCatalystServers and getCatalystUrlsForRotation from index.ts into a separate file to avoid circular dependencies between deploy.ts and index.ts.

Callers updated

  • AvatarSetupPage/utils.ts: Replaced hand-rolled catalyst loop with deployWithCatalystRotation. Now passes disabledCatalysts.
  • SetupPage/utils.ts: Replaced single-catalyst deploy with deployWithCatalystRotation. Gains catalyst rotation and error detection it previously lacked. Now passes disabledCatalysts.
  • modules/profile/index.ts: redeployExistingProfile and redeployExistingProfileWithContentServerData now use the shared function. Removed the old redeployWithCatalystRotation, attemptRedeployment, and isRetryableHttpError.
  • AvatarSetupPage.tsx and SetupPage.tsx: Added useDisabledCatalysts() hook and pass the value through to deploy functions. Added disabledCatalysts to useCallback dependency arrays.

Automatic Sentry context for deployment errors (src/shared/utils/errorHandler.ts)

handleError now detects DeploymentError instances and automatically includes statusCode, responseBody, and catalystUrl as Sentry extras. Callers don't need to extract or pass this context themselves.

Stabilized useDisabledCatalysts hook

The useMemo dependency was changed from the variant object (which could have a new reference each render) to the primitive payloadValue string. A stable EMPTY_LIST constant is returned when there are no disabled catalysts, preventing unnecessary useCallback recreations in consuming components.

@vercel
Copy link
Copy Markdown

vercel Bot commented Mar 18, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
auth Ready Ready Preview, Comment Mar 23, 2026 2:46pm

Request Review

* @param disabledCatalysts - Catalyst addresses to exclude from the list
* @returns Content URLs in the form `{catalystAddress}/content`
*/
function getCatalystUrlsForRotation(disabledCatalysts: string[] = []): string[] {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think we have this one in a lib already, but I am not finding it 🙃

Copy link
Copy Markdown
Contributor

@kevinszuchet kevinszuchet left a comment

Choose a reason for hiding this comment

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

LGTM

@LautaroPetaccio LautaroPetaccio merged commit 897c4d5 into main Mar 23, 2026
9 checks passed
@LautaroPetaccio LautaroPetaccio deleted the feat/improve-profile-deployment branch March 23, 2026 14:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants