Skip to content

Commit

Permalink
fix: Skeleton.toDB()s is_add determined wrong (#1248)
Browse files Browse the repository at this point in the history
This is a hotfix for the problem that `is_add` is being set based on if
the key is set or not. Furthermore, it is determined twice, so that the
"magic"-bullshit now was moved into the transaction. It is a fix for PR
#973 but previous implementation was also wrong.
  • Loading branch information
phorward authored Aug 28, 2024
1 parent e33b423 commit 6825f46
Showing 1 changed file with 13 additions and 15 deletions.
28 changes: 13 additions & 15 deletions src/viur/core/skeleton.py
Original file line number Diff line number Diff line change
Expand Up @@ -949,39 +949,45 @@ def toDB(cls, skel: SkeletonInstance, update_relations: bool = True, **kwargs) -
logging.warning(msg, stacklevel=3)
update_relations = not kwargs["clearUpdateTag"]

def txnUpdate(write_skel):
def __txn_update(write_skel):
db_key = write_skel["key"]
skel = write_skel.skeletonCls()

blob_list = set()
change_list = []
old_copy = {}
# Load the current values from Datastore or create a new, empty db.Entity
if is_add := not bool(db_key):
if not db_key:
# We'll generate the key we'll be stored under early so we can use it for locks etc
db_key = db.AllocateIDs(db.Key(skel.kindName))
db_obj = db.Entity(db_key)
db_obj["viur"] = {}
skel.dbEntity = db_obj
is_add = True
else:
db_key = db.keyHelper(db_key, skel.kindName)
if not (db_obj := db.Get(db_key)):
db_obj = db.Entity(db_key)
skel.dbEntity = db_obj
is_add = True
else:
skel.setEntity(db_obj)
old_copy = {k: v for k, v in db_obj.items()}
is_add = False

db_obj.setdefault("viur", {})

# Merge values and assemble unique properties
# Move accessed Values from srcSkel over to skel
skel.accessedValues = write_skel.accessedValues
skel["key"] = db_key # Ensure key stays set

for bone_name, bone in skel.items():
if bone_name == "key": # Explicitly skip key on top-level - this had been set above
continue

# Allow bones to perform outstanding "magic" operations before saving to db
bone.performMagic(skel, bone_name, isAdd=is_add) # FIXME VIUR4: ANY MAGIC IN OUR CODE IS DEPRECATED!!!

if not (bone_name in skel.accessedValues or bone.compute) and bone_name not in skel.dbEntity:
_ = skel[bone_name] # Ensure the datastore is filled with the default value
if (
Expand Down Expand Up @@ -1166,23 +1172,15 @@ def fixDotNames(entity):
blob_lock_obj["is_stale"] = False
db.Put(blob_lock_obj)

return db_obj.key, db_obj, skel, change_list
return db_obj.key, db_obj, skel, change_list, is_add

# END of txnUpdate subfunction
is_add = skel["key"] is None

# Allow bones to perform outstanding "magic" operations before saving to db
for bone_name, _bone in skel.items():
_bone.performMagic(skel, bone_name, isAdd=is_add)
# END of __txn_update subfunction

# Run our SaveTxn
if db.IsInTransaction():
key, db_obj, skel, change_list = txnUpdate(skel)
key, db_obj, skel, change_list, is_add = __txn_update(skel)
else:
key, db_obj, skel, change_list = db.RunInTransaction(txnUpdate, skel)

# Perform post-save operations (postProcessSerializedData Hook, Searchindex, ..)
skel["key"] = key
key, db_obj, skel, change_list, is_add = db.RunInTransaction(__txn_update, skel)

for bone_name, bone in skel.items():
bone.postSavedHandler(skel, bone_name, key)
Expand Down

0 comments on commit 6825f46

Please sign in to comment.