-
Notifications
You must be signed in to change notification settings - Fork 54
Description
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:
-
Nexus version X has a database enum that has variants A, B, C.
-
Nexus version Y introduces a new enum variant D through a schema upgrade.
-
A user request creates a row with that new enum variant.
-
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)