grpc/restartstream/restart.go
func Interceptor(settings Settings) grpc.StreamClientInterceptor {
	return func(ctx context.Context, desc *grpc.StreamDesc, cc *grpc.ClientConn, method string, streamer grpc.Streamer, opts ...grpc.CallOption) (stream grpc.ClientStream, err error) {
		s := &restartingStream{
			log: log.Get().WithField("method", method),

			ctx:      ctx,
			desc:     desc,
			cc:       cc,
			method:   method,
			streamer: streamer,
			opts:     opts,

			retryableCodes: settings.RetryableCodes,
			backoff:        settings.Backoff,
			retries:        -1,
		}

		err = s.start()

		stream = s
		return
	}
}
func Interceptor(settings Settings) grpc.StreamClientInterceptor {
	return func(ctx context.Context, desc *grpc.StreamDesc, cc *grpc.ClientConn, method string, streamer grpc.Streamer, opts ...grpc.CallOption) (stream grpc.ClientStream, err error) {
		s := &restartingStream{
			log: log.Get().WithField("method", method),

			ctx:      ctx,
			desc:     desc,
			cc:       cc,
			method:   method,
			streamer: streamer,
			opts:     opts,

			retryableCodes: settings.RetryableCodes,
			backoff:        settings.Backoff,
			retries:        -1,
		}

		err = s.start()

		stream = s
		return
	}
}
// Interceptor automatically restarts streams on non-expected errors
// To do so, the application should create a for-loop around RecvMsg, which
// returns the same errors that are received from the server.
//
// An io.EOF indicates the end of the stream
//
// To stop the reconnect behaviour, you have to cancel the context