Skip to content

Commit

Permalink
Merge branch 'master' into fix/integration-tests
Browse files Browse the repository at this point in the history
  • Loading branch information
sleipnir authored Jul 12, 2024
2 parents 7dc28cd + dce082c commit 87279fe
Show file tree
Hide file tree
Showing 25 changed files with 607 additions and 246 deletions.
69 changes: 9 additions & 60 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
- uses: erlef/setup-beam@v1
with:
otp-version: 26.1.x
elixir-version: 1.14.x
elixir-version: 1.15.x
- name: Retrieve dependencies cache
uses: actions/cache@v3
id: mix-cache # id to use in retrieve action
Expand All @@ -33,21 +33,11 @@ jobs:
name: OTP ${{matrix.otp}} / Elixir ${{matrix.elixir}}
strategy:
matrix:
otp: [23.x, 24.x, 25.1.x, 26.1.x]
elixir: [1.12.x, 1.13.x, 1.14.x, 1.15.x]
exclude:
- otp: 25.1.x
elixir: 1.12.x
- otp: 26.1.x
otp: [24.x, 25.x, 26.1.x]
elixir: [1.15.x]
include:
- otp: 24.x
elixir: 1.12.x
- otp: 25.1.x
elixir: 1.13.x
- otp: 26.1.x
elixir: 1.13.x
- otp: 26.1.x
elixir: 1.14.x
- otp: 23.x
elixir: 1.15.x
needs: check_format
steps:
- uses: actions/checkout@v3
Expand Down Expand Up @@ -96,21 +86,11 @@ jobs:
if: ${{ github.ref == 'refs/heads/master' }}
strategy:
matrix:
otp: [23.x, 24.x, 25.1.x, 26.1.x]
elixir: [1.12.x, 1.13.x, 1.14.x, 1.15.x]
exclude:
- otp: 25.1.x
elixir: 1.12.x
- otp: 26.1.x
otp: [24.x, 25.x, 26.1.x]
elixir: [1.15.x]
include:
- otp: 24.x
elixir: 1.12.x
- otp: 25.1.x
elixir: 1.13.x
- otp: 26.1.x
elixir: 1.13.x
- otp: 26.1.x
elixir: 1.14.x
- otp: 23.x
elixir: 1.15.x
steps:
- uses: actions/checkout@v3
- uses: erlef/setup-beam@v1
Expand All @@ -130,37 +110,6 @@ jobs:
run: mix run script/run.exs
working-directory: ./interop

dialyzer:
name: Dialyzer
runs-on: ubuntu-20.04
strategy:
matrix:
otp: [25.1.x, 26.1.x]
elixir: [1.15.x]
env:
MIX_ENV: test
steps:
- uses: actions/checkout@v3
- id: set_vars
run: |
mix_hash="${{ hashFiles(format('{0}{1}', github.workspace, '/mix.lock')) }}"
echo "::set-output name=mix_hash::$mix_hash"
- id: cache-plt
uses: actions/cache@v3
with:
path: |
_build/test/plts/dialyzer.plt
_build/test/plts/dialyzer.plt.hash
key: plt-cache-${{ matrix.otp }}-${{ matrix.elixir }}-${{ steps.set_vars.outputs.mix_hash }}
restore-keys: |
plt-cache-${{ matrix.otp }}-${{ matrix.elixir }}-
- uses: erlef/setup-beam@v1
with:
otp-version: ${{matrix.otp}}
elixir-version: ${{matrix.elixir}}
- run: mix deps.get 1>/dev/null
- run: mix dialyzer --format short

check_release:
runs-on: ubuntu-20.04
name: Check release
Expand Down
163 changes: 147 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
# gRPC Elixir

[![GitHub CI](https://github.com/elixir-grpc/grpc/actions/workflows/ci.yml/badge.svg)](https://github.com/elixir-grpc/grpc/actions/workflows/ci.yml)
[![Hex.pm](https://img.shields.io/hexpm/v/grpc.svg)](https://hex.pm/packages/grpc)
[![Travis Status](https://app.travis-ci.com/elixir-grpc/grpc.svg?branch=master)](https://app.travis-ci.com/elixir-grpc/grpc)
[![GitHub actions Status](https://github.com/elixir-grpc/grpc/workflows/CI/badge.svg)](https://github.com/elixir-grpc/grpc/actions)
[![Hex Docs](https://img.shields.io/badge/hex-docs-lightgreen.svg)](https://hexdocs.pm/grpc/)
[![License](https://img.shields.io/hexpm/l/grpc.svg)](https://github.com/elixir-grpc/grpc/blob/master/LICENSE.md)
[![Last Updated](https://img.shields.io/github/last-commit/elixir-grpc/grpc.svg)](https://github.com/elixir-grpc/grpc/commits/master)
[![Total Download](https://img.shields.io/hexpm/dt/grpc.svg)](https://hex.pm/packages/elixir-grpc/grpc)
[![Last Updated](https://img.shields.io/github/last-commit/elixir-grpc/grpc.svg)](https://github.com/elixir-grpc/grpc/commits/master)

An Elixir implementation of [gRPC](http://www.grpc.io/).

## Table of contents

- [Installation](#installation)
- [Usage](#usage)
- [Simple RPC](#simple-rpc)
- [HTTP Transcoding](#http-transcoding)
- [Start Application](#start-application)
- [Features](#features)
- [Benchmark](#benchmark)
- [Contributing](#contributing)
Expand All @@ -24,20 +27,49 @@ The package can be installed as:
```elixir
def deps do
[
{:grpc, "~> 0.7"},
# We don't force protobuf as a dependency for more
# flexibility on which protobuf library is used,
# but you probably want to use it as well
{:protobuf, "~> 0.11"}
{:grpc, "~> 0.8"}
]
end
```

## Usage

1. Generate Elixir code from proto file as [protobuf-elixir](https://github.com/tony612/protobuf-elixir#usage) shows(especially the `gRPC Support` section).
1. Write your protobuf file:

```protobuf
syntax = "proto3";
package helloworld;
2. Implement the server side code like below and remember to return the expected message types.
// The request message containing the user's name.
message HelloRequest {
string name = 1;
}
// The response message containing the greeting
message HelloReply {
string message = 1;
}
// The greeting service definition.
service Greeter {
// Greeting function
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
```

2. Then generate Elixir code from proto file as [protobuf-elixir](https://github.com/tony612/protobuf-elixir#usage) shows (especially the `gRPC Support` section) or using [protobuf_generate](https://hex.pm/packages/protobuf_generate) hex package. Example using `protobuf_generate` lib:

```shell
mix protobuf.generate --output-path=./lib --include-path=./priv/protos helloworld.proto
```

In the following sections you will see how to implement gRPC server logic.

### **Simple RPC**

1. Implement the server side code like below and remember to return the expected message types.

```elixir
defmodule Helloworld.Greeter.Server do
Expand All @@ -50,9 +82,7 @@ defmodule Helloworld.Greeter.Server do
end
```

3. Start the server

You can start the gRPC server as a supervised process. First, add `GRPC.Server.Supervisor` to your supervision tree.
2. Define gRPC endpoints

```elixir
# Define your endpoint
Expand All @@ -62,7 +92,86 @@ defmodule Helloworld.Endpoint do
intercept GRPC.Server.Interceptors.Logger
run Helloworld.Greeter.Server
end
```

We will use this module [in the gRPC server startup section](#start-application).

**__Note:__** For other types of RPC call like streams see [here](interop/lib/interop/server.ex).

### **HTTP Transcoding**

1. Adding [grpc-gateway annotations](https://cloud.google.com/endpoints/docs/grpc/transcoding) to your protobuf file definition:

```protobuf
import "google/api/annotations.proto";
import "google/protobuf/timestamp.proto";
package helloworld;
// The greeting service definition.
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply) {
option (google.api.http) = {
get: "/v1/greeter/{name}"
};
}
rpc SayHelloFrom (HelloRequestFrom) returns (HelloReply) {
option (google.api.http) = {
post: "/v1/greeter"
body: "*"
};
}
}
```

2. Add protoc plugin dependency and compile your protos using [protobuf_generate](https://github.com/drowzy/protobuf_generate) hex [package](https://hex.pm/packages/protobuf_generate):

In mix.exs:

```elixir
def deps do
[
{:grpc, "~> 0.7"},
{:protobuf_generate, "~> 0.1.1"}
]
end
```

And in your terminal:

```shell
mix protobuf.generate \
--include-path=priv/proto \
--include-path=deps/googleapis \
--generate-descriptors=true \
--output-path=./lib \
--plugins=ProtobufGenerate.Plugins.GRPCWithOptions \
google/api/annotations.proto google/api/http.proto helloworld.proto
```

3. Enable http_transcode option in your Server module
```elixir
defmodule Helloworld.Greeter.Server do
use GRPC.Server,
service: Helloworld.Greeter.Service,
http_transcode: true

@spec say_hello(Helloworld.HelloRequest.t, GRPC.Server.Stream.t) :: Helloworld.HelloReply.t
def say_hello(request, _stream) do
%Helloworld.HelloReply{message: "Hello #{request.name}"}
end
end
```

See full application code in [helloworld_transcoding](examples/helloworld_transcoding) example.

### **Start Application**

1. Start gRPC Server in your supervisor tree or Application module:

```elixir
# In the start function of your Application
defmodule HelloworldApp do
use Application
Expand All @@ -78,7 +187,7 @@ defmodule HelloworldApp do
end
```

4. Call rpc:
2. Call rpc:

```elixir
iex> {:ok, channel} = GRPC.Stub.connect("localhost:50051")
Expand All @@ -90,7 +199,27 @@ iex> {:ok, channel} = GRPC.Stub.connect("localhost:50051", interceptors: [GRPC.C
...
```

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

## Client Adapter and Configuration

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:

```elixir
GRPC.Stub.connect("localhost:50051",
# Use Mint adapter instead of default Gun
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:

```elixir
# File: your application's config file.
config :grpc, GRPC.Client.Adapters.Mint, custom_opts
```

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

## Features

Expand All @@ -99,11 +228,13 @@ Check [examples](examples) and [interop](interop)(Interoperability Test) for som
- [Server-streaming](https://grpc.io/docs/what-is-grpc/core-concepts/#server-streaming-rpc)
- [Client-streaming](https://grpc.io/docs/what-is-grpc/core-concepts/#client-streaming-rpc)
- [Bidirectional-streaming](https://grpc.io/docs/what-is-grpc/core-concepts/#bidirectional-streaming-rpc)
- [HTTP Transcoding](https://cloud.google.com/endpoints/docs/grpc/transcoding)
- [TLS Authentication](https://grpc.io/docs/guides/auth/#supported-auth-mechanisms)
- [Error handling](https://grpc.io/docs/guides/error/)
- Interceptors(See [`GRPC.Endpoint`](https://github.com/elixir-grpc/grpc/blob/master/lib/grpc/endpoint.ex))
- Interceptors (See [`GRPC.Endpoint`](https://github.com/elixir-grpc/grpc/blob/master/lib/grpc/endpoint.ex))
- [Connection Backoff](https://github.com/grpc/grpc/blob/master/doc/connection-backoff.md)
- Data compression
- [gRPC Reflection](https://github.com/elixir-grpc/grpc-reflection)

## Benchmark

Expand Down
1 change: 0 additions & 1 deletion examples/helloworld/mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ defmodule Helloworld.Mixfile do
{:jason, "~> 1.3.0"},
{:protobuf, "~> 0.11"},
{:google_protos, "~> 0.3.0"},
{:dialyxir, "~> 1.1", only: [:dev, :test], runtime: false}
]
end
end
3 changes: 0 additions & 3 deletions examples/helloworld/mix.lock
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
%{
"cowboy": {:hex, :cowboy, "2.9.0", "865dd8b6607e14cf03282e10e934023a1bd8be6f6bacf921a7e2a96d800cd452", [:make, :rebar3], [{:cowlib, "2.11.0", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "1.8.0", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "2c729f934b4e1aa149aff882f57c6372c15399a20d54f65c8d67bef583021bde"},
"cowlib": {:hex, :cowlib, "2.11.0", "0b9ff9c346629256c42ebe1eeb769a83c6cb771a6ee5960bd110ab0b9b872063", [:make, :rebar3], [], "hexpm", "2b3e9da0b21c4565751a6d4901c20d1b4cc25cbb7fd50d91d2ab6dd287bc86a9"},
"dialyxir": {:hex, :dialyxir, "1.1.0", "c5aab0d6e71e5522e77beff7ba9e08f8e02bad90dfbeffae60eaf0cb47e29488", [:mix], [{:erlex, ">= 0.2.6", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "07ea8e49c45f15264ebe6d5b93799d4dd56a44036cf42d0ad9c960bc266c0b9a"},
"erlex": {:hex, :erlex, "0.2.6", "c7987d15e899c7a2f34f5420d2a2ea0d659682c06ac607572df55a43753aa12e", [:mix], [], "hexpm", "2ed2e25711feb44d52b17d2780eabf998452f6efda104877a3881c2f8c0c0c75"},
"google_protos": {:hex, :google_protos, "0.3.0", "15faf44dce678ac028c289668ff56548806e313e4959a3aaf4f6e1ebe8db83f4", [:mix], [{:protobuf, "~> 0.10", [hex: :protobuf, repo: "hexpm", optional: false]}], "hexpm", "1f6b7fb20371f72f418b98e5e48dae3e022a9a6de1858d4b254ac5a5d0b4035f"},
"gun": {:hex, :grpc_gun, "2.0.1", "221b792df3a93e8fead96f697cbaf920120deacced85c6cd3329d2e67f0871f8", [:rebar3], [{:cowlib, "~> 2.11", [hex: :cowlib, repo: "hexpm", optional: false]}], "hexpm", "795a65eb9d0ba16697e6b0e1886009ce024799e43bb42753f0c59b029f592831"},
"jason": {:hex, :jason, "1.3.0", "fa6b82a934feb176263ad2df0dbd91bf633d4a46ebfdffea0c8ae82953714946", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "53fc1f51255390e0ec7e50f9cb41e751c260d065dcba2bf0d08dc51a4002c2ac"},
"protobuf": {:hex, :protobuf, "0.11.0", "58d5531abadea3f71135e97bd214da53b21adcdb5b1420aee63f4be8173ec927", [:mix], [{:jason, "~> 1.2", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "30ad9a867a5c5a0616cac9765c4d2c2b7b0030fa81ea6d0c14c2eb5affb6ac52"},
"ranch": {:hex, :ranch, "1.8.0", "8c7a100a139fd57f17327b6413e4167ac559fbc04ca7448e9be9057311597a1d", [:make, :rebar3], [], "hexpm", "49fbcfd3682fab1f5d109351b61257676da1a2fdbe295904176d5e521a2ddfe5"},
}
1 change: 0 additions & 1 deletion examples/helloworld_transcoding/mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ defmodule Helloworld.Mixfile do
{:protobuf_generate, "~> 0.1.1", only: [:dev, :test]},
{:jason, "~> 1.3.0"},
{:google_protos, "~> 0.3.0"},
{:dialyxir, "~> 1.1", only: [:dev, :test], runtime: false}
]
end
end
3 changes: 0 additions & 3 deletions examples/helloworld_transcoding/mix.lock
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
%{
"cowboy": {:hex, :cowboy, "2.9.0", "865dd8b6607e14cf03282e10e934023a1bd8be6f6bacf921a7e2a96d800cd452", [:make, :rebar3], [{:cowlib, "2.11.0", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "1.8.0", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "2c729f934b4e1aa149aff882f57c6372c15399a20d54f65c8d67bef583021bde"},
"cowlib": {:hex, :cowlib, "2.11.0", "0b9ff9c346629256c42ebe1eeb769a83c6cb771a6ee5960bd110ab0b9b872063", [:make, :rebar3], [], "hexpm", "2b3e9da0b21c4565751a6d4901c20d1b4cc25cbb7fd50d91d2ab6dd287bc86a9"},
"dialyxir": {:hex, :dialyxir, "1.1.0", "c5aab0d6e71e5522e77beff7ba9e08f8e02bad90dfbeffae60eaf0cb47e29488", [:mix], [{:erlex, ">= 0.2.6", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "07ea8e49c45f15264ebe6d5b93799d4dd56a44036cf42d0ad9c960bc266c0b9a"},
"erlex": {:hex, :erlex, "0.2.6", "c7987d15e899c7a2f34f5420d2a2ea0d659682c06ac607572df55a43753aa12e", [:mix], [], "hexpm", "2ed2e25711feb44d52b17d2780eabf998452f6efda104877a3881c2f8c0c0c75"},
"google_protos": {:hex, :google_protos, "0.3.0", "15faf44dce678ac028c289668ff56548806e313e4959a3aaf4f6e1ebe8db83f4", [:mix], [{:protobuf, "~> 0.10", [hex: :protobuf, repo: "hexpm", optional: false]}], "hexpm", "1f6b7fb20371f72f418b98e5e48dae3e022a9a6de1858d4b254ac5a5d0b4035f"},
"gun": {:hex, :grpc_gun, "2.0.1", "221b792df3a93e8fead96f697cbaf920120deacced85c6cd3329d2e67f0871f8", [:rebar3], [{:cowlib, "~> 2.11", [hex: :cowlib, repo: "hexpm", optional: false]}], "hexpm", "795a65eb9d0ba16697e6b0e1886009ce024799e43bb42753f0c59b029f592831"},
"jason": {:hex, :jason, "1.3.0", "fa6b82a934feb176263ad2df0dbd91bf633d4a46ebfdffea0c8ae82953714946", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "53fc1f51255390e0ec7e50f9cb41e751c260d065dcba2bf0d08dc51a4002c2ac"},
"protobuf": {:hex, :protobuf, "0.11.0", "58d5531abadea3f71135e97bd214da53b21adcdb5b1420aee63f4be8173ec927", [:mix], [{:jason, "~> 1.2", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "30ad9a867a5c5a0616cac9765c4d2c2b7b0030fa81ea6d0c14c2eb5affb6ac52"},
"protobuf_generate": {:hex, :protobuf_generate, "0.1.1", "f6098b85161dcfd48a4f6f1abee4ee5e057981dfc50aafb1aa4bd5b0529aa89b", [:mix], [{:protobuf, "~> 0.11", [hex: :protobuf, repo: "hexpm", optional: false]}], "hexpm", "93a38c8e2aba2a17e293e9ef1359122741f717103984aa6d1ebdca0efb17ab9d"},
"ranch": {:hex, :ranch, "1.8.0", "8c7a100a139fd57f17327b6413e4167ac559fbc04ca7448e9be9057311597a1d", [:make, :rebar3], [], "hexpm", "49fbcfd3682fab1f5d109351b61257676da1a2fdbe295904176d5e521a2ddfe5"},
}
1 change: 0 additions & 1 deletion examples/route_guide/mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ defmodule RouteGuide.Mixfile do
{:grpc, path: "../../"},
{:protobuf, "~> 0.11"},
{:jason, "~> 1.2"},
{:dialyxir, "~> 1.1", only: [:dev, :test], runtime: false}
]
end
end
3 changes: 0 additions & 3 deletions examples/route_guide/mix.lock
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
%{
"cowboy": {:hex, :cowboy, "2.9.0", "865dd8b6607e14cf03282e10e934023a1bd8be6f6bacf921a7e2a96d800cd452", [:make, :rebar3], [{:cowlib, "2.11.0", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "1.8.0", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "2c729f934b4e1aa149aff882f57c6372c15399a20d54f65c8d67bef583021bde"},
"cowlib": {:hex, :cowlib, "2.11.0", "0b9ff9c346629256c42ebe1eeb769a83c6cb771a6ee5960bd110ab0b9b872063", [:make, :rebar3], [], "hexpm", "2b3e9da0b21c4565751a6d4901c20d1b4cc25cbb7fd50d91d2ab6dd287bc86a9"},
"dialyxir": {:hex, :dialyxir, "1.2.0", "58344b3e87c2e7095304c81a9ae65cb68b613e28340690dfe1a5597fd08dec37", [:mix], [{:erlex, ">= 0.2.6", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "61072136427a851674cab81762be4dbeae7679f85b1272b6d25c3a839aff8463"},
"erlex": {:hex, :erlex, "0.2.6", "c7987d15e899c7a2f34f5420d2a2ea0d659682c06ac607572df55a43753aa12e", [:mix], [], "hexpm", "2ed2e25711feb44d52b17d2780eabf998452f6efda104877a3881c2f8c0c0c75"},
"gun": {:hex, :grpc_gun, "2.0.1", "221b792df3a93e8fead96f697cbaf920120deacced85c6cd3329d2e67f0871f8", [:rebar3], [{:cowlib, "~> 2.11", [hex: :cowlib, repo: "hexpm", optional: false]}], "hexpm", "795a65eb9d0ba16697e6b0e1886009ce024799e43bb42753f0c59b029f592831"},
"jason": {:hex, :jason, "1.4.0", "e855647bc964a44e2f67df589ccf49105ae039d4179db7f6271dfd3843dc27e6", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "79a3791085b2a0f743ca04cec0f7be26443738779d09302e01318f97bdb82121"},
"protobuf": {:hex, :protobuf, "0.11.0", "58d5531abadea3f71135e97bd214da53b21adcdb5b1420aee63f4be8173ec927", [:mix], [{:jason, "~> 1.2", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "30ad9a867a5c5a0616cac9765c4d2c2b7b0030fa81ea6d0c14c2eb5affb6ac52"},
"ranch": {:hex, :ranch, "1.8.0", "8c7a100a139fd57f17327b6413e4167ac559fbc04ca7448e9be9057311597a1d", [:make, :rebar3], [], "hexpm", "49fbcfd3682fab1f5d109351b61257676da1a2fdbe295904176d5e521a2ddfe5"},
}
Loading

0 comments on commit 87279fe

Please sign in to comment.