Skip to content

Add the @task() decorator so task functions can be serialized by reference#143

Merged
gpauloski merged 9 commits intomainfrom
issue-121
Sep 5, 2024
Merged

Add the @task() decorator so task functions can be serialized by reference#143
gpauloski merged 9 commits intomainfrom
issue-121

Conversation

@gpauloski
Copy link
Copy Markdown
Contributor

@gpauloski gpauloski commented Sep 5, 2024

Description

Add the @task() decorator so task functions can be serialized by reference.

This was motivated in #121 by TaskVine's serverless mode wanting to refer to task functions by name, something that was previously not possible because functions were wrapped into Task class instances. Now, task functions defined in the top-level of a module can be mutated into a Task (which is now just a Protocol and all tasks are just functions rather than class instances).

This is fully backwards compatible. This did require some mildly complex logic to (1) ensure decorated functions can still be called like normal functions outside of the executor, (2) the Engine can still accept normal functions (it will internally wrap the function as a task), and (3) to make sure task() can be used as a decorator on a top-level function and to create a new function when the Engine is wrapping a function.

A notable side-effect of this change is that the TaskTransformer is now an argument of a task injected by the Engine. Thus, it is serialized/deserialized along with every method invocation. This was sometimes already the case in the old system if the executor did not cache functions. I expect the impact of this change to be trivial.

This change does add a nice feature that the name of a task can be customized if the name of the function associated with the task does no suffice.

Also fixes a few issues in the test suite:

  • Unreliable coverage in synthetic app.
  • Unsafe use of fork in ProcessPoolExecutor on POSIX platforms.
  • Disabling the Dask dashboard with None is bugged and does not work, so to avoid warnings for already used ports I've set the ports to random.

Fixes

Type of Change

  • Bug (non-breaking change which fixes an issue)
  • Enhancement (non-breaking change which adds or improves functionality)
  • Internal (refactoring, performance, and testing)
  • Breaking (fix or feature that would cause existing functionality to not work as expected)
  • Documentation (no changes to the code)
  • Development (CI workflows, packages, templates, etc.)
  • Package (package dependencies and versions)

Testing

All tests pass, new ones added where needed, and tested the cholesky app.

Pull Request Checklist

Please confirm the PR meets the following requirements.

  • Relevant tags are added (breaking, bug, documentation, enhancement, package, etc.).
  • Code changes pass pre-commit (e.g., ruff, mypy, etc.).
  • Tests have been added to show the fix is effective or that the new feature works.
  • New and existing unit tests pass locally with the changes.
  • Docs have been updated and reviewed if relevant.

Decorating a top-level function with @task would replace the function
with a Task that references the function. However, the Task would be
updated with functools.update_wrapper to look like the function. This
included the __name__ and __module__ which essentially clobbered the
original function so pickling Task would fail because the reference to
the wrapped function did not resolve to the right thing anymore.

This was fixed by switching to decorating with functions only (via
functools' wraps and partial). I.e., there is not Task object now (well
there is but it's just a protocol for what the wrapper functions do).
There's some tricky typing and serialization consequences that I tried
to leave as many comments for and added serializatin and typing tests.
@gpauloski gpauloski added the enhancement New features or improvements to existing functionality label Sep 5, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New features or improvements to existing functionality

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Synthetic app tests occasionally fail coverage Default to @task decorator for app task functions

1 participant