Skip to content

Constructor makes blocking network calls #212

Description

@thunderbiscuit

Currently, Client::new() and Client::from_config() do two things synchronously before returning: establish a TCP connection and complete a server.version protocol negotiation round-trip. This means the constructor can hang indefinitely (or until timeout) if the server is unreachable, which is unusual and surprising behavior for a constructor.

Relevant links: bitcoindevkit/bdk-dart#91, bitcoindevkit/bdk-ffi#1037, bitcoindevkit/bdk-ffi#1038

The Problem

Users constructing a Client may not expect it to block on network I/O. There is no way to hold a Client value that represents "configured but not yet connected", because construction and connection are the same operation.

Ideas from Claude (I have not looked into these deeply yet so just putting here for brainstorm)

Two directions worth exploring

  1. Lazy connection — The constructor stores the URL and Config but does not connect. The first API call triggers the TCP connection and server.version handshake transparently. The reconnect logic already in impl_inner_call! is structurally identical to what lazy init would need ("no client yet, create one" vs "client failed, recreate it"), so these two paths could potentially be unified.
  2. Explicit connect() method — The constructor is cheap and infallible. A separate connect() (or from_config() becomes the cheap constructor, and a connect() consumes it to produce a connected client) makes the network boundary explicit in the type system.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions