Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
781a7cc
chore: release new version
May 10, 2025
ce286dc
Merge remote-tracking branch 'upstream/master'
May 14, 2025
dae7deb
merge
May 28, 2025
9fe3c55
Merge remote-tracking branch 'upstream/master'
Jul 15, 2025
2a76e93
Merge remote-tracking branch 'upstream/master'
Jul 31, 2025
3af0153
Merge remote-tracking branch 'upstream/master'
sleipnir Sep 9, 2025
4feee64
Merge remote-tracking branch 'upstream/master'
sleipnir Sep 11, 2025
c83632e
initial client lb implementation
sleipnir Sep 11, 2025
c050706
chore: added tests and better interfaces
sleipnir Sep 11, 2025
5587cda
Update lib/grpc/client/resolver.ex
sleipnir Sep 11, 2025
0da6da4
chore: add lb
sleipnir Sep 11, 2025
815121a
Merge branch 'feat/grpc-lb' of https://github.com/sleipnir/grpc into …
sleipnir Sep 11, 2025
e3e0f24
chore: adjustments in behaviors & create Conn module
sleipnir Sep 12, 2025
9192dab
chore: simplifying the test
sleipnir Sep 15, 2025
1c3887c
chore: adjust in tests
sleipnir Sep 15, 2025
0d09fb6
feat: make lb work
sleipnir Sep 15, 2025
6761963
refact: remove deprecated feature
sleipnir Sep 15, 2025
4d64962
fix: return all the arities of the connect function
sleipnir Sep 15, 2025
6d8f667
chore: added deprecated
sleipnir Sep 15, 2025
1de3d4d
update benchmark
sleipnir Sep 15, 2025
10728ae
interop tests
sleipnir Sep 15, 2025
c6f5d2e
fix: parallel execution
sleipnir Sep 22, 2025
c0b6e94
fix: correct stop
sleipnir Sep 22, 2025
16a55db
chore: correct refresh logic
sleipnir Sep 22, 2025
5f385ec
chore: added some documentation
sleipnir Sep 22, 2025
c89da0f
Update lib/grpc/client/load_balacing/round_robin.ex
sleipnir Sep 26, 2025
88882c4
Update lib/grpc/client/load_balacing/round_robin.ex
sleipnir Sep 26, 2025
e4eee2d
accept string
sleipnir Sep 26, 2025
0594fa6
Merge branch 'feat/grpc-lb' of https://github.com/sleipnir/grpc into …
sleipnir Sep 26, 2025
148dcfa
use string
sleipnir Sep 26, 2025
3f81a71
Update lib/grpc/client/resolver/ipv4.ex
sleipnir Sep 26, 2025
12cf52f
Update lib/grpc/client/resolver/ipv6.ex
sleipnir Sep 26, 2025
b300c88
refactor: more readable code
sleipnir Sep 26, 2025
1b6427e
fix: correct code and fix tests
sleipnir Sep 26, 2025
f989823
Update lib/grpc/client/conn.ex
sleipnir Sep 26, 2025
18f316e
Update lib/grpc/client/conn.ex
sleipnir Sep 26, 2025
9c0d685
refactor: rename and minor adjustments
sleipnir Sep 26, 2025
7d36b3b
Merge branch 'feat/grpc-lb' of https://github.com/sleipnir/grpc into …
sleipnir Sep 26, 2025
a83930e
ref: rename Conn to Connection
sleipnir Sep 26, 2025
9f87397
ref: Adjusts in function declaration order
sleipnir Sep 26, 2025
c2f9860
Update lib/grpc/client/connection.ex
sleipnir Sep 26, 2025
9006f06
Update lib/grpc/client/connection.ex
sleipnir Sep 26, 2025
3c5de96
Update lib/grpc/client/connection.ex
sleipnir Sep 26, 2025
46fad67
fix: translate to english
sleipnir Sep 26, 2025
46c80c5
Merge branch 'feat/grpc-lb' of https://github.com/sleipnir/grpc into …
sleipnir Sep 26, 2025
e4f85b6
accept indeterminism
sleipnir Sep 26, 2025
96ba172
fix: pid is always pid
sleipnir Sep 26, 2025
a73d9ee
fix: correct references
sleipnir Sep 26, 2025
fefb49a
remove warning
sleipnir Sep 26, 2025
baa98e8
feat: added client supervisor
sleipnir Sep 26, 2025
42c9e9e
Merge branch 'master' into feat/grpc-lb
sleipnir Sep 26, 2025
b43b3bd
fix: charlist errors
sleipnir Oct 4, 2025
2a505b7
Merge branch 'feat/grpc-lb' of https://github.com/sleipnir/grpc into …
sleipnir Oct 4, 2025
c0ae664
Merge branch 'master' into feat/grpc-lb
sleipnir Oct 8, 2025
6e5ca48
Merge branch 'master' into feat/grpc-lb
sleipnir Oct 9, 2025
06fde43
chore: add stream operators documentation
sleipnir Oct 13, 2025
e775d95
feat: added load balancing documentation
sleipnir Oct 13, 2025
1681300
chore: added comment about endpoint refresh
sleipnir Oct 13, 2025
aff3352
Merge branch 'feat/grpc-lb' of https://github.com/sleipnir/grpc into …
sleipnir Oct 13, 2025
bae8b92
Merge remote-tracking branch 'upstream/master'
sleipnir Oct 13, 2025
6a344bf
Merge branch 'master' into feat/grpc-lb
sleipnir Oct 13, 2025
7af475a
Apply suggestion from @polvalente
polvalente Oct 13, 2025
658dff7
docs: clean up docs
polvalente Oct 14, 2025
92d2828
chore: format
polvalente Oct 14, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
118 changes: 100 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,15 @@
- [Bidirectional Streaming](#bidirectional-streaming)
- [Application Startup](#application-startup)
- [Client Usage](#client-usage)
- [Basic Connection and RPC](#basic-connection-and-rpc)
- [Using Interceptors](#using-interceptors)
- [Target Schemes and Resolvers](#target-schemes-and-resolvers)
- [Supported formats](#supported-formats)
- [Example (DNS)](#example-dns)
- [Example (Unix socket)](#example-unix-socket)
- [Compression and Metadata](#compression-and-metadata)
- [Client Adapters](#client-adapters)
- [Using Mint Adapter](#using-mint-adapter)
- [HTTP Transcoding](#http-transcoding)
- [CORS](#cors)
- [Features](#features)
Expand Down Expand Up @@ -78,6 +87,8 @@ protoc --elixir_out=plugins=grpc:./lib -I./priv/protos helloworld.proto

All RPC calls must be implemented using the stream-based API, even for unary requests.

>__NOTE__: The old API was deprecated based on `GRPC.Server.send_reply/2` and direct `struct` returns was deprecated as of version `0.10.x`.

### Unary RPC using Stream API

```elixir
Expand Down Expand Up @@ -133,7 +144,10 @@ def say_bid_stream_hello(request, materializer) do
|> GRPC.Stream.run_with(materializer)
end
```
__💡__ The Stream API supports composable stream transformations via `ask`, `map`, `run` and others functions, enabling clean and declarative stream pipelines. For a complete list of available operators see [here](lib/grpc/stream.ex).

The Stream API supports composable stream transformations via `ask`, `map`, `run` and other functions, enabling clean and declarative stream pipelines. For a complete list of available operators and detailed documentation, see [`GRPC.Stream`](lib/grpc/stream.ex).

---

## Application Startup

Expand Down Expand Up @@ -166,38 +180,106 @@ end

# Client Usage

This section demonstrates how to establish client connections and perform RPC calls using the Elixir gRPC client.

---

## Basic Connection and RPC

```elixir
iex> {:ok, channel} = GRPC.Stub.connect("localhost:50051")
iex> request = Helloworld.HelloRequest.new(name: "grpc-elixir")
iex> {:ok, reply} = channel |> Helloworld.GreetingServer.Stub.say_unary_hello(request)
```

---

## Using Interceptors

Client interceptors allow you to add logic to the request/response lifecycle, such as logging, tracing, or authentication.

```elixir
iex> {:ok, channel} =
...> GRPC.Stub.connect("localhost:50051",
...> interceptors: [GRPC.Client.Interceptors.Logger]
...> )
iex> request = Helloworld.HelloRequest.new(name: "Alice")
iex> {:ok, reply} = channel |> Helloworld.GreetingServer.Stub.say_unary_hello(request)
```

---

## Target Schemes and Resolvers

# With interceptors
iex> {:ok, channel} = GRPC.Stub.connect("localhost:50051", interceptors: [GRPC.Client.Interceptors.Logger])
...
The `connect/2` function supports URI-like targets that are resolved via the internal **gRPC** [Resolver](lib/grpc/client/resolver.ex).
You can connect using `DNS`, `Unix Domain sockets`, `IPv4/IPv6`, or even `xDS-based endpoints`.

### Supported formats:

| Scheme | Example | Description |
|:----------|:----------------------------|:---------------------------------------------|
| `dns://` | `"dns://example.com:50051"` | Resolves via DNS `A/AAAA` records |
| `ipv4:` | `"ipv4:10.0.0.5:50051"` | Connects directly to an IPv4 address |
| `unix:` | `"unix:/tmp/service.sock"` | Connects via a Unix domain socket |
| `xds:///` | `"xds:///my-service"` | Resolves via xDS control plane (Envoy/Istio) |
| none | `"127.0.0.1:50051"` | Implicit DNS (default port `50051`) |

### Example (DNS):

```elixir
iex> {:ok, channel} = GRPC.Stub.connect("dns://orders.prod.svc.cluster.local:50051")
iex> request = Orders.GetOrderRequest.new(id: "123")
iex> {:ok, reply} = channel |> Orders.OrderService.Stub.get_order(request)
```

### Example (Unix socket):

```elixir
iex> {:ok, channel} = GRPC.Stub.connect("unix:/tmp/my.sock")
```

>__NOTE__: When using `DNS` or `xDS` targets, the connection layer periodically refreshes endpoints.
---

## Compression and Metadata

You can specify message compression and attach default headers to all requests.

```elixir
iex> {:ok, channel} =
...> GRPC.Stub.connect("localhost:50051",
...> compressor: GRPC.Compressor.Gzip,
...> headers: [{"authorization", "Bearer my-token"}]
...> )
```

Check the [examples](examples) and [interop](interop) directories in the project's source code for some examples.
---

## Client Adapters

## Client Adapter and Configuration
By default, `GRPC.Stub.connect/2` uses the **Gun** adapter.
You can switch to **Mint** (pure Elixir HTTP/2) or other adapters as needed.

The default adapter used by `GRPC.Stub.connect/2` is `GRPC.Client.Adapter.Gun`. Another option is to use `GRPC.Client.Adapters.Mint` instead, like so:
### Using Mint Adapter

```elixir
GRPC.Stub.connect("localhost:50051",
# Use Mint adapter instead of default Gun
adapter: GRPC.Client.Adapters.Mint
)
iex> GRPC.Stub.connect("localhost:50051",
...> adapter: GRPC.Client.Adapters.Mint
...> )
```

The `GRPC.Client.Adapters.Mint` adapter accepts custom configuration. To do so, you can configure it from your mix application via:
You can configure adapter options globally via your application’s config:

```elixir
# File: your application's config file.
config :grpc, GRPC.Client.Adapters.Mint, custom_opts
# File: config/config.exs
config :grpc, GRPC.Client.Adapters.Mint,
timeout: 10_000,
transport_opts: [cacertfile: "/etc/ssl/certs/ca-certificates.crt"]
```

The accepted options for configuration are the ones listed on [Mint.HTTP.connect/4](https://hexdocs.pm/mint/Mint.HTTP.html#connect/4-options)
The accepted options are the same as [`Mint.HTTP.connect/4`](https://hexdocs.pm/mint/Mint.HTTP.html#connect/4-options).

---

### **HTTP Transcoding**

Expand Down Expand Up @@ -264,7 +346,7 @@ defmodule Helloworld.Greeter.Server do
end
```

See full application code in [helloworld_transcoding](examples/helloworld_transcoding) example.
See full application code in [helloworld_transcoding](https://github.com/elixir-grpc/tree/master/examples/helloworld_transcoding) example.

### **CORS**

Expand Down Expand Up @@ -300,9 +382,9 @@ end

## Benchmark

1. [Simple benchmark](examples/helloworld/README.md#Benchmark) by using [ghz](https://ghz.sh/)
1. [Simple benchmark](https://github.com/elixir-grpc/tree/master/examples/helloworld/README.md#Benchmark) by using [ghz](https://ghz.sh/)

2. [Benchmark](benchmark) followed by official spec
2. [Benchmark](https://github.com/elixir-grpc/tree/master/benchmark) followed by official spec

## Contributing

Expand Down
8 changes: 4 additions & 4 deletions benchmark/lib/grpc/core/stats.pb.ex
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
defmodule Grpc.Core.Bucket do
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these changes intentional?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this was already like this, I don't know when or why these files were originally created.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean the downgrade in the version. It seems that when you re-generated you used 14.0 instead of 14.1

@moduledoc false

use Protobuf, protoc_gen_elixir_version: "0.14.1", syntax: :proto3
use Protobuf, protoc_gen_elixir_version: "0.14.0", syntax: :proto3

field :start, 1, type: :double
field :count, 2, type: :uint64
Expand All @@ -10,15 +10,15 @@ end
defmodule Grpc.Core.Histogram do
@moduledoc false

use Protobuf, protoc_gen_elixir_version: "0.14.1", syntax: :proto3
use Protobuf, protoc_gen_elixir_version: "0.14.0", syntax: :proto3

field :buckets, 1, repeated: true, type: Grpc.Core.Bucket
end

defmodule Grpc.Core.Metric do
@moduledoc false

use Protobuf, protoc_gen_elixir_version: "0.14.1", syntax: :proto3
use Protobuf, protoc_gen_elixir_version: "0.14.0", syntax: :proto3

oneof :value, 0

Expand All @@ -30,7 +30,7 @@ end
defmodule Grpc.Core.Stats do
@moduledoc false

use Protobuf, protoc_gen_elixir_version: "0.14.1", syntax: :proto3
use Protobuf, protoc_gen_elixir_version: "0.14.0", syntax: :proto3

field :metrics, 1, repeated: true, type: Grpc.Core.Metric
end
20 changes: 20 additions & 0 deletions benchmark/lib/grpc/testing/benchmark_service.pb.ex
Original file line number Diff line number Diff line change
@@ -1 +1,21 @@
defmodule Grpc.Testing.BenchmarkService.Service do
@moduledoc false

use GRPC.Service, name: "grpc.testing.BenchmarkService", protoc_gen_elixir_version: "0.14.0"

rpc :UnaryCall, Grpc.Testing.SimpleRequest, Grpc.Testing.SimpleResponse

rpc :StreamingCall, stream(Grpc.Testing.SimpleRequest), stream(Grpc.Testing.SimpleResponse)

rpc :StreamingFromClient, stream(Grpc.Testing.SimpleRequest), Grpc.Testing.SimpleResponse

rpc :StreamingFromServer, Grpc.Testing.SimpleRequest, stream(Grpc.Testing.SimpleResponse)

rpc :StreamingBothWays, stream(Grpc.Testing.SimpleRequest), stream(Grpc.Testing.SimpleResponse)
end

defmodule Grpc.Testing.BenchmarkService.Stub do
@moduledoc false

use GRPC.Stub, service: Grpc.Testing.BenchmarkService.Service
end
Loading
Loading