Fixed migration errors when tested against a copy of the live dataset

This commit is contained in:
Stefan Zermatten
2021-09-27 13:42:37 +02:00
parent 5e83a88132
commit fe83b5cbc5
10 changed files with 87 additions and 29 deletions

View File

@@ -58,11 +58,10 @@ let AttributeSchema = createPropertySchema({
type: 'inlineCalculationFieldToCompute',
optional: true,
},
// The damage done to the attribute, always positive
// The damage done to the attribute, should always compute as positive
damage: {
type: SimpleSchema.Integer,
optional: true,
min: 0,
},
// Can the value be decimal?
decimal: {

View File

@@ -37,7 +37,7 @@ let EffectSchema = createPropertySchema({
text: {
type: String,
optional: true,
max: STORAGE_LIMITS.name,
max: STORAGE_LIMITS.effectCondition,
},
//which stats the effect is applied to
stats: {

View File

@@ -65,6 +65,7 @@ let ComputedOnlySkillSchema = createPropertySchema({
value: {
type: Number,
defaultValue: 0,
optional: true,
},
// The result of baseValueCalculation
baseValue: {

View File

@@ -44,18 +44,18 @@ let SpellSchema = new SimpleSchema({})
type: String,
optional: true,
defaultValue: 'action',
max: STORAGE_LIMITS.name,
max: STORAGE_LIMITS.spellDetail,
},
range: {
type: String,
optional: true,
max: STORAGE_LIMITS.name,
max: STORAGE_LIMITS.spellDetail,
},
duration: {
type: String,
optional: true,
defaultValue: 'Instantaneous',
max: STORAGE_LIMITS.name,
max: STORAGE_LIMITS.spellDetail,
},
verbal: {
type: Boolean,
@@ -72,7 +72,7 @@ let SpellSchema = new SimpleSchema({})
material: {
type: String,
optional: true,
max: STORAGE_LIMITS.name,
max: STORAGE_LIMITS.spellDetail,
},
ritual: {
type: Boolean,

View File

@@ -6,10 +6,10 @@ import STORAGE_LIMITS from '/imports/constants/STORAGE_LIMITS.js';
// because {type: Schema} fields can't be extended
function fieldToCompute(field){
const schemaObj = {
// This is required, if we don't have a calculation delete the whole object
[`${field}.calculation`]: {
type: String,
max: STORAGE_LIMITS.calculation,
optional: true,
},
}
// If the field is an array, we need to include those fields as well
@@ -40,7 +40,7 @@ function computedOnlyField(field){
function includeParentFields(field, schemaObj){
const splitField = field.split('.');
if (splitField.length === 1){
schemaObj[field] = {type: Object};
schemaObj[field] = {type: Object, optional: true};
return;
}
let key = '';
@@ -48,9 +48,9 @@ function includeParentFields(field, schemaObj){
splitField.forEach(value => {
if (key){
if (value === '$'){
schemaObj[key] = {type: Array};
schemaObj[key] = {type: Array, optional: true};
} else {
schemaObj[key] = {type: Object};
schemaObj[key] = {type: Object, optional: true};
}
key += '.';
}

View File

@@ -78,6 +78,7 @@ function applyDefaultCalculationValue(definition, key){
definition[calcField] = {
type: String,
defaultValue,
optional: true,
};
}
delete def.defaultValue;

View File

@@ -1,6 +1,6 @@
const STORAGE_LIMITS = Object.freeze({
// String lengths
calculation: 256,
calculation: 1024,
collectionName: 64,
color: 10000,
description: 49473, //the length of the Bee Movie script
@@ -10,8 +10,10 @@ const STORAGE_LIMITS = Object.freeze({
name: 128,
summary: 10000,
tagLength: 128,
url: 256,
url: 1024,
variableName: 64,
spellDetail: 512,
effectText: 512,
// Number limits
levelMax: 128,
@@ -22,13 +24,12 @@ const STORAGE_LIMITS = Object.freeze({
diceRollValuesCount: 100,
errorCount: 32,
extraTagsCount: 5,
inlineCalculationCount: 32,
inlineCalculationCount: 64,
logContentCount: 32,
readersCount: 50,
resourcesCount: 32,
rollCount: 64,
rollBonusCount: 32,
statsToTarget: 32,
statsToTarget: 64,
tagCount: 64,
writersCount: 20,
});

View File

@@ -5,6 +5,7 @@ import { get } from 'lodash';
import embedInlineCalculations from '/imports/api/creature/computation/afterComputation/embedInlineCalculations.js';
import transformFields from '/imports/migrations/server/transformFields.js';
import SCHEMA_VERSION from '/imports/constants/SCHEMA_VERSION.js';
import STORAGE_LIMITS from '/imports/constants/STORAGE_LIMITS.js';
// Git version 2.0-beta.33
// Database version 1
@@ -34,7 +35,10 @@ function migrateCollection({collection, reversed}){
}
export default function migrateProperty({collection, reversed, prop}){
const transforms = transformsByPropType[prop.type];
const transforms = [
...(transformsByPropType[prop.type] || []),
{from: 'dependencies'}
];
let migratedProp = transformFields(prop, transforms, reversed);
const schema = collection.simpleSchema({type: prop.type});
// Only clean if the schema version matches our destination version
@@ -43,7 +47,15 @@ export default function migrateProperty({collection, reversed, prop}){
migratedProp = schema.clean(migratedProp);
schema.validate(migratedProp);
} catch(e){
console.warn(e);
if (e.details[0]?.type === 'maxString'){
console.log({
prop: prop,
details: e.details,
});
} else {
console.warn({prop, error: e});
}
}
}
return migratedProp;
@@ -70,13 +82,13 @@ const transformsByPropType = {
...getComputedPropertyTransforms('baseValue'),
...getComputedPropertyTransforms('spellSlotLevel'),
...getInlineComputationTransforms('description'),
{from: 'value', to: 'total'},
{from: 'value', to: 'total', up: nanToNull},
{from: 'proficiency', to: 'proficiency', up: stripZero},
],
'buff': [
...getComputedPropertyTransforms('duration'),
...getComputedPropertyTransforms('spellSlotLevel'),
...getInlineComputationTransforms('description'),
{from: 'value', to: 'total'},
{from: 'value', to: 'total', up: nanToNull},
],
'classLevel': [
...getInlineComputationTransforms('description'),
@@ -89,8 +101,16 @@ const transformsByPropType = {
],
'effect': [
{from: 'calculation', to: 'amount.calculation'},
{from: 'result', to: 'amount.value'},
{from: 'errors', to: 'amount.errors'},
{from: 'result', to: 'amount.value', up: nanToNull},
{from: 'errors', to: 'amount.errors', up: trimErrors},
{from: 'name', to: 'name', up(val, src, doc){
if (src.operation === 'conditional'){
doc.text = val;
return;
} else {
return val;
}
}},
],
'feature': [
...getInlineComputationTransforms('summary'),
@@ -112,6 +132,15 @@ const transformsByPropType = {
'skill': [
...getComputedPropertyTransforms('baseValue'),
...getInlineComputationTransforms('description'),
{from: 'value', to: 'value', up: nanToNull},
{from: 'passiveBonus', to: 'passiveBonus', up: nanToNull},
{from: 'proficiency', to: 'proficiency', up: stripZero},
],
'spell': [
...actionTransforms,
],
'proficiency': [
{from: 'value', to: 'value', up: stripZero},
],
'propertySlot': [
...getComputedPropertyTransforms('quantityExpected'),
@@ -126,16 +155,16 @@ const transformsByPropType = {
],
'toggle': [
{from: 'condition', to: 'condition.calculation'},
{from: 'toggleResult', to: 'condition.value'},
{from: 'errors', to: 'condition.errors'},
{from: 'toggleResult', to: 'condition.value', up: nanToNull},
{from: 'errors', to: 'condition.errors', up: trimErrors},
],
};
function getComputedPropertyTransforms(key){
return [
{from: key, to: `${key}.calculation`},
{from: `${key}Result`, to: `${key}.value`},
{from: `${key}Errors`, to: `${key}.errors`},
{from: `${key}Result`, to: `${key}.value`, up: nanToNull},
{from: `${key}Errors`, to: `${key}.errors`, up: trimErrors},
];
}
@@ -149,3 +178,29 @@ function getInlineComputationTransforms(key){
{from: `${key}Calculations.$.result`, to: `${key}.inlineCalculations.$.value`},
];
}
function nanToNull(val){
if (Number.isNaN(val)){
return null;
} else {
return val;
}
}
function stripZero(val){
if (val === 0){
return undefined;
} else {
return val;
}
}
function trimErrors(arr){
if(!arr) return arr;
arr.forEach(e => {
if (e.message.length > STORAGE_LIMITS.errorMessage){
e.message = e.message.slice(0, STORAGE_LIMITS.errorMessage);
}
});
return arr;
}

View File

@@ -1,6 +1,7 @@
import { get, set, unset, forEachRight, cloneDeep } from 'lodash';
export default function transformFields(src, transformList, reversed = false){
if (!transformList) return src;
// don't bash the old document during the transforms
let doc = cloneDeep(src);
for(let originalTransform of transformList){
@@ -80,7 +81,7 @@ function transformArrayField(src, doc, {from, to, up}, reversed){
if (reversed){
forEachRight(state.array, iterate(stack, state, src, doc, toSplit, up));
} else {
state.array.forEach(iterate(stack, state, src, doc, toSplit, up));
state.array?.forEach(iterate(stack, state, src, doc, toSplit, up));
}
}
}

View File

@@ -1,5 +1,5 @@
import SimpleSchema from 'simpl-schema';
if (Meteor.isDevelopment){
SimpleSchema.debug = true
//SimpleSchema.debug = true
}