Skip to content

Status heartbeat - #440

Merged
SimonHeybrock merged 35 commits into
mainfrom
status-heartbeat
Sep 17, 2025
Merged

SimonHeybrock merged 35 commits into
mainfrom
status-heartbeat

Conversation

@SimonHeybrock

@SimonHeybrock SimonHeybrock commented Sep 10, 2025 •

Copy link
Copy Markdown
Member

Add job status heartbeat based on x5f2 messages. Status is used to populate a job status list widget. We also use this to replace the temporary job control widget from an earlier PR.

image

Fixes #436.

I think JobController will needs some more iterations, and I am postponing writing tests for that to a follow-up.

Comment on lines +106 to +108
self._job_status_widget = JobStatusListWidget(
job_service=job_service, job_controller=job_controller
)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Including this in the plotting widget (as first tab) is a hack for now, consider it temporary until we have figured out which UI components should be where, etc.

Base automatically changed from plotting to main September 11, 2025 01:29
@SimonHeybrock
SimonHeybrock marked this pull request as ready for review September 11, 2025 01:36
@jokasimr

Copy link
Copy Markdown
Contributor

Is job status written to Kafka to be visible in Nicos?

@SimonHeybrock

Copy link
Copy Markdown
Member Author

Is job status written to Kafka to be visible in Nicos?

Yes, in principle. They proposed to use this format.

@SimonHeybrock

Copy link
Copy Markdown
Member Author

Merging since it is holding up other work. Please review anyway, comments will be addressed on follow-up.

@SimonHeybrock
SimonHeybrock merged commit a04ffb0 into main Sep 17, 2025
4 checks passed
@SimonHeybrock
SimonHeybrock deleted the status-heartbeat branch September 17, 2025 07:09
@nvaytet nvaytet self-assigned this Sep 18, 2025
Comment thread src/beamlime/core/job.py
error_message: str | None = None
warning_message: str | None = None
start_time: int | None = None
end_time: int | None = None

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Not for now, but might be useful in the future to report things like memory usage in the job status?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Not sure, those things maybe be more suited for the Grafana/Graylog integration.

Comment thread src/beamlime/core/job.py
job_statuses.append(status)
# Track warnings from job operations, or clear them on success
if status.has_error and status.error_message is not None:
self._job_warning_messages[job.job_id] = status.error_message

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I'm sort of getting confused here as to what is an error and what is a warnings (also in the compute_results below)
If I followed correctly, status here is a JobError. But we're putting it in the warning_messages...

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

The name is legacy. Renaming to JobReply and adding comments about the warning/error distinction.

Comment thread src/beamlime/core/job.py

# Determine current state based on job's location in manager
if job_id in self._active_jobs:
if job_id in self._finishing_jobs:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We're having to check in various places if the job is in _finishing_jobs, or in _active_jobs. Can we set the type of job on the job object itself? Would this make things easier?

Maybe it was a way to categorize the jobs so that we don't need to scan all the jobs if we are looking only for fnishing jobs?
Do we expect to have thousands of jobs? If there are only a few jobs running, maybe iterating over all jobs is fast enough?

@SimonHeybrock SimonHeybrock Sep 22, 2025 •

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

There should only be a few jobs (tens maybe).

Can we set the type of job on the job object itself? Would this make things easier?

I pondered exactly that when first implementing it: Should a job (have to) know its status? My conclusion then was "no", the job is a simple wrapper, only the manager needs to know that (because nothing the job does depends on knowing whether it is scheduled, active, paused, ...). But maybe it would be simpler after all? Not so sure, but next time this code is touched we can consider it again?

if status.has_error:
self._logger.error(self._job_manager.format_job_error(status))
for error in job_errors:
if error.has_error:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Maybe related to the comment above about confusion as to what is warning and what is error:
I find it strange that an error potentially does not have an error...

except Exception as e:
self._logger.error("Error in job status update callback: %s", e)

def remove_job(self, job_id: JobId) -> None:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Does the order of steps in the function matter? If so, can you add a comment about it?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

It should not matter, since currently JobManager is designed for single-threaded use.

try:
self._job_list.remove(widget_panel)
except ValueError:
# Panel might not be in the list anymore

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

What happens if Panel is not in the list anymore? Can you describe in which situation this arises?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Adding a comment.

@SimonHeybrock

Copy link
Copy Markdown
Member Author

Comments are addressed in #464.

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.

Split config topic into command and status

4 participants