Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DATAUP-765: add user and wsid to job output #3386

Merged
merged 1 commit into from
Nov 16, 2023

Conversation

ialarmedalien
Copy link
Collaborator

Description of PR purpose/changes

This PR adds the user and wsid to the job objects returned by the narrative backend.

I added typing to quite a few of the methods so the diff looks bigger than it really is.

There's still some dodgy stuff going on with the job methods, but whatever. That can go in the next PR!

Jira Ticket / Issue

Related Jira ticket: https://kbase-jira.atlassian.net/browse/DATAUP-765

  • Added the Jira Ticket to the title of the PR (e.g. DATAUP-69 Adds a PR template)

Testing Instructions

  • Details for how to test the PR:
  • Tests pass locally and in GitHub Actions

Dev Checklist:

  • My code follows the guidelines at https://sites.google.com/lbl.gov/trussresources/home?authuser=0
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes
  • [] (JavaScript) I have run Prettier and ESLint on changed code manually or with a git precommit hook
  • (Python) I have run Black and Flake8 on changed Python code manually or with a git precommit hook
  • [] Any dependent changes have been merged and published in downstream modules

Updating Version and Release Notes (if applicable)

@ialarmedalien ialarmedalien self-assigned this Nov 9, 2023
# run_id (str): unique run ID for the job
# status (str): EE2 job status
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

no idea why this pretty important attribute was omitted!

extra_data: dict[str, Any] | None = None,
children: list["Job"] | None = None,
):
state = cls.query_ee2_states([job_id], init=True)
Copy link
Collaborator Author

@ialarmedalien ialarmedalien Nov 9, 2023

Choose a reason for hiding this comment

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

Use the plural form, query_ee2_states, so that the singular form can be removed.

Comment on lines -131 to -132
@staticmethod
def _trim_ee2_state(state: dict, exclude_fields: list) -> None:
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

moved down the file a bit

Comment on lines +183 to +160
@staticmethod
def _trim_ee2_state(
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

moved (but not changed)

# TODO
# Only batch container jobs have a child_jobs field
# and need the state refresh.
# But KBParallel/KB Batch App jobs may not have the
# batch_job field
self.refresh_state(force_refresh=True).get(
self.refresh_state(force_refresh=force_refresh).get(
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

this is deeply annoying to me. Why have a refresh_state method if you're not going to refresh the state?!

"""
Returns the parameters used to start the job. Job tries to use its params field, but
if that's None, then it makes a call to EE2.

If no exception is raised, this only returns the list of parameters, NOT the whole
object fetched from ee2.check_job
"""
if self.params is not None:
return self.params
if self.params is None:
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

slight rearrangement of the logic

Comment on lines +380 to +334
state = self.query_ee2_states([self.job_id], init=False)
self.update_state(state[self.job_id])
Copy link
Collaborator Author

@ialarmedalien ialarmedalien Nov 9, 2023

Choose a reason for hiding this comment

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

use plural form, query_ee2_states

Comment on lines -319 to -321
if self._acc_state is None:
self._acc_state = {}

Copy link
Collaborator Author

@ialarmedalien ialarmedalien Nov 9, 2023

Choose a reason for hiding this comment

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

self._acc_state is set during __init__() so will never be None

"""Wrapper for self._acc_state"""
state = copy.deepcopy(self._acc_state)
self._trim_ee2_state(state, exclude_fields)
return state

def output_state(self, state=None, no_refresh=False) -> dict:
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

change output_state so that it no longer merges in a fetched state; now the state merge is done by running update_state beforehand

self.update_state(state)
state = self.cached_state()

if state is None:
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

No way that state can be None with the new logic as self.cached_state() fetches self._acc_state, which always has something populated.

Comment on lines 460 to 461
# calling child_jobs may force an undesired data refresh even if
# refresh is set to False
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

this is a bug in the current implementation

@@ -67,7 +67,7 @@ class JobRequest:

INPUT_TYPES = [PARAM["JOB_ID"], PARAM["JOB_ID_LIST"], PARAM["BATCH_ID"]]

def __init__(self, rq: dict):
def __init__(self: "JobRequest", rq: dict):
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

all edits to this file are adding typing

Copy link

codecov bot commented Nov 9, 2023

Codecov Report

Merging #3386 (4faae24) into develop (04c80b2) will increase coverage by 0.01%.
Report is 1 commits behind head on develop.
The diff coverage is 92.35%.

❗ Current head 4faae24 differs from pull request most recent head b982e48. Consider uploading reports for the commit b982e48 to get more accurate results

Additional details and impacted files

Impacted file tree graph

@@             Coverage Diff             @@
##           develop    #3386      +/-   ##
===========================================
+ Coverage    29.34%   29.35%   +0.01%     
===========================================
  Files          497      497              
  Lines        50580    50569      -11     
===========================================
+ Hits         14841    14843       +2     
+ Misses       35739    35726      -13     
Files Coverage Δ
src/biokbase/narrative/jobs/appmanager.py 91.96% <100.00%> (+0.02%) ⬆️
src/biokbase/narrative/jobs/jobcomm.py 98.96% <100.00%> (ø)
src/biokbase/narrative/jobs/job.py 92.34% <98.30%> (-0.96%) ⬇️
src/biokbase/narrative/jobs/jobmanager.py 95.39% <95.23%> (+0.01%) ⬆️
...s/widgets/function_output/kbaseGenericSetViewer.js 0.00% <0.00%> (ø)

... and 2 files with indirect coverage changes


Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update a37bd72...b982e48. Read the comment docs.

Comment on lines 296 to 297
job.update_state(states[job_id])
output_states[job_id] = job.output_state(refresh=False)
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

update the job state and then retrieve the version suitable for output

@@ -6,7 +6,8 @@
import random
import re
import traceback
from typing import Callable, Optional
from collections.abc import Callable
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

all changes in this file are adding typing

Copy link
Member

Choose a reason for hiding this comment

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

Why the switch from using Optional?

Copy link
Collaborator Author

@ialarmedalien ialarmedalien Nov 16, 2023

Choose a reason for hiding this comment

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

Ruff likes type | None rather than Optional[type]

del state[field]

@staticmethod
def query_ee2_state(
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

delete this method, replace all uses with query_ee2_states

@@ -193,52 +188,59 @@ def __getattr__(self, name):
"cell_id": lambda: self._acc_state.get("job_input", {})
.get("narrative_cell_info", {})
.get("cell_id", JOB_ATTR_DEFAULTS["cell_id"]),
"child_jobs": lambda: copy.deepcopy(
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

moved down

"job_id": lambda: self._acc_state.get("job_id"),
"params": lambda: copy.deepcopy(
self._acc_state.get("job_input", {}).get(
"params", JOB_ATTR_DEFAULTS["params"]
)
),
"retry_ids": lambda: copy.deepcopy(
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

moved down

"retry_ids", JOB_ATTR_DEFAULTS["retry_ids"]
)
),
"status": lambda force_refresh=True: copy.deepcopy(
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

new

return "batch" if self.batch_job else self.app_spec()["info"]["name"]

def was_terminal(self):
def in_terminal_state(self: "Job") -> bool:
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

renamed method

Comment on lines +411 to +412
if "child_jobs" not in state:
state["child_jobs"] = JOB_ATTR_DEFAULTS["child_jobs"]
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

access via JOB_ATTR_DEFAULTS or otherwise there'll be an unnecessary call to ee2

from typing import List, Union

from ipykernel.comm import Comm
from typing import Union
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Nearly all typing additions; there are a few minor edits which I will comment on.

@@ -21,6 +20,8 @@

LOOKUP_TIMER_INTERVAL = 5

INPUT_TYPES = [PARAM["JOB_ID"], PARAM["JOB_ID_LIST"], PARAM["BATCH_ID"]]
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

move out of the JobRequest class

Comment on lines +292 to +296
if job.in_terminal_state():
# job is already finished, will not change
output_states[job_id] = job.output_state()
elif job_id in states:
job.update_state(states[job_id])
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

edit this to update the job state and then call output_state()

Comment on lines +321 to +322
job.update_state(fetched_states[job_id])
output_states[job_id] = job.output_state()
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

again, update the state and then get the output state

Comment on lines +371 to +375
jobs_to_lookup = [
job_id
for job_id in self._running_jobs
if self._running_jobs[job_id]["refresh"] or ignore_refresh_flag
]
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

use a list comprehension

@@ -518,27 +535,27 @@ def get_job_logs(
logs = logs[first_line:]
else:
(max_lines, logs) = job.log(first_line=first_line, num_lines=num_lines)

except Exception as e:
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

minor reorganisation of logic

Comment on lines +411 to +412
},
"wsid": 10538
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

add the WSIDs into these results

lines.append({"is_error": 0, "line": f"This is line {str(i+1)}"})
return lines
def log_gen(n_lines: int) -> list[dict[str, int | str]]:
return [{"is_error": 0, "line": f"This is line {i+1}"} for i in range(n_lines)]
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

use list comprehension

job_state = self.job_state_data.get(
job_id, {"job_id": job_id, "status": "unmocked"}
)
job_state = self.job_state_data.get(job_id, {"job_id": job_id})
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

a default is supplied for "status", so we don't need the "unmocked" status value any more

job.refresh_state()

def test_refresh_state__returns_none(self):
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

this is no longer relevant as there's no way to provoke this error.

@@ -248,6 +242,12 @@ def mock_check_jobs(params):
# expect there to be an error message added
expected[job_id]["error"] = exc_msg

def mock_check_jobs(params):
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

moved this code down a bit

Copy link
Member

@briehl briehl left a comment

Choose a reason for hiding this comment

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

I'm not sure if the GenericSetViewer code changes were intended in this PR, but there's a couple minor things with them.

this.genericClient = new GenericClient(Config.url('service_wizard'), {
token: this.authToken(),
});

const bare_type = this.options._obj_info.bare_type[0];
const method = this.methodMap[bare_type];
const method = this.methodMap[bare_type]
Copy link
Member

Choose a reason for hiding this comment

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

semicolon?

@@ -6,7 +6,8 @@
import random
import re
import traceback
from typing import Callable, Optional
from collections.abc import Callable
Copy link
Member

Choose a reason for hiding this comment

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

Why the switch from using Optional?

console.warn('no _obj_info: input was')
console.warn(options)
return
// if (options.obj_ref && options.wsName) {
Copy link
Member

Choose a reason for hiding this comment

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

This can probably be removed, as it's basically there below.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This was an accidental commit from something else I was troubleshooting. Not sure why I didn't see it when I was reviewing the PR! I'll remove it.

Removing some comments and an extraneous method; general tidying
Copy link

sonarcloud bot commented Nov 16, 2023

Kudos, SonarCloud Quality Gate passed!    Quality Gate passed

Bug A 0 Bugs
Vulnerability A 0 Vulnerabilities
Security Hotspot A 0 Security Hotspots
Code Smell A 3 Code Smells

No Coverage information No Coverage information
0.0% 0.0% Duplication

Copy link
Member

@briehl briehl left a comment

Choose a reason for hiding this comment

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

👍

@briehl
Copy link
Member

briehl commented Nov 16, 2023

Looks like the upload to codecov failed. AGAIN.

@ialarmedalien ialarmedalien merged commit 16b4c20 into develop Nov 16, 2023
6 of 9 checks passed
@ialarmedalien ialarmedalien deleted the DATAUP-765_add_wsid_to_job branch November 16, 2023 17:35
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