DRPC Documentation

repository·main·Indexed 23 days ago

https://github.com/storj/drpc

A lightweight, high-performance, transport-agnostic replacement for gRPC designed for simplicity and speed. Includes tools for Go code generation via protoc-gen-go-drpc, per-stream caching with drpccache, connection management via drpcconn and drpcmanager, and HTTP integration through drpchttp.

Tokens
11.9K
Snippets
29
Records
100
Agent score
81%

What's inside drpc

  1. Overview of DRPC

    main

    DRPC is a lightweight, high-performance replacement for gRPC. It is designed to be transport-agnostic, extensible via middleware, and compatible with many existing gRPC use cases. Key features include:

    • Simplicity: A small codebase with minimal dependencies.
    • Performance: A lightning-fast wire format that outperforms gRPC in microbenchmarks for latency, throughput, and memory allocation.
    • Extensibility: Built around interfaces and supports middleware for various tasks.
    • Compatibility: Can be made compatible with RPC clients from other languages (like Twirp or gRPC-web) using the drpchttp package.
  2. Use internal drpcopts for advanced configuration

    main
    The drpcopts package provides access to internal options that are not part of the standard public API. These options are intended for specialized use cases where high-precision control is needed and backward compatibility is not guaranteed. It primarily interacts with Manager and Stream types to set or retrieve debug information, statistics, and transport details.
  3. Use the drpcstats package for byte counter collection

    main

    The drpcstats package provides the Stats type, which is used to track the number of bytes read and written. It is designed for concurrent use, providing atomic updates to its counters.

    import "storj.io/drpc/drpcstats"
    
    // Stats keeps counters of read and written bytes.
    type Stats struct {
    	Read    uint64
    	Written uint64
    }
  4. Use drpcpool for client connection pooling

    main

    The drpcpool package provides a simple connection pool for DRPC clients. It manages a cache of connections with configurable limits on total capacity and per-key capacity. It also supports automatic expiration of connections that have been inactive in the pool for a specified duration.

    To use it, import: import "storj.io/drpc/drpcpool"

    import "storj.io/drpc/drpcpool"
  5. Use drpcmanager to manage DRPC transports

    main

    The drpcmanager package provides a Manager type that handles the lifecycle of a drpc.Transport. It ensures the connection is continuously read from, manages stream forwarding, and handles closing the transport. You can use it to manage transports for both DRPC clients and servers.

    To create a manager, use New(tr drpc.Transport) or NewWithOptions(tr drpc.Transport, opts Options) for more granular control.

  6. Understand the gRPC example baseline

    main
    The examples/grpc directory contains a baseline gRPC implementation. This example is intended to serve as a reference point for comparing standard gRPC behavior against DRPC-based implementations. Note that this specific example does not use DRPC.
  7. Use drpccache for per-stream caching

    main
    The drpccache package provides a mechanism for implementing per-stream caches in DRPC. It allows you to store and retrieve values associated with a specific stream by attaching a Cache instance to a context.Context.
  8. Use drpcmux to dispatch RPCs

    main
    The drpcmux package provides a Mux handler used to dispatch incoming DRPC requests to the appropriate service implementations. It implements the drpc.Handler interface, allowing you to register multiple services (Receivers) via their drpc.Description and route incoming streams based on the RPC name.
  9. Use Signal to capture and wait for errors

    main

    The Signal type is a helper for capturing a single error and providing multiple ways to inspect or wait for it. It is particularly useful for coordinating goroutines where one might fail and others need to be notified.

    Key behaviors:

    • First error wins: Set(err error) only keeps track of the first error set. It returns true if it was the first error set, and false otherwise.
    • Error vs. Set status: A non-nil error returned by Err() means the signal has been set, but a nil error does not necessarily mean the signal is unset (the signal could have been set with a nil error). Always use IsSet() or Get() to check if the signal has been triggered.
  10. Run DRPC and gRPC concurrently on the same ports

    main

    The drpcmigrate package allows you to multiplex a single network listener so that it can handle both DRPC and gRPC (or other protocols) on the same port. This is achieved by inspecting the first few bytes of a connection to determine which protocol it belongs to.

    To implement this, use a ListenMux to route incoming connections based on a specific prefix. For DRPC, the package provides a predefined DRPCHeader constant designed to avoid conflicts with headerless gRPC, HTTP, or TLS requests.

  11. Understand X-Drpc-Metadata header format

    main

    Metadata is attached to requests using the X-Drpc-Metadata header. This header can be provided multiple times. The format for each header is:

    X-Drpc-Metadata: percentEncode(key)=percentEncode(value)

    Note that only the % and = characters must be percent-encoded.

  12. How Content-Type determines DRPC protocol

    main

    The drpchttp handler selects the communication protocol based on the request's Content-Type:

    1. Unitary RPCs: application/json and application/protobuf trigger unitary-only RPCs. The response will match the request's Content-Type on success.
    2. gRPC-Web: Content types like application/grpc-web+proto, application/grpc-web+json, application/grpc-web-text+proto, and application/grpc-web-text+json support both unitary and server-streaming RPCs using the grpc-web protocol (5-byte header with flags and big-endian length). The -text variants use base64 encoding for bodies.

    Error Responses: On failure, the response code will not be 200 OK, the Content-Type will always be application/json, and the body will follow this schema:

    {
      "code": "short_error_string",
      "msg": "textual description"
    }

    If an error code cannot be determined, unknown is used.