Skip to content

fix(api): include name and arguments in operation hash - #1942

Open
wowi42 wants to merge 3 commits into
pyinfra-dev:3.xfrom
wowi42:fix/1370-op-hash-collision
Open

fix(api): include name and arguments in operation hash#1942
wowi42 wants to merge 3 commits into
pyinfra-dev:3.xfrom
wowi42:fix/1370-op-hash-collision

Conversation

@wowi42

@wowi42 wowi42 commented Aug 31, 2026

Copy link
Copy Markdown
Collaborator

Fixes #1370, implementing the approach from this analysis.

Problem

solve_operation_consistency built the operation hash purely from position (stack lines in CLI mode, per-host index in API mode, plus host.loop_position). Names and arguments were never hashed, and the duplicate-resolution loop only checked the current host's op_hash_order. As a result, different operations at the same position (eg calls in a plain for loop with per-host data) collapsed into a single hash:

  • ensure_shared_op_meta unioned their names into one set, so the "Detected changes" output showed a nondeterministic name and merged host counts
  • if the colliding operations differed on _parallel, _run_once or _serial, the deploy died with OperationValueError: Cannot have different values for ...
  • _run_once semantics broke, running the merged op on the first host only

Fix

Hash the operation names and arguments (normalized via _get_arg_value, so functions and StringIO stay deterministic) alongside the position. Different operations at the same position now get distinct hashes, while identical operations across hosts still share one hash, keeping cross-host dedup and _run_once/_serial/_parallel grouping intact. The same-host duplicate suffix behavior (hash-0, hash-0-1, ...) is unchanged.

Tests

  • test_op_per_host_data_no_hash_collision - per-host named ops get distinct hashes; identical ops still share one
  • test_op_per_host_args_no_name_no_hash_collision - same op/position with per-host args but no explicit name=
  • test_op_per_host_data_different_execution_kwargs - no false OperationValueError for distinct ops with different _parallel
  • test_cli_op_loop_per_host_data_no_hash_collision - exact issue repro in CLI mode (plain loop, same line)
  • test_cli_op_loop_identical_ops_dedupe - identical same-line loop calls still dedupe via hash suffixes

All collision tests fail on the old code; the dedup test passes on both.

wowi42 added 2 commits August 31, 2026 16:13
Operations at the same position (eg calls in a plain loop with per-host
data) previously shared one hash, merging their names and host counts in
the detected changes output and breaking _run_once/_parallel semantics.

Hash the operation names and arguments alongside the call position so
distinct operations get distinct hashes, while identical operations
across hosts still share one.

Fixes pyinfra-dev#1370
@wowi42 wowi42 added bug Label for all kind of bugs. API API mode specific issues. labels Aug 31, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

API API mode specific issues. bug Label for all kind of bugs.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Detected changed across mulitple hosts are wrong

1 participant