Skip to content

Proposed High Level Outline for Deprecating the ActorStack

Jeremy Friesen edited this page Sep 22, 2020 · 8 revisions

The goal of this refactor is to remove the case logic around the create_work and update_work methods in the Hyrax::WorksControllerBehavior module. Aspirationally, we would factor away the actor stack in favor of a form and transaction.

Below is an example of the two logic paths, one for ActiveFedora::Base objects and one for everything elses (e.g. Valkyrie objects).

# See ./app/controllers/concerns/hyrax/works_controller_behavior.rb
def create_work
  case curation_concern
  when ActiveFedora::Base
    # I copied the following two lines to provide more context for the example
    actor_environment = Actors::Environment.new(curation_concern, current_ability, attributes_for_actor)
    actor = Hyrax::CurationConcern.actor

    actor.create(actor_environment)
  else
    # I copied the following two lines to provide more context for the example
    transactions = Hyrax::Transactions::Container
    form = work_form_service.build(curation_concern, current_ability, self)

    @curation_concern = form.validate(params[hash_key_for_curation_concern]) &&
                        transactions['change_set.create_work'].call(form).value!
  end
end

For ActiveFedora::Base we build the actor_environment, analogue to Rack middleware’s env. With that environment we tell the actor to perform a create. The actor is responsible for both data validation and performing any other state changing processes.

Multiple actors compose the stack (see ./app/services/hyrax/default_middleware_stack.rb). Each actor implements a create and update method that receives the actor_environment.

The pattern of each actor is as follows: validate && next_actor.act && do_something.

  1. Validates the given actor environment based on the current actor’s “area of focus”
    1. Add errors if not valid
  2. If valid, calls the next step in the actor stack
  3. If the called next step is true, perform state changing operations based on “area of focus”

With multiple actors in the stack, as we work our way down the stack, we stop at the first encountered error.

If we work our way down to the bottom of the stack, without errors, we begin applying state changing operations as we traverse back up the stack. During this process we hope to not encounter errors/exceptions, as this will leave our data in a partially changed state (e.g. we have minimal transactionality).

For the other case (e.g. not ActiveFedora::Base), we separate the validations (e.g. form.validate)from the state changing operations (e.g. transactions[‘change_set.create_work’].call(form)).

Aspirationally, we want the form.validate to perform the same-ish validations as the actor stack steps. Likewise, when we use the named transaction (e.g. transactions[‘change_set.create_work’]) we want to perform the same-ish state changing processes as the actor stack steps.

From ./app/services/hyrax/default_middleware_stack.rb we have the following actors:

  • Hyrax::Actors::OptimisticLockValidator
  • Hyrax::Actors::CreateWithRemoteFilesActor
  • Hyrax::Actors::CreateWithFilesActor
  • Hyrax::Actors::CollectionsMembershipActor
  • Hyrax::Actors::AddToWorkActor
  • Hyrax::Actors::AttachMembersActor
  • Hyrax::Actors::ApplyOrderActor
  • Hyrax::Actors::DefaultAdminSetActor
  • Hyrax::Actors::InterpretVisibilityActor
  • Hyrax::Actors::TransferRequestActor
  • Hyrax::Actors::ApplyPermissionTemplateActor
  • Hyrax::Actors::CleanupFileSetsActor
  • Hyrax::Actors::CleanupTrophiesActor
  • Hyrax::Actors::FeaturedWorkActor
  • Hyrax::Actors::ModelActor
  • Hyrax::Actors::InitializeWorkflowActor

These need to be teased their validations extracted into a form object, and their state changing actions extracted into a transaction object.

Clone this wiki locally