Skip to content

[SYNPY-1851] Add high level function for creating grids#1423

Open
andrewelamb wants to merge 22 commits into
developfrom
SYNPY-1851
Open

[SYNPY-1851] Add high level function for creating grids#1423
andrewelamb wants to merge 22 commits into
developfrom
SYNPY-1851

Conversation

@andrewelamb

@andrewelamb andrewelamb commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Problem:

A data contributor assigned a CurationTask had no simple, idempotent way to open the Grid for that task. The only option was CurationTask.create_grid_session(), which always creates a brand-new session and re-links it to the task, replacing any session already linked. This made it easy to accidentally start over:

  • Calling it a second time (e.g. to fix validation errors) would discard the existing session and create a fresh one.
  • There was no supported way to fetch a Grid by its session_id alone — the Grid model could be created but not retrieved from Synapse.

Affected code: synapseclient/extensions/curator/, synapseclient/models/curation.py (Grid model), and synapseclient/api/curation_services.py.

Solution:

Add a high-level, get-or-create entry point plus the lower-level pieces it needs:

  • synapseclient.extensions.curator.get_curator_grid(task_id, ...) — the primary addition. It:

    1. Fetches the CurationTask.
    2. Reads the task status for an attached grid session.
    3. If a session is attached, fetches and returns that existing Grid.
    4. If the attached session no longer exists (404), or none is attached, creates a new session, links it to the task, and returns it.

    The first call starts a session; subsequent calls return the same one, so contributors can pick up where they left off without accidentally starting over. record_set_id and authorization mode are taken from the task properties automatically.

  • Grid.get() / Grid.get_async() — retrieve a Grid session from Synapse by its session_id and populate the model via fill_from_dict().

  • get_grid_session() in the API layer — wraps GET /grid/session/{sessionId}.

Non-grid execution details on the task raise a ValueError; a 404 on the linked session is handled by recreating, while any other HTTP error propagates. Docs (metadata_contribution.md and the async/sync curator reference) are updated to steer contributors to get_curator_grid, and the cleanup section now shows how to clear the task's stale session reference after delete().

Testing:

  • Unit tests (tests/unit/synapseclient/extensions/unit_test_get_curator_grid.py) covering every branch of get_curator_grid: create-when-no-session, get-existing-by-id, recreate-on-404, non-404 error propagation, general error propagation, create-when-execution-details-None, and raise-on-non-grid-execution-details.
  • Integration test (tests/integration/.../test_grid_async.py::test_get_grid_session_async) creating a Grid from a record set and re-fetching it via a fresh Grid instance, asserting the round-tripped fields match.

@andrewelamb
andrewelamb requested a review from a team as a code owner July 14, 2026 15:05
@andrewelamb
andrewelamb marked this pull request as draft July 14, 2026 15:05
@andrewelamb
andrewelamb marked this pull request as ready for review July 14, 2026 16:36
@andrewelamb
andrewelamb requested a review from cconrad8 July 14, 2026 16:39

@linglp linglp left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM! I have small design questions but overall it looks good. Thanks for the fixes.

Comment thread synapseclient/extensions/curator/get_grid.py Outdated
### Cleaning up a Grid session

```python
# Delete the grid session

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Nit: I think it's very easy to forget unlinking the grid and the task. What about creating something like CurationTask.delete_active_grid_session_async() that deletes the Grid and clears the link in one coordinated call in the future?

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.

@cconrad8 What do you think?

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.

Alternative is to make get_or_create_curator_grid a context manager that handled this automatically with a boolean flag to not clean up.

That way in the finally you can handle this for the user (The following is not correct code, but just mocking up what it roughly looks like).

try:
    yield latest_grid
finally:
    if cleanup:
        latest_grid.delete()
        
        # Remove the deleted session's reference from the task, so the task no longer
        # points at a session that no longer exists
        status = CurationTask(task_id).get_status()
        status.execution_details = None
        curation_task.update_status(curation_task_status=status)

Comment thread docs/guides/extensions/curator/metadata_contribution.md Outdated
@andrewelamb
andrewelamb requested a review from cconrad8 July 22, 2026 17:03
Comment thread synapseclient/extensions/curator/get_or_create_grid.py Outdated
Comment thread synapseclient/extensions/curator/get_or_create_grid.py
Comment thread synapseclient/extensions/curator/get_or_create_grid.py Outdated
Comment thread tests/unit/synapseclient/extensions/unit_test_get_or_create_curator_grid.py Outdated

@BryanFauble BryanFauble left a comment

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.

There are some changes to make before merging, approving now though.

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.

4 participants