Skip to content

Commit

Permalink
Add asynchronous effect handling routes
Browse files Browse the repository at this point in the history
  • Loading branch information
kmcbride committed Feb 16, 2024
1 parent 1ac08e3 commit 57427e9
Show file tree
Hide file tree
Showing 2 changed files with 649 additions and 0 deletions.
334 changes: 334 additions & 0 deletions MobiusCore/Source/EffectHandlers/EffectRouterDSL+Concurrency.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,334 @@
// Copyright 2019-2024 Spotify AB.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
public extension _PartialEffectRouter {
/// Routes the `Effect` to an asynchronous closure.
///
/// - Parameter handler: An asynchronous closure receiving the `Effect`'s parameters as input.
/// - Returns: An `EffectRouter` that includes a handler for the given `Effect`.
func to(_ handler: @escaping (EffectParameters) async -> Void) -> EffectRouter<Effect, Event> {
to { parameters, _ in
await handler(parameters)
}
}

/// Routes the `Effect` to an asynchronous throwing closure.
///
/// - Parameter handler: An asynchronous throwing closure receiving the `Effect`'s parameters as input.
/// - Returns: An `EffectRouter` that includes a handler for the given `Effect`.
func to(_ handler: @escaping (EffectParameters) async throws -> Void) -> EffectRouter<Effect, Event> {
to { parameters, _ in
try await handler(parameters)
}
}
}

@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
public extension _PartialEffectRouter where EffectParameters == Void {
/// Routes the `Effect` to an asynchronous closure.
///
/// - Parameter handler: An asynchronous closure.
/// - Returns: An `EffectRouter` that includes a handler for the given `Effect`.
func to(_ handler: @escaping () async -> Void) -> EffectRouter<Effect, Event> {
to { _, _ in
await handler()
}
}

/// Routes the `Effect` to an asynchronous throwing closure.
///
/// - Parameter handler: An asynchronous throwing closure.
/// - Returns: An `EffectRouter` that includes a handler for the given `Effect`.
func to(_ handler: @escaping () async throws -> Void) -> EffectRouter<Effect, Event> {
to { _, _ in
try await handler()
}
}
}

@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
public extension _PartialEffectRouter {
/// Routes the `Effect` to an asynchronous closure producing a single `Event`.
///
/// - Parameter handler: An asynchronous closure receiving the `Effect`'s parameters as input and producing a single `Event` as output.
/// - Returns: An `EffectRouter` that includes a handler for the given `Effect`.
func to(_ handler: @escaping (EffectParameters) async -> Event) -> EffectRouter<Effect, Event> {
to { parameters, callback in
await callback(handler(parameters))
}
}

/// Routes the `Effect` to an asynchronous throwing closure producing a single `Event`.
///
/// - Parameter handler: An asynchronous throwing closure receiving the `Effect`'s parameters as input and producing a single `Event` as output.
/// - Returns: An `EffectRouter` that includes a handler for the given `Effect`.
func to(_ handler: @escaping (EffectParameters) async throws -> Event) -> EffectRouter<Effect, Event> {
to { parameters, callback in
try await callback(handler(parameters))
}
}
}

@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
public extension _PartialEffectRouter where EffectParameters == Void {
/// Routes the `Effect` to an asynchronous closure producing a single `Event`.
///
/// - Parameter handler: An asynchronous closure producing a single `Event` as output.
/// - Returns: An `EffectRouter` that includes a handler for the given `Effect`.
func to(_ handler: @escaping () async -> Event) -> EffectRouter<Effect, Event> {
to { _, callback in
await callback(handler())
}
}

/// Routes the `Effect` to an asynchronous throwing closure producing a single `Event`.
///
/// - Parameter handler: An asynchronous throwing closure producing a single `Event` as output.
/// - Returns: An `EffectRouter` that includes a handler for the given `Effect`.
func to(_ handler: @escaping () async throws -> Event) -> EffectRouter<Effect, Event> {
to { _, callback in
try await callback(handler())
}
}
}

@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
public extension _PartialEffectRouter {
/// Routes the `Effect` to an asynchronous closure producing a sequence of `Event`s.
///
/// - Parameter handler: An asynchronous closure receiving the `Effect`'s parameters as input and producing an `AsyncSequence` of `Event`s as output.
/// - Returns: An `EffectRouter` that includes a handler for the given `Effect`.
func to<S: AsyncSequence>(
_ handler: @escaping (EffectParameters) async -> S
) -> EffectRouter<Effect, Event> where S.Element == Event {
to { parameters, callback in
for try await output in await handler(parameters) {
callback(output)
}
}
}
}

@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
public extension _PartialEffectRouter where EffectParameters == Void {
/// Routes the `Effect` to an asynchronous closure producing a sequence of `Event`s.
///
/// - Parameter handler: An asynchronous closure producing an `AsyncSequence` of `Event`s as output.
/// - Returns: An `EffectRouter` that includes a handler for the given `Effect`.
func to<S: AsyncSequence>(
_ handler: @escaping () async -> S
) -> EffectRouter<Effect, Event> where S.Element == Event {
to { _, callback in
for try await output in await handler() {
callback(output)
}
}
}
}

@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
public extension _PartialEffectRouter {
/// Routes the `Effect` to an `Actor`'s closure.
///
/// - Parameter actor: An `Actor` providing the `Effect` handling closure.
/// - Parameter handler: An isolated asynchronous closure receiving the `Effect`'s parameters as input.
/// - Returns: An `EffectRouter` that includes a handler for the given `Effect`.
func to<A: Actor>(
_ actor: A,
_ handler: @escaping (isolated A) -> (EffectParameters) async -> Void
) -> EffectRouter<Effect, Event> {
to { parameters, _ in
await handler(actor)(parameters)
}
}

/// Routes the `Effect` to an `Actor`'s throwing closure.
///
/// - Parameter actor: An `Actor` providing the `Effect` handling throwing closure.
/// - Parameter handler: An isolated asynchronous throwing closure receiving the `Effect`'s parameters as input.
/// - Returns: An `EffectRouter` that includes a handler for the given `Effect`.
func to<A: Actor>(

Check failure on line 162 in MobiusCore/Source/EffectHandlers/EffectRouterDSL+Concurrency.swift

View workflow job for this annotation

GitHub Actions / swiftlint

Multiline Parameters Violation: Functions and methods parameters should be either on the same line, or one per line. (multiline_parameters)
_ actor: A,
_ handler: @escaping (isolated A) -> (EffectParameters) async throws -> Void
) -> EffectRouter<Effect, Event> {
to { parameters, _ in
try await handler(actor)(parameters)
}
}
}

@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
public extension _PartialEffectRouter where EffectParameters == Void {
/// Routes the `Effect` to an `Actor`'s closure.
///
/// - Parameter actor: An `Actor` providing the `Effect` handling closure.
/// - Parameter handler: An isolated asynchronous closure.
/// - Returns: An `EffectRouter` that includes a handler for the given `Effect`.
func to<A: Actor>(
_ actor: A,
_ handler: @escaping (isolated A) -> () async -> Void

Check failure on line 181 in MobiusCore/Source/EffectHandlers/EffectRouterDSL+Concurrency.swift

View workflow job for this annotation

GitHub Actions / swiftlint

Void Return Violation: Prefer `-> Void` over `-> ()`. (void_return)
) -> EffectRouter<Effect, Event> {
to { _, _ in
await handler(actor)()
}
}

/// Routes the `Effect` to an `Actor`'s closure.
///
/// - Parameter actor: An `Actor` providing the `Effect` handling throwing closure.
/// - Parameter handler: An isolated asynchronous throwing closure.
/// - Returns: An `EffectRouter` that includes a handler for the given `Effect`.
func to<A: Actor>(

Check failure on line 193 in MobiusCore/Source/EffectHandlers/EffectRouterDSL+Concurrency.swift

View workflow job for this annotation

GitHub Actions / swiftlint

Multiline Parameters Violation: Functions and methods parameters should be either on the same line, or one per line. (multiline_parameters)
_ actor: A,
_ handler: @escaping (isolated A) -> () async throws -> Void

Check failure on line 195 in MobiusCore/Source/EffectHandlers/EffectRouterDSL+Concurrency.swift

View workflow job for this annotation

GitHub Actions / swiftlint

Void Return Violation: Prefer `-> Void` over `-> ()`. (void_return)
) -> EffectRouter<Effect, Event> {
to { _, _ in
try await handler(actor)()
}
}
}

@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
public extension _PartialEffectRouter {
/// Routes the `Effect` to an `Actor`'s closure producing a single `Event`.
///
/// - Parameter actor: An `Actor` providing the `Effect` handling closure.
/// - Parameter handler: An isolated asynchronous closure receiving the `Effect`'s parameters as input and producing a single `Event` as output.
/// - Returns: An `EffectRouter` that includes a handler for the given `Effect`.
func to<A: Actor>(
_ actor: A,
_ handler: @escaping (isolated A) -> (EffectParameters) async -> Event
) -> EffectRouter<Effect, Event> {
to { parameters, callback in
await callback(handler(actor)(parameters))
}
}

/// Routes the `Effect` to an `Actor`'s throwing closure producing a single `Event`.
///
/// - Parameter actor: An `Actor` providing the `Effect` handling throwing closure.
/// - Parameter handler: An isolated asynchronous throwing closure receiving the `Effect`'s parameters as input and producing a single `Event` as output.
/// - Returns: An `EffectRouter` that includes a handler for the given `Effect`.
func to<A: Actor>(

Check failure on line 224 in MobiusCore/Source/EffectHandlers/EffectRouterDSL+Concurrency.swift

View workflow job for this annotation

GitHub Actions / swiftlint

Multiline Parameters Violation: Functions and methods parameters should be either on the same line, or one per line. (multiline_parameters)
_ actor: A,
_ handler: @escaping (isolated A) -> (EffectParameters) async throws -> Event
) -> EffectRouter<Effect, Event> {
to { parameters, callback in
try await callback(handler(actor)(parameters))
}
}
}

@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
public extension _PartialEffectRouter where EffectParameters == Void {
/// Routes the `Effect` to an `Actor`'s closure producing a single `Event`.
///
/// - Parameter actor: An `Actor` providing the `Effect` handling closure.
/// - Parameter handler: An isolated asynchronous closure producing a single `Event` as output.
/// - Returns: An `EffectRouter` that includes a handler for the given `Effect`.
func to<A: Actor>(
_ actor: A,
_ handler: @escaping (isolated A) -> () async -> Event

Check failure on line 243 in MobiusCore/Source/EffectHandlers/EffectRouterDSL+Concurrency.swift

View workflow job for this annotation

GitHub Actions / swiftlint

Void Return Violation: Prefer `-> Void` over `-> ()`. (void_return)
) -> EffectRouter<Effect, Event> {
to { _, callback in
await callback(handler(actor)())
}
}

/// Routes the `Effect` to an `Actor`'s throwing closure producing a single `Event`.
///
/// - Parameter actor: An `Actor` providing the `Effect` handling throwing closure.
/// - Parameter handler: An isolated asynchronous throwing closure producing a single `Event` as output.
/// - Returns: An `EffectRouter` that includes a handler for the given `Effect`.
func to<A: Actor>(

Check failure on line 255 in MobiusCore/Source/EffectHandlers/EffectRouterDSL+Concurrency.swift

View workflow job for this annotation

GitHub Actions / swiftlint

Multiline Parameters Violation: Functions and methods parameters should be either on the same line, or one per line. (multiline_parameters)
_ actor: A,
_ handler: @escaping (isolated A) -> () async throws -> Event

Check failure on line 257 in MobiusCore/Source/EffectHandlers/EffectRouterDSL+Concurrency.swift

View workflow job for this annotation

GitHub Actions / swiftlint

Void Return Violation: Prefer `-> Void` over `-> ()`. (void_return)
) -> EffectRouter<Effect, Event> {
to { _, callback in
try await callback(handler(actor)())
}
}
}

@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
public extension _PartialEffectRouter {
/// Routes the `Effect` to an `Actor`'s closure producing a sequence of `Event`s.
///
/// - Parameter actor: An `Actor` providing the `Effect` handling closure.
/// - Parameter handler: An isolated asynchronous closure receiving the `Effect`'s parameters as input and producing an `AsyncSequence` of `Event`s as output.
/// - Returns: An `EffectRouter` that includes a handler for the given `Effect`.
func to<A: Actor, S: AsyncSequence>(
_ actor: A,
_ handler: @escaping (isolated A) -> (EffectParameters) async -> S
) -> EffectRouter<Effect, Event> where S.Element == Event {
to { parameters, callback in
for try await output in await handler(actor)(parameters) {
callback(output)
}
}
}
}

@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
public extension _PartialEffectRouter where EffectParameters == Void {
/// Routes the `Effect` to an `Actor`'s closure producing a sequence of `Event`s.
///
/// - Parameter actor: An `Actor` providing the `Effect` handling closure.
/// - Parameter handler: An isolated asynchronous closure producing an `AsyncSequence` of `Event`s as output.
/// - Returns: An `EffectRouter` that includes a handler for the given `Effect`.
func to<A: Actor, S: AsyncSequence>(
_ actor: A,
_ handler: @escaping (isolated A) -> () async -> S

Check failure on line 293 in MobiusCore/Source/EffectHandlers/EffectRouterDSL+Concurrency.swift

View workflow job for this annotation

GitHub Actions / swiftlint

Void Return Violation: Prefer `-> Void` over `-> ()`. (void_return)
) -> EffectRouter<Effect, Event> where S.Element == Event {
to { _, callback in
for try await output in await handler(actor)() {
callback(output)
}
}
}
}

@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
private extension _PartialEffectRouter {
func to(
_ handler: @Sendable @escaping (EffectParameters, Consumer<Event>) async -> Void
) -> EffectRouter<Effect, Event> {
to { parameters, callback in
let task = Task.detached {
defer { callback.end() }
await handler(parameters, callback.send)
}

return AnonymousDisposable {
task.cancel()
}
}
}

func to(
_ handler: @Sendable @escaping (EffectParameters, Consumer<Event>) async throws -> Void
) -> EffectRouter<Effect, Event> {
to { parameters, callback in
let task = Task.detached {
defer { callback.end() }
try await handler(parameters, callback.send)
}

return AnonymousDisposable {
task.cancel()
}
}
}
}
Loading

0 comments on commit 57427e9

Please sign in to comment.