Giter Club home page Giter Club logo

sinkemall's Introduction

SinkEmAll

An error handling reactive extension for fine-grained control over Abort, Retry, Fail?

Battleship (also Battleships or Sea Battle) is a guessing game for two players. It is played on ruled grids (paper or board) on which each player's fleet of ships (including battleships) are marked. The locations of the fleets are concealed from the other player. Players alternate turns calling "shots" at the other player's ships, and the objective of the game is to destroy the opposing player's fleet.

Usage

SinkEmAll extends the way of handling errors in RxSwift. It brings (A)bort, (R)etry, (F)ail? pattern back to the game. Yes, that's the battleship game!

    /// Definition of a single attempt of handling error.
    /// That's the battleship game: you can miss, hit, or sink on target.
    ///
    /// - miss: Attempt the operation again. (R)etry
    /// - hit: Throw an error to the next handler in the chain of responsibility. (A)bort or (I)gnore
    /// - sink: Gracefully recover from an error. (F)ail
    public enum Shot {
        case miss
        case hit(Error)
        case sink
    }

Therefore, you can implement ErrorShooting protocol in order to take a single shot on target.

    extension ViewController: ErrorShooting {
    
        func shoot(error: RetriableError, attempt: Int, complete: @escaping (Shot) -> Void) {
            let alert = UIAlertController(title: "", message: "Something wrong happened", preferredStyle: .alert)
            if error.canRetry && attempt < 3 {
                alert.addAction(
                    UIAlertAction(title: "Retry", style: .cancel) { _ in
                        complete(.miss)
                    }
                )
            }
            alert.addAction(
                UIAlertAction(title: "Rethrow", style: .destructive) { _ in
                    complete(.hit(error))
                }
            )
            alert.addAction(
                UIAlertAction(title: "Close", style: .default) { _ in
                    complete(.sink)
                }
            )
    
            present(alert, animated: true)
        }
    
    }

Take note that shoot function is generic so another error type can be used.

    class ConsoleErrorLogger: ErrorShooting {
    
        public let level: Level
    
        public init(level: Level) {
            self.level = level
        }
    
        public func shoot(error: DescribableError, attempt: Int, complete: ((Shot) -> Void)) {
            if let message = error.message(for: level) {
                print("Error Log: \(message)")
            }
            complete(.hit(error))
        }
    
    }

After that you can use your instance as a shooter for reactive operator.

    observableThatErrorsOut
        .shootError(with: viewController)
        .shootError(with: ConsoleErrorLogger(level: .debug))

Another example with custom shooter function:

    observableThatErrorsOut
    	.shootError { error, _ in
            print("Sinking an error: \(error.localizedDescription)")
            return .just(.sink)
        }

Please look at ViewController.swift file in example project for more examples.

Example

To run the example project, clone the repo and run pod install from the Example directory first.

TO-DO

  • Replace completion handlers with dedicated shot observable
  • Add miss, hit and sink hooks to error traits
  • Wrap around the underlying error in some ship struct
  • What about Result type?
  • Add support for tvOS, watchOS and macOS deployment targets
  • Add support for other reactive frameworks
  • Add timeout
  • Provide more examples
  • Improve README.md by adding a diagram of shooting an error
  • How to enjoy error handling in RxSwift

Author

Piotr Boguslaw Łyczba, [email protected]

License

SinkEmAll is available under the MIT license. See the LICENSE file for more info.

sinkemall's People

Contributors

lyzkov avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.