in moz_kinto_publisher/main.py [0:0]
def crlite_verify_record_consistency(*, existing_records, channel):
# This function assumes that existing_records is sorted according to
# record["details"]["name"], which is a "YYYY-MM-DDTHH:MM:SS+00:00Z"
# timestamp.
existing_records = [
x for x in existing_records if x.get("channel", CHANNEL_DEFAULT) == channel.slug
]
# It's OK if there are no records yet.
if len(existing_records) == 0:
return
for r in existing_records:
if not ("id" in r and "incremental" in r and "attachment" in r):
raise ConsistencyException(f"Malformed record {r}.")
if r["incremental"] and not "parent" in r:
raise ConsistencyException(f"Malformed record {r}.")
# There must be exactly 1 full filter in the existing records.
full_filters = [r for r in existing_records if not r["incremental"]]
if len(full_filters) == 0:
raise ConsistencyException("No full filters.")
if len(full_filters) >= 2:
raise ConsistencyException(f"Multiple full filters: {full_filters}")
# Each incremental filter should be a descendent of the full filter
ids = {r["id"]: r for r in existing_records}
maxHeight = 0
for r in existing_records:
ptr = r["id"]
height = 0
while ids[ptr]["incremental"]:
ptr = ids[ptr]["parent"]
if ptr not in ids:
raise ConsistencyException(f"Record {r['id']} has unknown parent {ptr}")
height += 1
if height > len(existing_records):
raise ConsistencyException(f"Record parent cycle")
maxHeight = max(height, maxHeight)
# The incremental filters should form a chain (no branching), hence there's
# an incremental filter len(existing_records)-1 steps away from the full
# filter.
if maxHeight != len(existing_records) - 1:
raise ConsistencyException(f"Multiple filter descendents: {full_filters}")