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

Add event serialization testing #9573

Open
wants to merge 5 commits into
base: main
Choose a base branch
from

Conversation

DanSava
Copy link
Contributor

@DanSava DanSava commented Dec 17, 2024

Issue
Resolves #9517

Approach
Add serialization roundtrip for all events generated by EverestRunModel

  • PR title captures the intent of the changes, and is fitting for release notes.
  • Added appropriate release note label
  • Commit history is consistent and clean, in line with the contribution guidelines.
  • Make sure unit tests pass locally after every commit (git rebase -i main --exec 'pytest tests/ert/unit_tests -n logical -m "not integration_test"')

When applicable

  • When there are user facing changes: Updated documentation
  • New behavior or changes to existing untested code: Ensured that unit tests are added (See Ground Rules).
  • Large PR: Prepare changes in small commits for more convenient review
  • Bug fix: Add regression test for the bug
  • Bug fix: Create Backport PR to latest release

@DanSava DanSava self-assigned this Dec 17, 2024
@codecov-commenter
Copy link

codecov-commenter commented Dec 17, 2024

Codecov Report

Attention: Patch coverage is 96.77419% with 2 lines in your changes missing coverage. Please review.

Project coverage is 91.74%. Comparing base (790933d) to head (9cfb9d8).
Report is 48 commits behind head on main.

Files with missing lines Patch % Lines
src/ert/ensemble_evaluator/snapshot.py 94.11% 1 Missing ⚠️
src/ert/run_models/event.py 97.67% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #9573      +/-   ##
==========================================
+ Coverage   91.71%   91.74%   +0.02%     
==========================================
  Files         429      426       -3     
  Lines       26672    26589      -83     
==========================================
- Hits        24463    24393      -70     
+ Misses       2209     2196      -13     
Flag Coverage Δ
cli-tests 39.80% <41.93%> (+0.09%) ⬆️
everest-models-test 34.16% <40.32%> (+0.02%) ⬆️
gui-tests 74.23% <41.93%> (+2.42%) ⬆️
integration-test 37.98% <40.32%> (-0.29%) ⬇️
performance-tests 51.55% <41.93%> (-0.11%) ⬇️
test 39.52% <40.32%> (-0.05%) ⬇️
unit-tests 74.27% <96.77%> (+0.28%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link

codspeed-hq bot commented Dec 17, 2024

CodSpeed Performance Report

Merging #9573 will degrade performances by 10.59%

Comparing DanSava:test-event-serialization (9cfb9d8) with main (7b2bedf)

Summary

❌ 1 regressions
✅ 23 untouched benchmarks

⚠️ Please fix the performance issues or acknowledge them on CodSpeed.

Benchmarks breakdown

Benchmark main DanSava:test-event-serialization Change
test_direct_dark_performance_with_storage[gen_x: 20, sum_x: 20 reals: 10-summary-get_record_observations] 1.3 ms 1.5 ms -10.59%

@DanSava DanSava force-pushed the test-event-serialization branch from 261b703 to bdac9c6 Compare December 17, 2024 14:02
@DanSava DanSava force-pushed the test-event-serialization branch 4 times, most recently from 9281d76 to 7089a3b Compare January 8, 2025 11:26
@DanSava DanSava force-pushed the test-event-serialization branch from 7089a3b to 9c6ec15 Compare January 8, 2025 12:55
@DanSava DanSava added the release-notes:improvement Automatically categorise as improvement in release notes label Jan 10, 2025
Copy link
Collaborator

@oyvindeide oyvindeide left a comment

Choose a reason for hiding this comment

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

Looks good! Some suggestions and questions

Comment on lines +404 to +410
start_time = source.get("start_time")
if start_time and isinstance(start_time, str):
start_time = datetime.fromisoformat(start_time)
end_time = source.get("end_time")
if end_time and isinstance(end_time, str):
end_time = datetime.fromisoformat(end_time)

Copy link
Collaborator

Choose a reason for hiding this comment

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

Where does this not happen? Seems like we mostly do:

def convert_iso8601_to_datetime(
    timestamp: datetime | str,
) -> datetime:
    if isinstance(timestamp, datetime):
        return timestamp

    return datetime.fromisoformat(timestamp)

Comment on lines +420 to +424
for step in realization["fm_steps"].values():
if "start_time" in step and isinstance(step["start_time"], str):
step["start_time"] = datetime.fromisoformat(step["start_time"])
if "end_time" in step and isinstance(step["end_time"], str):
step["end_time"] = datetime.fromisoformat(step["end_time"])
Copy link
Collaborator

Choose a reason for hiding this comment

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

Same comment here, should perhaps do it on the sender side?

Comment on lines +110 to +131
match event_type:
case FullSnapshotEvent.__name__:
snapshot = EnsembleSnapshot.from_nested_dict(json_dict["snapshot"])
json_dict["snapshot"] = snapshot
return FullSnapshotEvent(**json_dict)
case SnapshotUpdateEvent.__name__:
snapshot = EnsembleSnapshot.from_nested_dict(json_dict["snapshot"])
json_dict["snapshot"] = snapshot
return SnapshotUpdateEvent(**json_dict)
case RunModelDataEvent.__name__ | RunModelUpdateEndEvent.__name__:
if "run_id" in json_dict and isinstance(json_dict["run_id"], str):
json_dict["run_id"] = UUID(json_dict["run_id"])
if json_dict.get("data"):
json_dict["data"] = DataSection(**json_dict["data"])
return EVENT_MAPPING[event_type](**json_dict)
case _:
if event_type in EVENT_MAPPING:
if "run_id" in json_dict and isinstance(json_dict["run_id"], str):
json_dict["run_id"] = UUID(json_dict["run_id"])
return EVENT_MAPPING[event_type](**json_dict)
else:
raise TypeError(f"Unknown status event type {event_type}")
Copy link
Collaborator

Choose a reason for hiding this comment

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

Think this could also be done by pydantic directly?
for example:

class EventWrapper(BaseModel):
    model_config = ConfigDict(arbitrary_types_allowed=True)
    event: Annotated[StatusEvents, Field(discriminator='event_type')]

event_dict.update(
{
"snapshot": event.snapshot.to_dict(),
"event_type": event.__class__.__name__,
Copy link
Collaborator

Choose a reason for hiding this comment

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

Might be better to add this directly to the events?

event_type: Literal['FullSnapshotEvent'] = 'FullSnapshotEvent'

the pro is it is more explicit, but on the flip side it is more verbose and has to be kept in sync for all events 🤔

raise TypeError(f"Unknown status event type {event_type}")


def status_event_to_json(event: StatusEvents) -> str:
Copy link
Collaborator

Choose a reason for hiding this comment

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

In my PR I did:

await websocket.send_json(event)

so did not need a custom function, is that needed? It just takes StatusEvents:

StatusEvents = Union[
    FullSnapshotEvent,
    SnapshotUpdateEvent,
    EndEvent,
    AnalysisStatusEvent,
    AnalysisTimeEvent,
    AnalysisReportEvent,
    RunModelErrorEvent,
    RunModelStatusEvent,
    RunModelTimeEvent,
    RunModelUpdateBeginEvent,
    RunModelDataEvent,
    RunModelUpdateEndEvent,
]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
release-notes:improvement Automatically categorise as improvement in release notes
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Make sure events can be serialized
3 participants