Skip to content

Refactor per-channel output and add tests for fetch_all_channels#995

Open
DarshanCode2005 wants to merge 5 commits intoNixOS:mainfrom
DarshanCode2005:unified-channel-output
Open

Refactor per-channel output and add tests for fetch_all_channels#995
DarshanCode2005 wants to merge 5 commits intoNixOS:mainfrom
DarshanCode2005:unified-channel-output

Conversation

@DarshanCode2005
Copy link
Copy Markdown
Contributor

# FIXME(@fricklerhandwerk): Fold that intobranch_info, so there's only one output. print("Parallel fetches results", results)
What’s changed:

  • Cleaner output: Each channel now prints one clear line with its details (release, state, commit) and result (fetched, already present, or error), after all fetches finish.
  • Standard output: Replaced print/pprint with self.stdout.write for proper command output handling.
  • Tests added:
    • 4 unit tests for reporting logic
    • 1 integration test for the full command flow with the database

Copy link
Copy Markdown
Collaborator

@fricklerhandwerk fricklerhandwerk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's some good thinking in it (especially the new test), but I recommend keeping it simple here: Aggregate the data into the collection of dicts and pprint them at the end.

Comment on lines +150 to +151
coros = [repo.update_from_ref(ch.head_sha1_commit) for ch, _ in registered]
results = asyncio.run(wait_for_parallel_fetches(coros))
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That probably also works

Suggested change
coros = [repo.update_from_ref(ch.head_sha1_commit) for ch, _ in registered]
results = asyncio.run(wait_for_parallel_fetches(coros))
results = asyncio.run(wait_for_parallel_fetches(
repo.update_from_ref(ch.head_sha1_commit) for ch, _ in registered
))

},
channel_branch=monitored.name,
)
registered.append((channel, branch_info))
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of repeating all the dict field names, how about instead:

Suggested change
registered.append((channel, branch_info))
report_info = {"channel_branch": channel_branch, **defaults}
registered.append((channel, report_info))

The change can probably be a lot smaller then. I don't think there's much point in renaming the channel iterator variable.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done , passing branch_info directly to update_or_create as the updated dict.

"head_sha1_commit": channel.revision,
"release_version": release_from_branch(channel.name),

# Step 1: register/update all channels in the DB, collect for reporting.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# Step 1: register/update all channels in the DB, collect for reporting.

I generally discourage this sort of comment for two reasons:

  • Which step in a sequence this is may change, and so the comment is likely to drift
  • It doesn't add information. The code doesn't do anything fancy and looking at it for a couple of seconds will explain it fully.

Comments should almost exclusively explain why a non-obvious piece of code is the way it is. Very rarely, if something that should be simple looks complicated, there should be a summary of what it does. This happens sometimes in this codebase where an involved DB query for can't be broken down into procedures with appropriate names (or where such a breakdown would introduce more problems than it would solve). But that's certainly not the case here.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay.

Comment on lines 93 to 96
async def wait_for_parallel_fetches(
parallel_fetches: list[Coroutine[Any, Any, bool]],
parallel_fetches: Sequence[Coroutine[Any, Any, bool]],
) -> list[Any]:
return await asyncio.gather(*parallel_fetches, return_exceptions=True)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Arguably this procedure does nothing on its own, why not inline it while we're at it?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, removed the helper function entirely; asyncio.gather is now called inline inside asyncio.run.

@pytest.mark.django_db
@patch("shared.management.commands.fetch_all_channels.fetch_from_monitoring")
@patch("shared.management.commands.fetch_all_channels.GitRepo")
def test_command_upserts_channels_and_reports_fetch_results(
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a very good test to have!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

Comment on lines +99 to +114
def format_channel_report(
branch_info: dict[str, Any], fetch_result: bool | BaseException
) -> str:
channel = branch_info["channel_branch"]
sha = branch_info["head_sha1_commit"][:12]
state = branch_info["state"]
release = branch_info.get("release_version") or "unstable"

if isinstance(fetch_result, BaseException):
status = f"ERROR ({fetch_result})"
elif fetch_result:
status = "fetched"
else:
status = "already present"

return f"[{channel}] release={release} state={state} commit={sha} -> {status}"
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I imagined something much simpler: Just attach the fetch status to the already existing branch_info dict and pprint that.

Printing a line makes the log less readable, and will need work later to make it machine-readable once we start storing logs.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, okay format_channel_report is gone and pprints the dict directly.

},
channel_branch=monitored.name,
)
registered.append((channel, branch_info))
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're not really using the NixChannel here -- that head_sha1_commit is also in the branch_info dict.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, I've simplified this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants