[Instances] Honor reserved instances (#3563)

* [Instances] Honor reserved instances

Logic to select next available instance id was incorrect.
The correct logic selected the max id + 1 or max reserved + 1, but then it would overwrite if we enabled recycling ids.
Additionally, it was incrementing the reserved ids and assigning ids to the max reserved id vice the next available.
Finally, it was running the logic twice.

* Fix updated SQL to use fmt
This commit is contained in:
JJ 2023-08-20 20:21:51 -04:00 committed by GitHub
parent a61f951d0e
commit c47644ea46
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -131,85 +131,60 @@ bool Database::CreateInstance(uint16 instance_id, uint32 zone_id, uint32 version
bool Database::GetUnusedInstanceID(uint16 &instance_id)
{
uint32 max_reserved_instance_id = RuleI(Instances, ReservedInstances);
uint32 max = 32000;
uint32 max_instance_id = 32000;
// sanity check reserved
if (max_reserved_instance_id >= max_instance_id) {
instance_id = 0;
return false;
}
// initial query - get max unused id above reserved
auto query = fmt::format(
"SELECT IFNULL(MAX(id), {}) + 1 FROM instance_list WHERE id > {}",
max_reserved_instance_id,
max_reserved_instance_id
);
// recycle instances - change query to get first unused id above reserved
if (RuleB(Instances, RecycleInstanceIds)) {
query = (
query = fmt::format(
SQL(
SELECT i.id + 1 AS next_available
SELECT MIN(i.id + 1) AS next_available
FROM instance_list i
LEFT JOIN instance_list i2 ON i2.id = i.id + 1
WHERE i2.id IS NULL
ORDER BY i.id
LIMIT 0, 1;
)
LEFT JOIN instance_list i2 ON i.id + 1 = i2.id
WHERE i.id > {}
AND i2.id IS NULL;
),
RuleI(Instances, ReservedInstances)
);
}
auto results = QueryDatabase(query);
// could not successfully query - bail out
if (!results.Success()) {
instance_id = 0;
return false;
}
// no instances running - assign first id above reserved
if (results.RowCount() == 0) {
instance_id = max_reserved_instance_id;
instance_id = max_reserved_instance_id + 1;
return true;
}
auto row = results.begin();
if (Strings::ToInt(row[0]) <= max) {
// check that id is within limits
if (Strings::ToInt(row[0]) <= max_instance_id) {
instance_id = Strings::ToInt(row[0]);
return true;
}
if (instance_id < max_reserved_instance_id) {
instance_id = max_reserved_instance_id;
return true;
}
query = fmt::format("SELECT id FROM instance_list where id > {} ORDER BY id", max_reserved_instance_id);
results = QueryDatabase(query);
if (!results.Success()) {
// unhandled situation - should not reach here
instance_id = 0;
return false;
}
if (results.RowCount() == 0) {
instance_id = 0;
return false;
}
max_reserved_instance_id++;
for (auto row : results) {
if (max_reserved_instance_id < Strings::ToUnsignedInt(row[0])) {
instance_id = max_reserved_instance_id;
return true;
}
if (max_reserved_instance_id > max) {
instance_id = 0;
return false;
}
max_reserved_instance_id++;
}
instance_id = max_reserved_instance_id;
return true;
}
bool Database::IsGlobalInstance(uint16 instance_id)