fix(bundle): semver-aware schema update — не откатывать user-published
This commit is contained in:
+48
-1
@@ -103,7 +103,14 @@ public class CuodBundleImporter {
|
||||
Optional<DictionaryDefinition> existing = repository.findByName(entry.name());
|
||||
if (existing.isPresent()) {
|
||||
DictionaryDefinition def = existing.get();
|
||||
if (props.updateExistingSchema() && !entry.schemaVersion().equals(def.getSchemaVersion())) {
|
||||
// Semver-aware update: применяем bundle только если он СТРОГО НОВЕЕ
|
||||
// чем то что в БД. Иначе bundle с 1.0.0 откатывал бы user-published
|
||||
// 1.1.0 на каждом рестарте writer'а (regression наблюдалась на staging
|
||||
// 2026-06-02 — ground_station). User-published > bundle-shipped по
|
||||
// умолчанию: dev опубликовал — это новее manifest.json.
|
||||
boolean bundleNewer = props.updateExistingSchema()
|
||||
&& isStrictlyNewer(entry.schemaVersion(), def.getSchemaVersion());
|
||||
if (bundleNewer) {
|
||||
JsonNode prevSchema = def.getSchemaJson();
|
||||
def.setSchemaJson(schema);
|
||||
def.setSchemaVersion(entry.schemaVersion());
|
||||
@@ -304,4 +311,44 @@ public class CuodBundleImporter {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* True если {@code bundle} строго новее {@code db} по semver (X.Y.Z).
|
||||
* Используется чтобы bundle-import не откатывал user-published schema:
|
||||
* bundle ship'ит 1.0.0, dev опубликовал 1.1.0 → bundle skip.
|
||||
* Bundle ship'ит 1.2.0 → bundle wins.
|
||||
*
|
||||
* <p>Non-semver формат: fallback на string equals (т.е. update только
|
||||
* если "разные"). Не худшее поведение — раньше так и было всегда.
|
||||
*/
|
||||
static boolean isStrictlyNewer(String bundleVersion, String dbVersion) {
|
||||
if (bundleVersion == null) return false;
|
||||
if (dbVersion == null) return true;
|
||||
int[] bundle = parseSemver(bundleVersion);
|
||||
int[] db = parseSemver(dbVersion);
|
||||
if (bundle == null || db == null) {
|
||||
// Fallback: non-semver — обновим если "разные" чтобы сохранить
|
||||
// прежнее поведение для custom версионных схем.
|
||||
return !bundleVersion.equals(dbVersion);
|
||||
}
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (bundle[i] > db[i]) return true;
|
||||
if (bundle[i] < db[i]) return false;
|
||||
}
|
||||
return false; // equal
|
||||
}
|
||||
|
||||
private static int[] parseSemver(String s) {
|
||||
String[] parts = s.split("\\.");
|
||||
if (parts.length != 3) return null;
|
||||
try {
|
||||
return new int[] {
|
||||
Integer.parseInt(parts[0]),
|
||||
Integer.parseInt(parts[1]),
|
||||
Integer.parseInt(parts[2]),
|
||||
};
|
||||
} catch (NumberFormatException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user