The name of networks should be unique.
Also adds support for exact-name queries for AlamanacNetworks.
Differential D19379
Add unique constraint for Almanac network names amckinley on Apr 17 2018, 6:41 PM. Authored by Tags None Referenced Files
Subscribers
Details
The name of networks should be unique. Also adds support for exact-name queries for AlamanacNetworks. Applied migration with existing duplicates, saw networks renamed, attempted to add duplicates, got a nice error message.
Diff Detail
Event TimelineComment Actions Migrations like this are tricky. For example, if an install has two networks with the same name already, ADD UNIQUE KEY ... will fail and leave the user stuck with a broken install that can't upgrade and no clear way to continue. I think the state of the art here is D18623, a PHP migration with:
I think the Network change is reasonable, but should be accompanied by these changes:
(I think the future of Almanac is very automation-heavy and that these constraints make sense looking forward.) I'm somewhat less certain the Interface change is correct/desirable in the long run. Currently, we actually destroy Interface objects, but this is unusual and should probably stop at some point, and we should disable/archive them instead. When that happens, maybe it becomes valid to have an old disabled :80 interface and a newer enabled :80 interface? But it's easy to remove this key later and will only get harder to add it, and I can't come up with any reason not to have it today. However, we need to do the migration dance to make sure we don't stick installs in a dead state:
AlmanacInterfaceEditor may also need a didCatchDuplicateKeyException() implementation to provide a nicer error message. (Maybe split this into two separate changes, too.) Comment Actions
Does this require a migration? It looks like it's just a collation type change according to bin/storage upgrade.
Do I need to create a migration to fix this as well? It looks pretty non-trivial to mangle arbitrary strings to conform to the AlmanacNames::validateName(...) rules.
Comment Actions The new migration logic might be too clever by half, but I tried pretty hard to break it and wasn't able to. Comment Actions
Something like this? $counts = queryfx_all( $conn_w, 'SELECT networkPHID, devicePHID, address, port, count(*) N FROM %T GROUP BY networkPHID, devicePHID, address, port', $interface->getTableName()); foreach ($counts as $row) { if ($row['N'] > 1) { //blah blah } } Comment Actions
In general, no. bin/storage adjust will do this kind of change automatically. In this particular case, if you don't add an explicit migration, installs can technically do this:
This is normally very hard to do (i.e., you basically have to willfully break Phabricator) and fairly easy to get out of (Phabricator runs fine without adjust, so you can just go rename one of the networks, although it may not be clear that renaming is what you should do) so I probably wouldn't bother with an explicit migration, but you could add one if you want. (One note is that we use --no-adjust in the Phacility cluster to limit downtime (adjust runs in a separate, optional phase) so rough edges here are a little more likely to cut us than regular installs.)
I think these are fine to leave as-is since nothing else depends on them or references them. This change is mostly just for consistency and sanity in a more API-oriented world.
That should work, but it's a little tricky to get the IDs out if you GROUP BY (at least, I don't know a good way to do it). I'd probably just do something dumb/simple like this: $big_map = array(); foreach (new LiskMigrationIterator(new AlmanacInterface()) as $interface) { $big_map["$network/$device/$address/$port"][] = $interface->getID(); } Then throw away all the entries with only 1 element, and you're left with the duplicates. But the GROUP BY approach is perfectly fine too if you find that simpler to write or work with. Actual changes here look good to me. I don't see any way to break the rename migration, except the one edge case inline.
|