fix(core): sort dict keys before msgpack encoding in DictTransformer - #3467
Open
KR-Ravindra wants to merge 4 commits into
Open
KR-Ravindra wants to merge 4 commits into
KR-Ravindra wants to merge 4 commits into
Conversation
DictTransformer.dict_to_binary_literal encoded the dict in insertion order, so equal dicts built in a different key order produced different msgpack bytes and therefore different propeller cache keys. Recursively sort dict keys (through nested dicts and lists) before encoding so the literal bytes are canonical. Dataclasses, FlyteFile and FlyteDirectory values inside the dict are passed through untouched. Signed-off-by: KR Ravindra <42912207+KR-Ravindra@users.noreply.github.com>
- Add tuple support to _sort_dict_keys (returns tuple) - Add test case for tuple-nested dict - Fix 122-char assert to meet 120-char line limit in pyproject.toml Signed-off-by: KR Ravindra <42912207+KR-Ravindra@users.noreply.github.com>
Signed-off-by: KR Ravindra <42912207+KR-Ravindra@users.noreply.github.com>
Signed-off-by: KR Ravindra <42912207+KR-Ravindra@users.noreply.github.com>
KR-Ravindra
marked this pull request as ready for review
September 11, 2026 07:51
KR-Ravindra
requested review from
cosmicbboy,
davidmirror-ops,
kumare3,
machichima,
pingsutw,
samhita-alla and
wild-endeavor
as code owners
September 11, 2026 07:51
Author
|
Following up after three weeks. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Tracking issue
Closes flyteorg/flyte#6776
Problem
DictTransformerserializes untyped dicts (and typed dicts with non-strkeys) to a msgpack binary scalar. msgpack preserves insertion order, so two dicts that are equal in Python but built in a different key order produce different bytes. flytepropeller hashes the raw literal bytes for the cache key, so logically identical inputs cause spurious cache misses. It shows up in practice with large generated nested config dicts.dict_to_binary_literalencodesvas-is, so the byte layout depends on the caller's insertion order.Fix
Option 2 from the issue discussion — sort before encoding, no new dependency.
_sort_dict_keysreturns a copy with dict keys sorted recursively through nested dicts, lists and tuples, ordered by(type name, key)so mixedint/strkeys can still be ordered; if keys cannot be compared at all the original order is kept, so nothing that encodes today starts failing. It is called right beforeencoder.encode(...).Only dicts, lists and tuples are rewritten. Because the sorted copy is what gets encoded,
to_python_valuereturns keys in sorted rather than insertion order. Dataclasses,FlyteFile,FlyteDirectoryand anything else nested inside are passed through untouched, so mashumaro'sSerializableTypehandling is unchanged, and mashumaro preserves iteration order, so sorting the input is enough to make the output canonical.Scope:
DictTransformeronly. ADict[...]field inside a dataclass goes throughDataclassTransformerand is not changed.test_guess_dict3compared output bytes againstmsgpack.dumps()of the insertion-ordered dict, which no longer holds by design; it now decodes and compares the value, still checking themsgpacktag.test_dict_to_binary_literal_is_independent_of_key_orderasserts two permutations of a nested dict produce byte-identical literals and round-trip correctly, plusDict[int, str]and mixedstr/int/Nonekeys.On the large-dict cost concern from the issue: for a ~200k-leaf dict (2.1 MB msgpack) the sort takes ~78 ms against ~15 ms for the encode — a few times the encode, and well below the network round trips in a task launch.
Check all the applicable boxes
Related PRs
flyteorg/flyte#7075 (closed) explored fixing this in propeller instead.
Links
Yes, AI-assisted; reviewed by me.