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());
|
Optional<DictionaryDefinition> existing = repository.findByName(entry.name());
|
||||||
if (existing.isPresent()) {
|
if (existing.isPresent()) {
|
||||||
DictionaryDefinition def = existing.get();
|
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();
|
JsonNode prevSchema = def.getSchemaJson();
|
||||||
def.setSchemaJson(schema);
|
def.setSchemaJson(schema);
|
||||||
def.setSchemaVersion(entry.schemaVersion());
|
def.setSchemaVersion(entry.schemaVersion());
|
||||||
@@ -304,4 +311,44 @@ public class CuodBundleImporter {
|
|||||||
}
|
}
|
||||||
return null;
|
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