Link

final public class Link<B> : Executable, PathDescribing

Link is the primary interface for HoneyBee processes. A link represents a single asynchronous function, as well as its execution context. The execution context includes:

  1. A AsyncBlockPerformer execution context
  2. An error handling function for when things go wrong
  3. A list of child Links to execute using the result of this link.

A single link’s execution process is as follows:

  1. Link is executed with the execution argument.
  2. This method’s function is called with argument. If the function errors, then the error is given to this link’s registered error handler along with an optional ErrorContext
  3. (If the function does not error) The result value B is captured.
  4. This link’s child links are individually, in parallel executed in this link’s AsyncBlockPerformer
  5. When all of the child links have completed their execution, then this link signals that it has completed execution, via callback.
  • B

    Declaration

    Swift

    final public class Link<B> : Executable, PathDescribing
  • Primary chain form. All other forms translate into this form.

    See more

    Declaration

    Swift

    public func chain<C,Failable>(file: StaticString = #file, line: UInt = #line, functionDescription: String? = nil, _ function: @escaping (B, @escaping (Failable) -> Void) -> Void) -> Link<C> where Failable: FailableResultProtocol, Failable.Wrapped == C

    Parameters

    function

    will be executed as a child link of this Link. Receives B (the result of this Link and generates C.

    Return Value

    The child link which has been added to this Link‘s child list. Children are executed in parallel. See Link’s description.

  • finally creates a subchain which will be executed whether or not the proceeding chain errors. In the case that no error occurs in the proceeding chain, finally is executed after the final link of the chain, as though it had been directly appended there. In the case that an error, the subchain defined by finally will be executed after the error handler has finished.

    Example:

    HoneyBee.start { root in
       root.errorHandler(funcE)
           .chain(funcA)
           .finally { link in
               link.chain(funcZ)
           }
              .chain(funcB)
           .chain(funcC)
    }
    

    In the preceding example, if no error occurs then the functions will execute in this order: funcA, funcB, funcC, funcZ. The error handler, funcE will not be executed. If funcB produces an error, then execution is as follows: funcA, funcB, funcE, funcZ. The links after the error, (funcC), will not be executed.

    Declaration

    Swift

    public func finally(file: StaticString = #file, line: UInt = #line, _ defineBlock: (Link<B>) -> Void ) -> Link<B>

    Parameters

    defineBlock

    context within which to define the finally chain.

    Return Value

    a Link with the same execution context as self, but with a finally chain registered.

  • insert inserts a value of any type into the chain data flow.

    See more

    Declaration

    Swift

    public func insert<C>(file: StaticString = #file, line: UInt = #line, _ c: C) -> Link<C>

    Parameters

    c

    Any value

    Return Value

    a Link whose child links will receive c as their function argument.

  • drop ignores drops the inbound value and returns a Link whose value is Void

    Declaration

    Swift

    public func drop(file: StaticString = #file, line: UInt = #line) -> Link<Void>

    Return Value

    a Link whose child links will receive Void as their function argument.

  • tunnel defines a subchain with whose value is ultimately discarded. The links within the tunnel subchain run sequentially before the link which is the return value of tunnel. tunnel returns a Link whose execution result B is the result the receiver link. Thus the value B hides or goes under ground while the subchain processes and pops back up when it is completed. For example:

     .insert(8)
     .tunnel { link in
        link.chain(intToString) //convert int to string
     }
     .chain(multiplyInt)
    

    In the example above insert results in an Int into the chain and that int is passed along to intToString which transform the value into a String. After the tunnel context has finished, the original value 8 (an Int) is passed to multiplyInt

    See more

    Declaration

    Swift

    public func tunnel<R>(file: StaticString = #file, line: UInt = #line, _ defineBlock: (Link<B>) -> Link<R>) -> Link<B>

    Parameters

    defineBlock

    a block which creates a subchain to be limited.

    Return Value

    a Link whose execution result R is discarded.

  • Yields self to a new definition block. Within the block the caller may invoke chaining methods on block multiple times, thus achieving parallel chains. Example:

    link.branch { stem in
      stem.chain(func1)
          .chain(func2)
    
      stem.chain(func3)
          .chain(func4)
    }
    

    In the preceding example, when link is executed it will start the links containing func1 and func3 in parallel. func2 will execute when func1 is finished. Likewise func4 will execute when func3 is finished.

    Declaration

    Swift

    public func branch(_ defineBlock: (Link<B>) -> Void)

    Parameters

    defineBlock

    the block to which this Link yields itself.

  • Yields self to a new definition block. Within the block the caller may invoke chaining methods on block multiple times, thus achieving parallel chains. Example:

    link.branch { stem in
      let a = stem.chain(func1)
                  .chain(func2)
    
      let b = stem.chain(func3)
                  .chain(func4)
    
      return (a + b) // operator for .conjoin
               .chain(combine)
    }
    

    In the preceding example, when link is executed it will start the links containing func1 and func3 in parallel. func2 will execute when func1 is finished. Likewise func4 will execute when func3 is finished.

    See more

    Declaration

    Swift

    public func branch<C>(_ defineBlock: (Link<B>) -> Link<C>) -> Link<C>

    Parameters

    defineBlock

    the block to which this Link yields itself.

    Return Value

    The link which is returned from defineBlock

  • conjoin is a compliment to branch. Within the context of a branch it is natural and expected to create parallel execution chains. If the process definition wishes at some point to combine the results of these execution chains, then conjoin should be used. conjoin returns a Link which waits for both the receiver and the argument Links created results. Those results are combined into a tuple (B,C) which is passed to the child links of the returned Link

    See more

    Declaration

    Swift

    public func conjoin<C>(_ other: Link<C>) -> Link<(B,C)>

    Parameters

    other

    the Link to join with

    Return Value

    A Link which combines the receiver and the arguments results.

  • conjoin is a compliment to branch. Within the context of a branch it is natural and expected to create parallel execution chains. If the process definition wishes at some point to combine the results of these execution chains, then conjoin should be used. conjoin returns a Link which waits for both the receiver and the argument Links created results. Those results are combined into a tuple (X, Y, C) which is passed to the child links of the returned Link

    See more

    Declaration

    Swift

    public func conjoin<X,Y,C>(other: Link<C>) -> Link<(X,Y,C)> where B == (X,Y)

    Parameters

    other

    the Link to join with

    Return Value

    A Link which combines the receiver and the arguments results.

  • conjoin is a compliment to branch. Within the context of a branch it is natural and expected to create parallel execution chains. If the process definition wishes at some point to combine the results of these execution chains, then conjoin should be used. conjoin returns a Link which waits for both the receiver and the argument Links created results. Those results are combined into a tuple (X, Y, Z, C) which is passed to the child links of the returned Link

    See more

    Declaration

    Swift

    public func conjoin<X,Y,Z,C>(other: Link<C>) -> Link<(X,Y,Z,C)> where B == (X,Y,Z)

    Parameters

    other

    the Link to join with

    Return Value

    A Link which combines the receiver and the arguments results.

  • operator syntax for conjoin function

    See more

    Declaration

    Swift

    public static func +<C>(lhs: Link<B>, rhs: Link<C>) -> Link<(B,C)>
  • operator syntax for conjoin function

    See more

    Declaration

    Swift

    public static func +<X,Y,C>(lhs: Link<B>, rhs: Link<C>) -> Link<(X,Y,C)> where B == (X,Y)
  • operator syntax for conjoin function

    See more

    Declaration

    Swift

    public static func +<X,Y,Z,C>(lhs: Link<B>, rhs: Link<C>) -> Link<(X,Y,Z,C)> where B == (X,Y,Z)
  • operator syntax for join left behavior

    See more

    Declaration

    Swift

    public static func <+<C>(lhs: Link<B>, rhs: Link<C>) -> Link<B>

    Parameters

    lhs

    Link whose value to propagate

    rhs

    Link whose value to drop

    Return Value

    a Link which contains the value of the left-hand Link

  • operator syntax for join right behavior

    See more

    Declaration

    Swift

    public static func +><C>(lhs: Link<B>, rhs: Link<C>) -> Link<C>

    Parameters

    lhs

    Link whose value to drop

    rhs

    Link whose value to propagate

    Return Value

    a Link which contains the value of the left-hand Link

  • Establishes a new error handler for this link and all descendant links.

    Declaration

    Swift

    public func setErrorHandler(_ errorHandler: @escaping (ErrorContext) -> Void ) -> Link<B>

    Parameters

    errorHandler

    a function which takes an ErrorContext object. The context contains all available debug information on the erroring function, including the error itself.

    Return Value

    A Link which has errorHandler installed

  • Declaration

    Swift

    public func chain(file: StaticString = #file, line: UInt = #line, functionDescription: String? = nil, _ function: @escaping (B) -> () throws -> Void) -> Link<B>
  • Declaration

    Swift

    public func chain(file: StaticString = #file, line: UInt = #line, functionDescription: String? = nil, _ function: @escaping (B) -> ((() -> Void)?) throws -> Void) -> Link<B>
  • Declaration

    Swift

    public func chain(file: StaticString = #file, line: UInt = #line, functionDescription: String? = nil, _ function: @escaping (B) -> (@escaping () -> Void) throws -> Void) -> Link<B>
  • Declaration

    Swift

    public func chain(file: StaticString = #file, line: UInt = #line, functionDescription: String? = nil, _ function: @escaping (B) throws -> Void) -> Link<B>
  • Declaration

    Swift

    public func chain(file: StaticString = #file, line: UInt = #line, functionDescription: String? = nil, _ function: @escaping (B, (() -> Void)?) throws -> Void) -> Link<B>
  • Declaration

    Swift

    public func chain(file: StaticString = #file, line: UInt = #line, functionDescription: String? = nil, _ function: @escaping (B, @escaping () -> Void) throws -> Void) -> Link<B>
  • Declaration

    Swift

    public func chain(file: StaticString = #file, line: UInt = #line, functionDescription: String? = nil, _ function: @escaping ((() -> Void)?) throws -> Void) -> Link<B>
  • Declaration

    Swift

    public func chain(file: StaticString = #file, line: UInt = #line, functionDescription: String? = nil, _ function: @escaping (@escaping () -> Void) throws -> Void) -> Link<B>
  • Declaration

    Swift

    public func chain<C>(file: StaticString = #file, line: UInt = #line, functionDescription: String? = nil, _ function:  @escaping (B) throws -> C ) -> Link<C>
  • Declaration

    Swift

    public func chain<C>(file: StaticString = #file, line: UInt = #line, functionDescription: String? = nil, _ function:  @escaping (B, ((C) -> Void)?) throws -> Void) -> Link<C>
  • Declaration

    Swift

    public func chain(file: StaticString = #file, line: UInt = #line, functionDescription: String? = nil, _ function: @escaping (B) -> (((Error?) -> Void)?) -> Void) -> Link<B>
  • Declaration

    Swift

    public func chain(file: StaticString = #file, line: UInt = #line, functionDescription: String? = nil, _ function: @escaping (B) -> (@escaping (Error?) -> Void) -> Void) -> Link<B>
  • Declaration

    Swift

    public func chain(file: StaticString = #file, line: UInt = #line, functionDescription: String? = nil, _ function: @escaping (B, ((Error?) -> Void)?) -> Void) -> Link<B>
  • Declaration

    Swift

    public func chain(file: StaticString = #file, line: UInt = #line, functionDescription: String? = nil, _ function: @escaping (B, @escaping (Error?) -> Void) -> Void) -> Link<B>
  • Declaration

    Swift

    public func chain<C>(file: StaticString = #file, line: UInt = #line, functionDescription: String? = nil, _ function: @escaping (B, ((C?, Error?) -> Void)?) -> Void) -> Link<C>
  • Declaration

    Swift

    public func chain<C>(file: StaticString = #file, line: UInt = #line, functionDescription: String? = nil, _ function: @escaping (B, @escaping (C?, Error?) -> Void) -> Void) -> Link<C>
  • Declaration

    Swift

    public func chain<C>(file: StaticString = #file, line: UInt = #line, functionDescription: String? = nil, _ function: @escaping (B) -> (@escaping (C) -> Void) throws -> Void) -> Link<C>
  • Declaration

    Swift

    public func chain<C>(file: StaticString = #file, line: UInt = #line, functionDescription: String? = nil, _ function: @escaping (B) -> () throws -> C) -> Link<C>
  • Declaration

    Swift

    public func chain<C>(file: StaticString = #file, line: UInt = #line, functionDescription: String? = nil, _ function: @escaping (B) -> (@escaping (C?, Error?) -> Void) -> Void) -> Link<C>
  • Declaration

    Swift

    public func chain(file: StaticString = #file, line: UInt = #line, functionDescription: String? = nil, _ function: @escaping (@escaping (Error?) -> Void) -> Void) -> Link<B>
  • Declaration

    Swift

    public func chain<C>(file: StaticString = #file, line: UInt = #line, functionDescription: String? = nil, _ function: @escaping (@escaping (C) -> Void) throws -> Void) -> Link<C>
  • Declaration

    Swift

    public func chain<C>(file: StaticString = #file, line: UInt = #line, functionDescription: String? = nil, _ function: @escaping (((C?, Error?) -> Void)?) -> Void) -> Link<C>
  • Declaration

    Swift

    public func chain<C>(file: StaticString = #file, line: UInt = #line, functionDescription: String? = nil, _ function: @escaping (@escaping (C?, Error?) -> Void) -> Void) -> Link<C>
  • Declaration

    Swift

    public func chain<C>(file: StaticString = #file, line: UInt = #line, functionDescription: String? = nil, _ function: @escaping (((C) -> Void)?) throws -> Void) -> Link<C>
  • Declaration

    Swift

    public func chain(file: StaticString = #file, line: UInt = #line, functionDescription: String? = nil, _ function: @escaping (((Error?) -> Void)?) -> Void) -> Link<B>
  • Declaration

    Swift

    public func chain<C>(file: StaticString = #file, line: UInt = #line, functionDescription: String? = nil, _ function: @escaping (B) -> (((C?, Error?) -> Void)?) -> Void) -> Link<C>
  • Declaration

    Swift

    public func chain<C>(file: StaticString = #file, line: UInt = #line, functionDescription: String? = nil, _ function: @escaping (B) -> (((C) -> Void)?) throws -> Void) -> Link<C>
  • Declaration

    Swift

    public func chain<C>(file: StaticString = #file, line: UInt = #line, functionDescription: String? = nil, _ function: @escaping (B, @escaping (C) -> Void) throws -> Void) -> Link<C>
  • Creates a new Link which accesses a keypath starting at B and ending at type C and appends the link to the execution list of this Link

    See more

    Declaration

    Swift

    public func chain<C>(file: StaticString = #file, line: UInt = #line, functionDescription: String? = nil, _ keyPath: KeyPath<B,C>) -> Link<C>
  • Set the execution queue for all descendant links. N.B. this does not change the execution queue for the receiver’s function. Example

    HoneyBee.start(on: .main) { root in
       root.setErrorHandlder(handleError)
              .chain(funcA)
           .setQueue(.global())
           .chain(funcB)
    }
    

    In the preceding example, funcA will run on DispatchQueue.main and funcB will run on DispatchQueue.global()

    Declaration

    Swift

    public func setBlockPerformer(_ blockPerformer: AsyncBlockPerformer) -> Link<B>

    Parameters

    queue

    the new DispatchQueue for child links

    Return Value

    the receiver

  • When the inbound type is a Collection, you may call map to asynchronously map over the elements of B in parallel, transforming them with transform subchain.

    See more

    Declaration

    Swift

    public func map<C>(limit: Int? = nil, acceptableFailure: FailureRate = .none, _ transform: @escaping (Link<B.Iterator.Element>) -> Link<C>) -> Link<[C]>

    Parameters

    transform

    the transformation subchain defining block which converts B.Iterator.Element to C

    Return Value

    a Link which will yield an array of Cs to it’s child links.

  • When the inbound type is a Collection, you may call filter to asynchronously filter the elements of B in parallel, using filter subchain

    Declaration

    Swift

    public func filter(limit: Int? = nil, acceptableFailure: FailureRate = .none, _ filter: @escaping (Link<B.Iterator.Element>) -> Link<Bool>) -> Link<[B.Iterator.Element]>

    Parameters

    filter

    the filter subchain which produces a Bool

    Return Value

    a Link which will yield to it’s child links an array containing those B.Iterator.Elements which filter approved.

  • When the inbound type is a Collection, you may call each Each accepts a define block which creates a subchain which will be invoked once per element of the sequence. The Link which is given as argument to the define block will pass to its child links the element of the sequence which is currently being processed.

    Declaration

    Swift

    public func each(limit: Int? = nil, acceptableFailure: FailureRate = .none, _ defineBlock: @escaping (Link<B.Element>) -> Void) -> Link<[B.Element]>

    Parameters

    defineBlock

    a block which creates a subchain for each element of the Collection

    Return Value

    a Link which will pass the nonfailing elements of B to its child links

  • When the inbound type is a Collection, you may call reduce Reduce accepts a define block which creates a subchain which will be executed sequentially, once per element of the sequence. The result of each successive execution of the subchain will be forwarded to the next pass of the subchain. The result of the final execution of the subchain will be forwarded to the returned link.

    See more

    Declaration

    Swift

    public func reduce<T>(with t: T, acceptableFailure: FailureRate = .none, _ defineBlock: @escaping (Link<(T,B.Element)>) -> Link<T>) -> Link<T>

    Return Value

    a Link which will pass the result of the reduce to its child links.

  • When the inbound type is a Collection, you may call reduce Reduce accepts a define block which creates a subchain which will be executed in parallel, with up to N/2 other subchains. Each subchain combines two B.Elements into one B.Element. The result of each combination is again combined until a single value remains. This value is forwarded to the returned link.

    Declaration

    Swift

    public func reduce(_ defineBlock: @escaping (Link<(B.Element,B.Element)>) -> Link<B.Element>) -> Link<B.Element>

    Parameters

    defineBlock

    a block which creates a subchain to combined two elements of the Collection

    Return Value

    a Link which will pass the final combined result of the reduce to its child links.

  • When B is an Optional you may call optionally. The supplied define block creates a subchain which will be run if the Optional value is non-nil. The Link given to the define block yields a non-optional value of B.WrappedType to its child links This function returns a Link with a void result value, because the subchain defined by optionally will not be executed if B is nil.

    See more

    Declaration

    Swift

    public func optionally<X>(_ defineBlock: @escaping (Link<B.WrappedType>) -> Link<X>) -> Link<B>

    Parameters

    defineBlock

    a block which creates a subchain to run if B is non-nil

    Return Value

    a Link with a void value type.

  • limit defines a subchain with special runtime protections. The links within the limit subchain are guaranteed to have at most maxParallel parallel executions. limit is particularly useful in the context of a fully parallel process when part of the process must access a limited resource pool such as CPU execution contexts or network resources. This method returns a Link whose execution result J is the result of the final link of the subchain. This permits the chain to proceed naturally after limit. For example:

     .limit(5) { link in
        link.chain(resourceLimitedIntGenerator)
    }
    .chain(multiplyInt)
    

    In the example above resourceLimitedIntGenerator results in an Int and that int is passed along to multipyInt after the limit context has finished.

    See more

    Declaration

    Swift

    public func limit<J>(_ maxParallel: Int, _ defineBlock: (Link<B>) -> Link<J>) -> Link<J>

    Parameters

    maxParallel

    the maximum number of parallel executions permitted for the subchains defined by defineBlock

    defineBlock

    a block which creates a subchain to be limited.

    Return Value

    a Link whose execution result J is the result of the final link of the subchain.

  • limit defines a subchain with special runtime protections. The links within the limit subchain are guaranteed to have at most maxParallel parallel executions. limit is particularly useful in the context of a fully parallel process when part of the process must access a limited resource pool such as CPU execution contexts or network resources.

    Declaration

    Swift

    public func limit(_ maxParallel: Int, _ defineBlock: (Link<B>) -> Void) -> Void

    Parameters

    maxParallel

    the maximum number of parallel executions permitted for the subchains defined by defineBlock

    defineBlock

    a block which creates a subchain to be limited.

  • retry defines a subchain with special runtime properties. The defined subchain will execute a maximum of maxTimes + 1 times in an attempt to reach a non-error result. If each of the maxTimes + 1 attempts result in error, the error from the last-attempted pass will be send to the registered error handler. If any of the attempts succeeds, the result R will be forwarded to the link which is returned from this function. For example:

     .retry(2) { link in
        link.chain(transientlyFailingIntGenerator)
    }
    .chain(multiplyInt)
    

    In the example above transientlyFailingIntGenerator is a function which can fail in non-fatal ways. When it succeeds, the result is an Int and that int is passed to multiplyInt after the retry.

    See more

    Declaration

    Swift

    public func retry<R>(_ maxTimes: Int, _ defineBlock: @escaping (Link<B>) -> Link<R>) -> Link<R>

    Parameters

    maxTimes

    the maximum number of times to reattempt the subchain. Thus the subchain is executed at most maxTimes + 1

    defineBlock

    a block which creates a subchain to be retried.

    Return Value

    a Link whose execution result R is the result of the final link of the subchain.