This implements an entirely new architectural flow for the editing of projects, formerly described as Actions by
frontend.py. The new architectural design focuses on describing the effects that should occur when a specific endpoint is triggered. These actions, such as "validate that this project id is owned by this user", or "delete the source with this id", can themselves be composed into larger actions, like "validate this project id is owned by this user, and if it is, delete the source with this id". Each action is itself comprised of a description of an SQL query and code to interpret its results.
The primary benefit of this architectural scheme is improved testability. Because the code describes rather than executes these effects, it means that an SQL database is not required to run any of the tests, and a very high coverage can be achieved without adding test dependencies, the IO delays associated with databases, or any of the complications that surround needing to coordinate external services.
This PR also includes tests for the
queries.py module, although
outcomes.py are both omitted, because these modules are likely to be dropped as part of planned changes to Mystic's code. All code should have documentation attached as well, explaining the purpose of each method.
A brief overview of the major modules added in this PR:
queries.pyis responsible for describing specific queries. This includes the actual SQL statement to run, and code which interprets the results. This is also where various "glue" queries exist, which allow combining several queries together logically.
query_driver.pyis a very small module responsible for executing the queries described by
outcome.pyprovides code which describes various "outcome" effects, such as rebuilding the
projects.json, displaying an error on the page, or sending a job to mystic-coordinator.
outcome_runner.pyis a small module for running the outcomes described by
actions.pyis where these concepts are put into practice. Each "action" is actually a function which returns a composite query. The returned composite query eventually evaluates to an outcome. All endpoints in editing a project can (and are) described in this way. These descriptions are not executed in this module, but rather returned to
views.py, where they are delegated to the query driver and outcome runner.
Review notes for Amy:
You don't have to actually review the code itself, unless you feel like you have a lot of patience or time you want to use. If you do, I'd recommend starting with the very first commit, which is a small scale implementation of this for just a single action. This should help you pick up on the main ideas of the change, and understand the bigger thing easier. That said, you really don't have to do that, and you can just run it and poke around for bugs.
The part to review is really just different ways to submit the "New Project"/"Edit Project" form, because that (POST requests to
/) is predominantly what should be affected by this change.