[][src]Crate stubborn_io

Contains the ingredients needed to create wrappers over tokio AsyncRead/AsyncWrite items to automatically reconnect upon failures. This is done so that a user can use them without worrying that their application logic will terminate simply due to an event like a temporary network failure.

This crate will try to provide commonly used io items, for example, the StubbornTcpStream. If you need to create your own, you simply need to implement the UnderlyingIo trait. Once implemented, you can construct it easily by creating a StubbornIo type as seen below.

Compiler Warning

This crate only works on nightly, as it is dependent on async/await. Once that is stabilized in Rust 1.38, it will work in regular Rust.

Motivations

This crate was created because I was working on a service that needed to fetch data from a remote server via a tokio TcpConnection. It normally worked perfectly (as does all of my code ☺), but every time the remote server had a restart or turnaround, my application logic would stop working. stubborn-io was born because I did not want to complicate my service's logic with TcpStream reconnect and disconnect handling code. With stubborn-io, I can keep the service exactly the same, knowing that the StubbornTcpStream's sensible defaults will perform reconnects in a way to keep my service running. Once I realized that the implementation could apply to all IO items and not just TcpStream, I made it customizable as seen below.

Example on how a Stubborn IO item might be created

This example is not tested
#![feature(async_await)]

use std::io;
use std::future::Future;
use std::path::PathBuf;
use std::pin::Pin;
use stubborn_io::tokio::{StubbornIo, UnderlyingIo};
use tokio::fs::File;

impl UnderlyingIo<PathBuf> for File {
    // Establishes an io connection.
    // Additionally, this will be used when reconnect tries are attempted.
    fn establish(path: PathBuf) -> Pin<Box<dyn Future<Output = io::Result<Self>> + Send>> {
        Box::pin(async move {
            // In this case, we are trying to "connect" a file that
            // should exist on the system
            Ok(File::open(path).await?)
        })
    }
}

// Because StubbornIo implements deref, you are able to invoke
// the original methods on the File struct.
type HomemadeStubbornFile = StubbornIo<File, PathBuf>;
let path = PathBuf::from("./foo/bar.txt");

let stubborn_file = HomemadeStubbornFile::connect(&path).await?;
// ... application logic here

Modules

config

Provides options to configure the behavior of stubborn-io items, specifically related to reconnect behavior.

tokio

Provides functionality related to asynchronous IO, including concrete ready to use structs such as StubbornTcpStream as well as the UnderlyingIO trait and StubbornIO struct needed to create custom stubborn io types yourself.

Structs

ReconnectOptions

User specified options that control the behavior of the stubborn-io upon disconnect.

Type Definitions

StubbornTcpStream

A drop in replacement for tokio's TcpStream, with the distinction that it will automatically attempt to reconnect in the face of connectivity failures.