workflow-swift icon indicating copy to clipboard operation
workflow-swift copied to clipboard

Consider something like LifecycleWorker

Open bencochran opened this issue 3 years ago • 1 comments

Kotlin has LifecycleWorker that makes it easy to perform side-effects when the worker is started or stopped.

At the moment, this is essentially equivalent to doing the following in Swift:

func render(state: State, context: RenderContext<SomeWorkflow>) -> Rendering {
    let onStart: () -> Void = …
    let onEnd: () -> Void = …

    context.runSideEffect(key: "lifecycle") { lifetime in
        onStart()
        lifetime.onEnded(onEnd)
    }

    …
}

We might consider making some convenience for this in Swift land. I’d hesitate tying it to Worker specifically since that lives in WorkflowReactiveSwift and this could be built more generally.

Open to suggestions on API shape

bencochran avatar Sep 21 '20 22:09 bencochran

I think it'd be easier if we tied this to Worker, but we could build it more generally:

public struct LifecycleWorker {
    let key: AnyHashable
    let onStarted: () -> Void
    let onStopped: () -> Void

    init(key: AnyHashable, onStarted: @escaping () -> Void, onStopped: @escaping () -> Void) {
        self.key = key

        self.onStarted = onStarted
        self.onStopped = onStopped
    }
}

extension LifecycleWorker: AnyWorkflowConvertible {
    public typealias Rendering = Void
    public typealias Output = Never

    public func asAnyWorkflow() -> AnyWorkflow<Rendering, Output> {
        LifecycleWorkerWorkflow(worker: self).asAnyWorkflow()
    }
}

// Internal plumbing

struct LifecycleWorkerWorkflow: Workflow {
    typealias State = Void
    typealias Rendering = Void

    private var worker: LifecycleWorker

    init(worker: LifecycleWorker) {
        self.worker = worker
    }

    func render(state: Void, context: RenderContext<LifecycleWorkerWorkflow>) -> Void {
        context.runSideEffect(key: worker.key) { lifetime in
            worker.onStarted()
            lifetime.onEnded(worker.onStopped)
        }
    }
}

Does it create confusion that this is a "worker" but the worker definition lives in the other module?

AquaGeek avatar Oct 20 '20 21:10 AquaGeek