-
Notifications
You must be signed in to change notification settings - Fork 8
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
Y24-396: Refactor Automatic State Changers #2044
Open
StephenHulme
wants to merge
18
commits into
y24-088-tuberacks-epic
Choose a base branch
from
y24-396-refactor-state-changes-using-mixins
base: y24-088-tuberacks-epic
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
18 commits
Select commit
Hold shift + click to select a range
0f7e5f1
refactor: convert AutomaticBehaviour from a class to a mixin module
StephenHulme cc7244d
tests: refactor tests to match refactored state changes
StephenHulme 6c1916e
tests: refactor to pull out AutomaticPlateStateChanger as shared example
StephenHulme 01706b5
tests: add tests for TubeStateChanger
StephenHulme f0590e1
tests: add tests for AutomaticTubeStateChanger
StephenHulme 1c1d102
tests: expand stub_v2_tube to duplicate stub_v2_plate
StephenHulme 0750b3a
tests: return v2_tube for automated state changers
StephenHulme 43ff5b9
tests: use a better fort of tube purpose
StephenHulme a067948
refactor: rename variable for increased clarity
StephenHulme 1a445c2
tests: use consistent library name of limber_bespoke_aggregation
StephenHulme ce90421
refactor: replace DefaultStateChanger with PlateStateChanger
StephenHulme a5bfc7a
fix: repair refactoring regressions
StephenHulme 857bdf2
Merge branch 'develop' into y24-396-refactor-state-changes-using-mixins
StephenHulme 4a5018d
Merge branch 'y24-088-tuberacks-epic' into y24-396-refactor-state-cha…
StephenHulme a265c2e
tests: refactor state changers spec to describe each class
StephenHulme 6336534
tests: add test for tube state changer
StephenHulme 08c7851
style: remove abstract method errors from coverage
StephenHulme 4d724e1
tests: remove references to tube aggregation
StephenHulme File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,16 +1,67 @@ | ||
# frozen_string_literal: true | ||
|
||
# A State changer is responsible for transitioning the state of a plate, or | ||
# individual wells. | ||
# A State changer is responsible for transitioning the state of labware and its receptacles where applicable. | ||
# | ||
# Hierarchy: | ||
# - BaseStateChanger | ||
# - PlateStateChanger | ||
# - AutomaticPlateStateChanger [includes AutomaticBehaviour] | ||
# - TubeRackStateChanger | ||
# - AutomaticTubeRackStateChanger [includes AutomaticBehaviour] | ||
# - TubeStateChanger | ||
# - AutomaticTubeStateChanger [includes AutomaticBehaviour] | ||
# | ||
module StateChangers | ||
class StateChangeError < StandardError | ||
def self.lookup_for(purpose_uuid) | ||
(details = Settings.purposes[purpose_uuid]) || raise("Unknown purpose UUID: #{purpose_uuid}") | ||
details[:state_changer_class].constantize | ||
end | ||
|
||
# The Default State changer is used by the vast majority of plates. It creates | ||
# a simple StateChange record in Sequencescape, specifying the new 'target-state' | ||
# As a result, Sequencescape will attempt to transition the entire plate, or the | ||
# specified wells. | ||
class DefaultStateChanger | ||
# Plate state changer to automatically complete specified work requests. | ||
# This is the abstract behaviour. | ||
# | ||
# Must include v2_labware method in the including class | ||
module AutomaticBehaviour | ||
def purpose_uuid | ||
@purpose_uuid ||= v2_labware.purpose.uuid | ||
end | ||
|
||
def purpose_config | ||
@purpose_config ||= Settings.purposes[purpose_uuid] | ||
end | ||
|
||
def work_completion_request_types | ||
@work_completion_request_types ||= parse_work_completion_request_types | ||
end | ||
|
||
# config can be a single request type or an array of request types | ||
# convert them here into a consistent array format | ||
def parse_work_completion_request_types | ||
config = purpose_config[:work_completion_request_type] | ||
return config if config.is_a?(Array) | ||
|
||
[config] | ||
end | ||
|
||
# rubocop:todo Style/OptionalBooleanParameter | ||
def move_to!(state, reason = nil, customer_accepts_responsibility = false) | ||
super | ||
complete_outstanding_requests | ||
end | ||
|
||
# rubocop:enable Style/OptionalBooleanParameter | ||
|
||
def complete_outstanding_requests | ||
in_progress_submission_uuids = | ||
v2_labware.in_progress_submission_uuids(request_types_to_complete: work_completion_request_types) | ||
return if in_progress_submission_uuids.blank? | ||
|
||
api.work_completion.create!(submissions: in_progress_submission_uuids, target: v2_labware.uuid, user: user_uuid) | ||
end | ||
end | ||
|
||
# The Base state changer that contains common behaviour for all state changers. | ||
class BaseStateChanger | ||
attr_reader :labware_uuid, :api, :user_uuid | ||
private :api | ||
|
||
|
@@ -55,6 +106,20 @@ | |
# | ||
# @param target_state [String] the state to check against the FILTER_FAILS_ON list | ||
# @return [Array<String>, nil] an array of well locations requiring the state change, or nil if no change is needed | ||
def contents_for(_target_state) | ||
raise 'Must be implemented on subclass' # pragma: no cover | ||
end | ||
|
||
def labware | ||
raise 'Must be implemented on subclass' # pragma: no cover | ||
end | ||
end | ||
|
||
# The Plate State changer is used by the vast majority of plates. It creates | ||
# a simple StateChange record in Sequencescape, specifying the new 'target-state' | ||
# As a result, Sequencescape will attempt to transition the entire plate, or the | ||
# specified wells. | ||
class PlateStateChanger < BaseStateChanger | ||
def contents_for(target_state) | ||
return nil unless FILTER_FAILS_ON.include?(target_state) | ||
|
||
|
@@ -72,14 +137,9 @@ | |
end | ||
end | ||
|
||
def self.lookup_for(purpose_uuid) | ||
(details = Settings.purposes[purpose_uuid]) || raise("Unknown purpose UUID: #{purpose_uuid}") | ||
details[:state_changer_class].constantize | ||
end | ||
|
||
# The tube rack state changer is used by TubeRacks. | ||
# It contains racked tubes. | ||
class TubeRackStateChanger < DefaultStateChanger | ||
class TubeRackStateChanger < BaseStateChanger | ||
# This method determines the coordinates of tubes that require a state change based on the target state. | ||
# If the target state is not in the FILTER_FAILS_ON list, it returns nil. | ||
# It filters out tubes that are in the 'failed' state and collects their coordinates. | ||
|
@@ -111,81 +171,46 @@ | |
end | ||
|
||
# The tube state changer is used by Tubes. It works the same way as the default | ||
# state changer but does not need to handle a subset of wells like the plate. | ||
class TubeStateChanger < DefaultStateChanger | ||
# plate state changer but does not need to handle a subset of wells like the plate. | ||
class TubeStateChanger < BaseStateChanger | ||
# Tubes have no wells so contents is always empty | ||
def contents_for(_target_state) | ||
nil | ||
end | ||
end | ||
|
||
# Plate state changer to automatically complete specified work requests. | ||
# This is the abstract version. | ||
class AutomaticLabwareStateChanger < DefaultStateChanger | ||
def v2_labware | ||
raise 'Must be implemented on subclass' | ||
end | ||
|
||
def purpose_uuid | ||
@purpose_uuid ||= v2_labware.purpose.uuid | ||
end | ||
|
||
def purpose_config | ||
@purpose_config ||= Settings.purposes[purpose_uuid] | ||
end | ||
|
||
def work_completion_request_types | ||
@work_completion_request_types ||= parse_work_completion_request_types | ||
end | ||
|
||
# config can be a single request type or an array of request types | ||
# convert them here into a consistent array format | ||
def parse_work_completion_request_types | ||
config = purpose_config[:work_completion_request_type] | ||
return config if config.is_a?(Array) | ||
|
||
[config] | ||
end | ||
|
||
# rubocop:todo Style/OptionalBooleanParameter | ||
def move_to!(state, reason = nil, customer_accepts_responsibility = false) | ||
super | ||
complete_outstanding_requests | ||
end | ||
|
||
# rubocop:enable Style/OptionalBooleanParameter | ||
|
||
def complete_outstanding_requests | ||
in_prog_submissions = | ||
v2_labware.in_progress_submission_uuids(request_types_to_complete: work_completion_request_types) | ||
return if in_prog_submissions.blank? | ||
|
||
api.work_completion.create!(submissions: in_prog_submissions, target: v2_labware.uuid, user: user_uuid) | ||
def labware | ||
raise 'Tubes are not supported by API V1' | ||
end | ||
end | ||
|
||
# This version of the AutomaticLabwareStateChanger is used by Plates. | ||
class AutomaticPlateStateChanger < AutomaticLabwareStateChanger | ||
class AutomaticPlateStateChanger < PlateStateChanger | ||
include AutomaticBehaviour | ||
|
||
def v2_labware | ||
@v2_labware ||= Sequencescape::Api::V2.plate_for_completion(labware_uuid) | ||
end | ||
end | ||
|
||
# This version of the AutomaticLabwareStateChanger is used by Tubes. | ||
class AutomaticTubeStateChanger < AutomaticLabwareStateChanger | ||
# This version of the AutomaticLabwareStateChanger is used by TubeRacks. | ||
class AutomaticTubeRackStateChanger < TubeRackStateChanger | ||
include AutomaticBehaviour | ||
|
||
def v2_labware | ||
@v2_labware ||= Sequencescape::Api::V2.tube_for_completion(labware_uuid) | ||
@v2_labware ||= Sequencescape::Api::V2.tube_rack_for_completion(labware_uuid) | ||
end | ||
|
||
def labware | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this labware vs v2_labware nonsense will hopefully get refactored out in a later story! |
||
@labware ||= v2_labware | ||
end | ||
end | ||
|
||
# This version of the AutomaticLabwareStateChanger is used by TubeRacks. | ||
class AutomaticTubeRackStateChanger < AutomaticLabwareStateChanger | ||
# This version of the AutomaticLabwareStateChanger is used by Tubes. | ||
class AutomaticTubeStateChanger < TubeStateChanger | ||
include AutomaticBehaviour | ||
|
||
def v2_labware | ||
@v2_labware ||= Sequencescape::Api::V2.tube_rack_for_completion(labware_uuid) | ||
@v2_labware ||= Sequencescape::Api::V2.tube_for_completion(labware_uuid) | ||
end | ||
|
||
def labware | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That can't be true?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not a path that appears to be used in the current iteration - I'm hoping it will be removed with @sdjmchattie's v1 API removal changes