Skip to content

How to deal with different Nexus versions having different types? #1093

@jmpesp

Description

@jmpesp

During an upgrade, any request to Nexus will hit a load balancer and could be sent to two different Nexus versions. There are many ways that this could fail but one that was discussed in relation to PR #1092 was the following:

  1. Nexus version X has a database enum that has variants A, B, C.

  2. Nexus version Y introduces a new enum variant D through a schema upgrade.

  3. A user request creates a row with that new enum variant.

  4. Another user request does a GET to list all objects that include that enum

This can be reproduced (using PR #1092) by POSTing to the /images endpoint:

{
  "name": "crucible-tester-sparse",
  "description": "boot from a url!",
  "distribution": "debian",
  "version": "9",
  "block_size": 512,
  "source": {
    "type": "url",
    "src": "http://127.0.0.1:8080/crucible-tester-sparse.img"
  }
}

then, using the CockroachDB cli to perform a schema upgrade that adds a variant to the enum:

ALTER TYPE distribution ADD VALUE 'freebsd';
update global_image set distribution = 'freebsd' where name = 'crucible-tester-sparse';

then, performing a GET /images. Nexus currently returns a 500 error:

May 18 20:37:36.123 INFO request completed

error_message_external: Internal Server Error
error_message_internal: unexpected database error: Unrecognized enum variant for Distribution
response_code: 500
uri: /images
method: GET
req_id: a53847a4-1456-4f08-8d8f-b41378bda09a
remote_addr: 127.0.0.1:36764
local_addr: 127.0.0.1:12220
component: dropshot_external
name: e6bff1ff-24fb-49dc-a54e-c6a350cd4d6c

PR #1092 introduces InterregnumError - specifically, the database enum contains the "freebsd" variant but the external enum does not. A TryFrom is required to convert from the database enum to the external enum, with an Interregnum error being thrown if freebsd is found in the DB.

Note that's not to say that this is the way we should do it, just that it was an attempt at addressing this issue's question. A safe upgrade scheme would be to add a variant to the database enum first, let that upgrade propagate out to all Nexus instances, and then proceed with a second upgrade to add the variant to the external enum. This implicitly relies on every Nexus being upgraded from version X -> Y before being upgraded from Y -> Z.

I'm opening this issue to track work related to the issue's title question: how are we going to deal with different Nexus versions having different types? There's a versioning RFD in the works that should also address this question (@smklein @ahl)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions