SWIMProtocol

public protocol SWIMProtocol

This protocol defines all callbacks that a SWIM Shell (in other words, “runtime”) must implement to properly drive the underlying SWIM.Instance (which contains the complete logic of SWIM).

  • MUST be invoked periodically, in intervals of self.swim.dynamicLHMProtocolInterval.

    MUST NOT be scheduled using a “repeated” task/timer", as the interval is dynamic and may change as the algorithm proceeds. Implementations should schedule each next tick by handling the returned directive’s scheduleNextTick case, which includes the appropriate delay to use for the next protocol tick.

    This is the heart of the protocol, as each tick corresponds to a “protocol period” in which:

    • suspect members are checked if they’re overdue and should become .unreachable or .dead,
    • decisions are made to .ping a random peer for fault detection,
    • and some internal house keeping is performed.

    Note: This means that effectively all decisions are made in interval sof protocol periods. It would be possible to have a secondary periodic or more ad-hoc interval to speed up some operations, however this is currently not implemented and the protocol follows the fairly standard mode of simply carrying payloads in periodic ping messages.

    Declaration

    Swift

    mutating func onPeriodicPingTick() -> [SWIM.Instance.PeriodicPingTickDirective]

    Return Value

    SWIM.Instance.PeriodicPingTickDirective which must be interpreted by a shell implementation

  • MUST be invoked whenever a ping message is received.

    A specific shell implementation must the returned directives by acting on them. The order of interpreting the events should be as returned by the onPing invocation.

    Declaration

    Swift

    mutating func onPing(
        pingOrigin: SWIMPingOriginPeer,
        payload: SWIM.GossipPayload,
        sequenceNumber: SWIM.SequenceNumber
    ) -> [SWIM.Instance.PingDirective]

    Parameters

    pingOrigin

    the origin peer that issued this ping, it should be replied to (as instructed in the returned ping directive)

    payload

    gossip information to be processed by this peer, resulting in potentially discovering new information about other members of the cluster

    sequenceNumber

    sequence number of this ping, will be used to reply to the ping’s origin using the same sequence number

    Return Value

    SWIM.Instance.PingDirective which must be interpreted by a shell implementation

  • MUST be invoked when a pingRequest is received.

    The returned directives will instruct an implementation to perform probes of available peers on behalf of

    Declaration

    Swift

    mutating func onPingRequest(
        target: SWIMPeer,
        pingRequestOrigin: SWIMPingRequestOriginPeer,
        payload: SWIM.GossipPayload,
        sequenceNumber: SWIM.SequenceNumber
    ) -> [SWIM.Instance.PingRequestDirective]

    Parameters

    target

    target peer which this instance was asked to indirectly ping.

    pingRequestOrigin

    the origin of this ping request; it should be notified with an .ack once we get a reply from the probed peer

    payload

    gossip information to be processed by this peer, resulting in potentially discovering new information about other members of the cluster

    sequenceNumber

    the sequenceNumber of the incoming pingRequest, used to reply with the appropriate sequence number once we get an ack from the target

    Return Value

    SWIM.Instance. which must be interpreted by a shell implementation

  • MUST be invoked when a ping response (or timeout) occur for a specific ping.

    Declaration

    Swift

    mutating func onPingResponse(
        response: SWIM.PingResponse,
        pingRequestOrigin: SWIMPingRequestOriginPeer?,
        pingRequestSequenceNumber: SWIM.SequenceNumber?
    ) -> [SWIM.Instance.PingResponseDirective]

    Parameters

    response

    the response (or timeout) related to this ping

    pingRequestOrigin

    if this ping was issued on behalf of a pingRequestOrigin, that peer, otherwise nil

    pingRequestSequenceNumber

    if this ping was issued on behalf of a pingRequestOrigin, then the sequence number of that pingRequest, otherwise nil

    Return Value

    SWIM.Instance.PingResponseDirective which must be interpreted by a shell implementation

  • MUST be invoked be exactly in one of the two following situations:

    • the first successful response from any number of ping messages that this peer has performed on behalf of a pingRequestOrigin,
    • just one single time with a timeout if none of the pings successfully returned an ack.

    Declaration

    Swift

    mutating func onPingRequestResponse(_ response: SWIM.PingResponse, pinged: SWIMPeer) -> [SWIM.Instance.PingRequestResponseDirective]

    Parameters

    response

    the response representing this ping’s result (i.e. ack or timeout).

    pinged

    the pinged peer that this response is from

    Return Value

    SWIM.Instance.PingRequestResponseDirective which must be interpreted by a shell implementation

  • MUST be invoked whenever a response to a pingRequest (an ack, nack or lack response i.e. a timeout) happens.

    This function is adjusting Local Health and MUST be invoked on every received response to a pingRequest, in order for the local health adjusted timeouts to be calculated correctly.

    Declaration

    Swift

    mutating func onEveryPingRequestResponse(
        _ response: SWIM.PingResponse,
        pinged: SWIMPeer
    ) -> [SWIM.Instance.PingRequestResponseDirective]

    Parameters

    response

    the response representing

    pinged

    the pinged peer that this response is from

    Return Value

    SWIM.Instance.PingRequestResponseDirective which must be interpreted by a shell implementation

  • Optional, only relevant when using settings.unreachable status mode (which is disabled by default).

    When .unreachable members are allowed, this function MUST be invoked to promote a node into .dead state.

    In other words, once a MemberStatusChangedEvent for an unreachable member has been emitted, a higher level system may take additional action and then determine when to actually confirm it dead. Systems can implement additional split-brain prevention mechanisms on those layers for example.

    Once a node is determined dead by such higher level system, it may invoked swim.confirmDead(peer: theDefinitelyDeadPeer, to mark the node as dead, with all of its consequences.

    Declaration

    Swift

    mutating func confirmDead(peer: SWIMPeer) -> SWIM.Instance.ConfirmDeadDirective

    Parameters

    peer

    the peer which should be confirmed dead.

    Return Value

    SWIM.Instance.ConfirmDeadDirective which must be interpreted by a shell implementation