Skip to content

fix: make silent job and peer failures visible and actionable - #9497

Open
pjwerneck wants to merge 15 commits into
devfrom
pjwerneck/fix-silent-failures
Open

fix: make silent job and peer failures visible and actionable#9497
pjwerneck wants to merge 15 commits into
devfrom
pjwerneck/fix-silent-failures

Conversation

@pjwerneck

Copy link
Copy Markdown
Collaborator

Summary

Make silent job and peer failures visible and actionable

Changes

  • jobs[N] now matches the [N] shown in the table; jobs["name"] raises on an ambiguous name instead of returning the wrong job
  • process_approved_jobs reports every approved job it skipped, and skips on (job_name, ds_email) so same-named jobs from other submitters still run
  • syft_job, syft_rds, syft_enclaves and syft_bg configure their own loggers
  • "No public encryption bundle" names the cause and remedy per peer state
  • approve_job checks for the approval file first; JobInfo file listings catch OSError; approve/reject errors name both parties

Testing

- jobs[N] now matches the [N] shown in the table; jobs["name"] raises on an  ambiguous name instead of returning the wrong job
- process_approved_jobs reports every approved job it skipped, and skips on  (job_name, ds_email) so same-named jobs from other submitters still run
- syft_job, syft_rds, syft_enclaves and syft_bg configure their own loggers
- "No public encryption bundle" names the cause and remedy per peer state
- approve_job checks for the approval file first; JobInfo file listings catch OSError; approve/reject errors name both parties
chore: land syft-pr-review skill update on this branch for testing
chore: land prefetch.sh .claude exclusion on this branch
Both were code standards that already said the right thing and were applied
too loosely.

The naming standard covered test names only; it now covers any name, and
pins the output to the name, what it breaks, and the rename — nothing else.

The duplication standard said 'functions or methods' and was still fired on a
couple of repeated lines, so it now says so outright: it never fires on lines.
chore: land naming/duplication standard update on this branch
… findings

Two over-corrections from the previous commit.

The duplication floor said 'never on lines', which is stronger than intended:
a repeated line or two is not worth flagging, but a big enough copied block
still is, whether or not it is a whole function.

The naming finding was pinned to an 'old - violation - new' dash form. A plain
sentence is what was asked for: 'x() violates the no-filler rule, rename to
y()'.
chore: land naming/duplication corrections on this branch
@koenvanderveen
koenvanderveen marked this pull request as ready for review September 2, 2026 15:15

@koenvanderveen koenvanderveen left a comment

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.

Comment thread .claude/skills/syft-pr-review/SKILL.md Outdated
def job_sort_key(job):
# Parse submitted_at timestamp for sorting (most recent first)
# Root owner first, then peers, newest-first within each owner.
# This list is the authority for both jobs[N] and the table's [N].

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.

JobClient.jobs is now the single authority for order — own datasite first, then owner email, then newest — and both the printed [N] and jobs[N] read that one list, so they agree.

I think in general we need 1) a deterministic way to get job X from user Y, ideally client.jobs["a@b.org"]["<jobname>"], and 2) to use that in the hints.

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.

because fixing the hints kind of solve a problem that shouldnt exist in the first place: no deterministic way to get a job handle, we may sometimes use the shorthand but we shouldnt all the time. If we can assert that there is no @ in a job name, we would know whether a passed arg is an email or a job name, filter on emails first and then filter on job name, which should be unique for that user

@pjwerneck pjwerneck Sep 3, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Done. jobs["do@org.com"]["analysis"]. An @ in the key means datasite, so validate_job_name rejects @ in new job names now, as you suggested, but it handles existing ones. I added a deprecation warning.

Chaining a second email narrows to the ds when a name is duplicated among submitters, so jobs["do@x"]["ds1@y"]["analysis"] disambiguates.

if not approval_file.exists():
print(
"🟠 Approval file does not exist yet. Kindly wait until enclave sends it."
raise FileNotFoundError(

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.

SyftEnclaveClient.approve_job() now checks the per-party approval file first and raises FileNotFoundError naming the data owner and the job, before job.approve() runs.

Does this pre-check really solve anything?

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.

Perhaps we could also still write a ticket about this specifically. I think the main problem is that we need for the enclave before we can approve but changing that would mean changing the whole design around enclave jobs

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

You're right. It's not really solving anything here. EnclaveJobInfo.approve() is already refusing when the file was missing. The pre-check only changed the message and exception type. Dropped it. Kept Permissionerror as it was before.

Comment thread packages/syft-job/src/syft_job/job.py Outdated
f"Current job is in {self.datasite_owner_email}'s folder."
f"You are {self.current_user_email}, and job '{self.name}' is on "
f"{self.datasite_owner_email}'s datasite. Only they can approve "
f"it. If you meant one of your own, index it by name: "

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.

The error raised when JobInfo.approve() is called on a job that sits on a peer's datasite now suggests indexing by name instead.

I don't get it — why would indexing by name always give your own job?

@pjwerneck pjwerneck Sep 3, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Correct. With the other correction from above, it now says jobs["<your own email>"]["<name>"]. An email key keeps the jobs it is a party to, so naming yourself keeps your own datasite's jobs and the keys can only resolve there.

assert do_client.jobs[0].status == "failed"


def test_jobs_table_hint_uses_name_based_indexing(tmp_path: Path):

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 file adds ten tests built from JobClient and SyftJobRunner over a tmp_path SyftBox folder; four of them are about the hint under the jobs table.

Perhaps we should isolate the hint tests in their own file.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Done.

# The state a data owner hits when the enclave has not distributed yet.
approval_file.unlink()

with pytest.raises(FileNotFoundError) as exc:

@koenvanderveen koenvanderveen Sep 3, 2026

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 deletes the per-party approval file the enclave writes, and asserts SyftEnclaveClient.approve_job() raises FileNotFoundError naming the data owner, the job and client.sync().

A missing approval file shouldn't crash the enclave, and we should double check if thats the case

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Checked. The enclave never calls approve_job, and EnclaveRunner.tick() does not let exceptions propagate anyway.

It can't crash the enclave, but I moved the tests to test_enclave_job_info.py, testing EnclaveJobInfo.approve() so it doesn't imply otherwise.

Comment thread packages/syft-job/tests/test_job_flow.py Outdated
Comment thread packages/syft-enclave/tests/test_enclave_jobs.py Outdated
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants