Skip to content
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

[chore]: refactor some internal actions to use existential any #190

Merged
merged 1 commit into from
Feb 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 15 additions & 7 deletions Workflow/Sources/SubtreeManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ extension WorkflowNode {

extension WorkflowNode.SubtreeManager {
enum Output {
case update(AnyWorkflowAction<WorkflowType>, source: WorkflowUpdateDebugInfo.Source)
case update(any WorkflowAction<WorkflowType>, source: WorkflowUpdateDebugInfo.Source)
case childDidUpdate(WorkflowUpdateDebugInfo)
}
}
Expand Down Expand Up @@ -175,7 +175,7 @@ extension WorkflowNode.SubtreeManager {
/// Update the existing child
existing.update(
workflow: workflow,
outputMap: { AnyWorkflowAction(outputMap($0)) },
outputMap: { outputMap($0) },
eventPipe: eventPipe
)
child = existing
Expand All @@ -184,7 +184,7 @@ extension WorkflowNode.SubtreeManager {
/// This spins up a new workflow node, etc to host the newly created child.
child = ChildWorkflow<Child>(
workflow: workflow,
outputMap: { AnyWorkflowAction(outputMap($0)) },
outputMap: { outputMap($0) },
eventPipe: eventPipe
)
}
Expand Down Expand Up @@ -272,7 +272,7 @@ extension WorkflowNode.SubtreeManager {

fileprivate final class ReusableSink<Action: WorkflowAction>: AnyReusableSink where Action.WorkflowType == WorkflowType {
func handle(action: Action) {
let output = Output.update(AnyWorkflowAction(action), source: .external)
let output = Output.update(action, source: .external)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

this change will help the observation API be more useful as we will be able to expose the underlying conformance and not an AnyWorkflow wrapper


if case .pending = eventPipe.validationState {
// Workflow is currently processing an `event`.
Expand Down Expand Up @@ -387,9 +387,13 @@ extension WorkflowNode.SubtreeManager {

fileprivate final class ChildWorkflow<W: Workflow>: AnyChildWorkflow {
private let node: WorkflowNode<W>
private var outputMap: (W.Output) -> AnyWorkflowAction<WorkflowType>
private var outputMap: (W.Output) -> any WorkflowAction<WorkflowType>

init(workflow: W, outputMap: @escaping (W.Output) -> AnyWorkflowAction<WorkflowType>, eventPipe: EventPipe) {
init(
workflow: W,
outputMap: @escaping (W.Output) -> any WorkflowAction<WorkflowType>,
eventPipe: EventPipe
) {
self.outputMap = outputMap
self.node = WorkflowNode<W>(workflow: workflow)

Expand All @@ -408,7 +412,11 @@ extension WorkflowNode.SubtreeManager {
return node.render(isRootNode: false)
}

func update(workflow: W, outputMap: @escaping (W.Output) -> AnyWorkflowAction<WorkflowType>, eventPipe: EventPipe) {
func update(
workflow: W,
outputMap: @escaping (W.Output) -> any WorkflowAction<WorkflowType>,
eventPipe: EventPipe
) {
self.outputMap = outputMap
self.eventPipe = eventPipe
node.update(workflow: workflow)
Expand Down
16 changes: 13 additions & 3 deletions Workflow/Sources/WorkflowNode.swift
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,19 @@ final class WorkflowNode<WorkflowType: Workflow> {
let output: Output

switch subtreeOutput {
case .update(let event, let source):
/// Apply the update to the current state
let outputEvent = event.apply(toState: &state)
case .update(let action, let source):

/// 'Opens' the existential `any WorkflowAction<WorkflowType>` value
/// allowing the underlying conformance to be applied to the Workflow's State
func openAndApply<A: WorkflowAction>(
Copy link
Contributor Author

Choose a reason for hiding this comment

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

it's not entirely clear to me why this is necessary, or exactly why it works, but if you try to invoke action.apply(...) on the any WorkflowAction variable, you get a compiler error. this makes some amount of sense b/c an any WorkflowAction isn't itself a WorkflowAction. i did skim this and this to see if there are other options, but this was the only thing i've been able to get working thus far.

_ action: A,
to state: inout WorkflowType.State
) -> WorkflowType.Output? where A.WorkflowType == WorkflowType {
/// Apply the update to the current state
action.apply(toState: &state)
}

let outputEvent = openAndApply(action, to: &state)

/// Finally, we tell the outside world that our state has changed (including an output event if it exists).
output = Output(
Expand Down
2 changes: 1 addition & 1 deletion Workflow/Tests/SubtreeManagerTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ final class SubtreeManagerTests: XCTestCase {
manager.onUpdate = {
switch $0 {
case .update(let event, _):
events.append(event)
events.append(AnyWorkflowAction(event))
default:
break
}
Expand Down