Skip to content

Commit 2cda1e3

Browse files
authored
Merge branch 'master' into ref/remove-warnings
2 parents 36344d2 + 55f5d1a commit 2cda1e3

File tree

24 files changed

+606
-245
lines changed

24 files changed

+606
-245
lines changed

.github/workflows/ci.yml

+9-60
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ jobs:
1717
- uses: erlef/setup-beam@v1
1818
with:
1919
otp-version: 26.1.x
20-
elixir-version: 1.14.x
20+
elixir-version: 1.15.x
2121
- name: Retrieve dependencies cache
2222
uses: actions/cache@v3
2323
id: mix-cache # id to use in retrieve action
@@ -33,21 +33,11 @@ jobs:
3333
name: OTP ${{matrix.otp}} / Elixir ${{matrix.elixir}}
3434
strategy:
3535
matrix:
36-
otp: [23.x, 24.x, 25.1.x, 26.1.x]
37-
elixir: [1.12.x, 1.13.x, 1.14.x, 1.15.x]
38-
exclude:
39-
- otp: 25.1.x
40-
elixir: 1.12.x
41-
- otp: 26.1.x
36+
otp: [24.x, 25.x, 26.1.x]
37+
elixir: [1.15.x]
38+
include:
39+
- otp: 24.x
4240
elixir: 1.12.x
43-
- otp: 25.1.x
44-
elixir: 1.13.x
45-
- otp: 26.1.x
46-
elixir: 1.13.x
47-
- otp: 26.1.x
48-
elixir: 1.14.x
49-
- otp: 23.x
50-
elixir: 1.15.x
5141
needs: check_format
5242
steps:
5343
- uses: actions/checkout@v3
@@ -96,21 +86,11 @@ jobs:
9686
if: ${{ github.ref == 'refs/heads/master' }}
9787
strategy:
9888
matrix:
99-
otp: [23.x, 24.x, 25.1.x, 26.1.x]
100-
elixir: [1.12.x, 1.13.x, 1.14.x, 1.15.x]
101-
exclude:
102-
- otp: 25.1.x
103-
elixir: 1.12.x
104-
- otp: 26.1.x
89+
otp: [24.x, 25.x, 26.1.x]
90+
elixir: [1.15.x]
91+
include:
92+
- otp: 24.x
10593
elixir: 1.12.x
106-
- otp: 25.1.x
107-
elixir: 1.13.x
108-
- otp: 26.1.x
109-
elixir: 1.13.x
110-
- otp: 26.1.x
111-
elixir: 1.14.x
112-
- otp: 23.x
113-
elixir: 1.15.x
11494
steps:
11595
- uses: actions/checkout@v3
11696
- uses: erlef/setup-beam@v1
@@ -130,37 +110,6 @@ jobs:
130110
run: mix run script/run.exs
131111
working-directory: ./interop
132112

133-
dialyzer:
134-
name: Dialyzer
135-
runs-on: ubuntu-20.04
136-
strategy:
137-
matrix:
138-
otp: [25.1.x, 26.1.x]
139-
elixir: [1.15.x]
140-
env:
141-
MIX_ENV: test
142-
steps:
143-
- uses: actions/checkout@v3
144-
- id: set_vars
145-
run: |
146-
mix_hash="${{ hashFiles(format('{0}{1}', github.workspace, '/mix.lock')) }}"
147-
echo "::set-output name=mix_hash::$mix_hash"
148-
- id: cache-plt
149-
uses: actions/cache@v3
150-
with:
151-
path: |
152-
_build/test/plts/dialyzer.plt
153-
_build/test/plts/dialyzer.plt.hash
154-
key: plt-cache-${{ matrix.otp }}-${{ matrix.elixir }}-${{ steps.set_vars.outputs.mix_hash }}
155-
restore-keys: |
156-
plt-cache-${{ matrix.otp }}-${{ matrix.elixir }}-
157-
- uses: erlef/setup-beam@v1
158-
with:
159-
otp-version: ${{matrix.otp}}
160-
elixir-version: ${{matrix.elixir}}
161-
- run: mix deps.get 1>/dev/null
162-
- run: mix dialyzer --format short
163-
164113
check_release:
165114
runs-on: ubuntu-20.04
166115
name: Check release

README.md

+147-16
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,21 @@
11
# gRPC Elixir
22

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

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

1212
## Table of contents
1313

1414
- [Installation](#installation)
1515
- [Usage](#usage)
16+
- [Simple RPC](#simple-rpc)
17+
- [HTTP Transcoding](#http-transcoding)
18+
- [Start Application](#start-application)
1619
- [Features](#features)
1720
- [Benchmark](#benchmark)
1821
- [Contributing](#contributing)
@@ -24,20 +27,49 @@ The package can be installed as:
2427
```elixir
2528
def deps do
2629
[
27-
{:grpc, "~> 0.7"},
28-
# We don't force protobuf as a dependency for more
29-
# flexibility on which protobuf library is used,
30-
# but you probably want to use it as well
31-
{:protobuf, "~> 0.11"}
30+
{:grpc, "~> 0.8"}
3231
]
3332
end
3433
```
3534

3635
## Usage
3736

38-
1. Generate Elixir code from proto file as [protobuf-elixir](https://github.com/tony612/protobuf-elixir#usage) shows(especially the `gRPC Support` section).
37+
1. Write your protobuf file:
38+
39+
```protobuf
40+
syntax = "proto3";
41+
42+
package helloworld;
3943
40-
2. Implement the server side code like below and remember to return the expected message types.
44+
// The request message containing the user's name.
45+
message HelloRequest {
46+
string name = 1;
47+
}
48+
49+
// The response message containing the greeting
50+
message HelloReply {
51+
string message = 1;
52+
}
53+
54+
// The greeting service definition.
55+
service Greeter {
56+
// Greeting function
57+
rpc SayHello (HelloRequest) returns (HelloReply) {}
58+
}
59+
60+
```
61+
62+
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:
63+
64+
```shell
65+
mix protobuf.generate --output-path=./lib --include-path=./priv/protos helloworld.proto
66+
```
67+
68+
In the following sections you will see how to implement gRPC server logic.
69+
70+
### **Simple RPC**
71+
72+
1. Implement the server side code like below and remember to return the expected message types.
4173

4274
```elixir
4375
defmodule Helloworld.Greeter.Server do
@@ -50,9 +82,7 @@ defmodule Helloworld.Greeter.Server do
5082
end
5183
```
5284

53-
3. Start the server
54-
55-
You can start the gRPC server as a supervised process. First, add `GRPC.Server.Supervisor` to your supervision tree.
85+
2. Define gRPC endpoints
5686

5787
```elixir
5888
# Define your endpoint
@@ -62,7 +92,86 @@ defmodule Helloworld.Endpoint do
6292
intercept GRPC.Server.Interceptors.Logger
6393
run Helloworld.Greeter.Server
6494
end
95+
```
96+
97+
We will use this module [in the gRPC server startup section](#start-application).
98+
99+
**__Note:__** For other types of RPC call like streams see [here](interop/lib/interop/server.ex).
100+
101+
### **HTTP Transcoding**
102+
103+
1. Adding [grpc-gateway annotations](https://cloud.google.com/endpoints/docs/grpc/transcoding) to your protobuf file definition:
104+
105+
```protobuf
106+
import "google/api/annotations.proto";
107+
import "google/protobuf/timestamp.proto";
108+
109+
package helloworld;
65110
111+
// The greeting service definition.
112+
service Greeter {
113+
// Sends a greeting
114+
rpc SayHello (HelloRequest) returns (HelloReply) {
115+
option (google.api.http) = {
116+
get: "/v1/greeter/{name}"
117+
};
118+
}
119+
120+
rpc SayHelloFrom (HelloRequestFrom) returns (HelloReply) {
121+
option (google.api.http) = {
122+
post: "/v1/greeter"
123+
body: "*"
124+
};
125+
}
126+
}
127+
```
128+
129+
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):
130+
131+
In mix.exs:
132+
133+
```elixir
134+
def deps do
135+
[
136+
{:grpc, "~> 0.7"},
137+
{:protobuf_generate, "~> 0.1.1"}
138+
]
139+
end
140+
```
141+
142+
And in your terminal:
143+
144+
```shell
145+
mix protobuf.generate \
146+
--include-path=priv/proto \
147+
--include-path=deps/googleapis \
148+
--generate-descriptors=true \
149+
--output-path=./lib \
150+
--plugins=ProtobufGenerate.Plugins.GRPCWithOptions \
151+
google/api/annotations.proto google/api/http.proto helloworld.proto
152+
```
153+
154+
3. Enable http_transcode option in your Server module
155+
```elixir
156+
defmodule Helloworld.Greeter.Server do
157+
use GRPC.Server,
158+
service: Helloworld.Greeter.Service,
159+
http_transcode: true
160+
161+
@spec say_hello(Helloworld.HelloRequest.t, GRPC.Server.Stream.t) :: Helloworld.HelloReply.t
162+
def say_hello(request, _stream) do
163+
%Helloworld.HelloReply{message: "Hello #{request.name}"}
164+
end
165+
end
166+
```
167+
168+
See full application code in [helloworld_transcoding](examples/helloworld_transcoding) example.
169+
170+
### **Start Application**
171+
172+
1. Start gRPC Server in your supervisor tree or Application module:
173+
174+
```elixir
66175
# In the start function of your Application
67176
defmodule HelloworldApp do
68177
use Application
@@ -78,7 +187,7 @@ defmodule HelloworldApp do
78187
end
79188
```
80189

81-
4. Call rpc:
190+
2. Call rpc:
82191

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

93-
Check [examples](examples) and [interop](interop)(Interoperability Test) for some examples.
202+
Check the [examples](examples) and [interop](interop) directories in the project's source code for some examples.
203+
204+
## Client Adapter and Configuration
205+
206+
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:
207+
208+
```elixir
209+
GRPC.Stub.connect("localhost:50051",
210+
# Use Mint adapter instead of default Gun
211+
adapter: GRPC.Client.Adapters.Mint
212+
)
213+
```
214+
215+
The `GRPC.Client.Adapters.Mint` adapter accepts custom configuration. To do so, you can configure it from your mix application via:
216+
217+
```elixir
218+
# File: your application's config file.
219+
config :grpc, GRPC.Client.Adapters.Mint, custom_opts
220+
```
221+
222+
The accepted options for configuration are the ones listed on [Mint.HTTP.connect/4](https://hexdocs.pm/mint/Mint.HTTP.html#connect/4-options)
94223

95224
## Features
96225

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

108239
## Benchmark
109240

examples/helloworld/mix.exs

-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ defmodule Helloworld.Mixfile do
2222
{:jason, "~> 1.3.0"},
2323
{:protobuf, "~> 0.11"},
2424
{:google_protos, "~> 0.3.0"},
25-
{:dialyxir, "~> 1.1", only: [:dev, :test], runtime: false}
2625
]
2726
end
2827
end

examples/helloworld/mix.lock

-3
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,8 @@
11
%{
22
"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"},
33
"cowlib": {:hex, :cowlib, "2.11.0", "0b9ff9c346629256c42ebe1eeb769a83c6cb771a6ee5960bd110ab0b9b872063", [:make, :rebar3], [], "hexpm", "2b3e9da0b21c4565751a6d4901c20d1b4cc25cbb7fd50d91d2ab6dd287bc86a9"},
4-
"dialyxir": {:hex, :dialyxir, "1.1.0", "c5aab0d6e71e5522e77beff7ba9e08f8e02bad90dfbeffae60eaf0cb47e29488", [:mix], [{:erlex, ">= 0.2.6", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "07ea8e49c45f15264ebe6d5b93799d4dd56a44036cf42d0ad9c960bc266c0b9a"},
5-
"erlex": {:hex, :erlex, "0.2.6", "c7987d15e899c7a2f34f5420d2a2ea0d659682c06ac607572df55a43753aa12e", [:mix], [], "hexpm", "2ed2e25711feb44d52b17d2780eabf998452f6efda104877a3881c2f8c0c0c75"},
64
"google_protos": {:hex, :google_protos, "0.3.0", "15faf44dce678ac028c289668ff56548806e313e4959a3aaf4f6e1ebe8db83f4", [:mix], [{:protobuf, "~> 0.10", [hex: :protobuf, repo: "hexpm", optional: false]}], "hexpm", "1f6b7fb20371f72f418b98e5e48dae3e022a9a6de1858d4b254ac5a5d0b4035f"},
75
"gun": {:hex, :grpc_gun, "2.0.1", "221b792df3a93e8fead96f697cbaf920120deacced85c6cd3329d2e67f0871f8", [:rebar3], [{:cowlib, "~> 2.11", [hex: :cowlib, repo: "hexpm", optional: false]}], "hexpm", "795a65eb9d0ba16697e6b0e1886009ce024799e43bb42753f0c59b029f592831"},
86
"jason": {:hex, :jason, "1.3.0", "fa6b82a934feb176263ad2df0dbd91bf633d4a46ebfdffea0c8ae82953714946", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "53fc1f51255390e0ec7e50f9cb41e751c260d065dcba2bf0d08dc51a4002c2ac"},
97
"protobuf": {:hex, :protobuf, "0.11.0", "58d5531abadea3f71135e97bd214da53b21adcdb5b1420aee63f4be8173ec927", [:mix], [{:jason, "~> 1.2", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "30ad9a867a5c5a0616cac9765c4d2c2b7b0030fa81ea6d0c14c2eb5affb6ac52"},
10-
"ranch": {:hex, :ranch, "1.8.0", "8c7a100a139fd57f17327b6413e4167ac559fbc04ca7448e9be9057311597a1d", [:make, :rebar3], [], "hexpm", "49fbcfd3682fab1f5d109351b61257676da1a2fdbe295904176d5e521a2ddfe5"},
118
}

examples/helloworld_transcoding/mix.exs

-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ defmodule Helloworld.Mixfile do
2323
{:protobuf_generate, "~> 0.1.1", only: [:dev, :test]},
2424
{:jason, "~> 1.3.0"},
2525
{:google_protos, "~> 0.3.0"},
26-
{:dialyxir, "~> 1.1", only: [:dev, :test], runtime: false}
2726
]
2827
end
2928
end
-3
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,9 @@
11
%{
22
"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"},
33
"cowlib": {:hex, :cowlib, "2.11.0", "0b9ff9c346629256c42ebe1eeb769a83c6cb771a6ee5960bd110ab0b9b872063", [:make, :rebar3], [], "hexpm", "2b3e9da0b21c4565751a6d4901c20d1b4cc25cbb7fd50d91d2ab6dd287bc86a9"},
4-
"dialyxir": {:hex, :dialyxir, "1.1.0", "c5aab0d6e71e5522e77beff7ba9e08f8e02bad90dfbeffae60eaf0cb47e29488", [:mix], [{:erlex, ">= 0.2.6", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "07ea8e49c45f15264ebe6d5b93799d4dd56a44036cf42d0ad9c960bc266c0b9a"},
5-
"erlex": {:hex, :erlex, "0.2.6", "c7987d15e899c7a2f34f5420d2a2ea0d659682c06ac607572df55a43753aa12e", [:mix], [], "hexpm", "2ed2e25711feb44d52b17d2780eabf998452f6efda104877a3881c2f8c0c0c75"},
64
"google_protos": {:hex, :google_protos, "0.3.0", "15faf44dce678ac028c289668ff56548806e313e4959a3aaf4f6e1ebe8db83f4", [:mix], [{:protobuf, "~> 0.10", [hex: :protobuf, repo: "hexpm", optional: false]}], "hexpm", "1f6b7fb20371f72f418b98e5e48dae3e022a9a6de1858d4b254ac5a5d0b4035f"},
75
"gun": {:hex, :grpc_gun, "2.0.1", "221b792df3a93e8fead96f697cbaf920120deacced85c6cd3329d2e67f0871f8", [:rebar3], [{:cowlib, "~> 2.11", [hex: :cowlib, repo: "hexpm", optional: false]}], "hexpm", "795a65eb9d0ba16697e6b0e1886009ce024799e43bb42753f0c59b029f592831"},
86
"jason": {:hex, :jason, "1.3.0", "fa6b82a934feb176263ad2df0dbd91bf633d4a46ebfdffea0c8ae82953714946", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "53fc1f51255390e0ec7e50f9cb41e751c260d065dcba2bf0d08dc51a4002c2ac"},
97
"protobuf": {:hex, :protobuf, "0.11.0", "58d5531abadea3f71135e97bd214da53b21adcdb5b1420aee63f4be8173ec927", [:mix], [{:jason, "~> 1.2", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "30ad9a867a5c5a0616cac9765c4d2c2b7b0030fa81ea6d0c14c2eb5affb6ac52"},
108
"protobuf_generate": {:hex, :protobuf_generate, "0.1.1", "f6098b85161dcfd48a4f6f1abee4ee5e057981dfc50aafb1aa4bd5b0529aa89b", [:mix], [{:protobuf, "~> 0.11", [hex: :protobuf, repo: "hexpm", optional: false]}], "hexpm", "93a38c8e2aba2a17e293e9ef1359122741f717103984aa6d1ebdca0efb17ab9d"},
11-
"ranch": {:hex, :ranch, "1.8.0", "8c7a100a139fd57f17327b6413e4167ac559fbc04ca7448e9be9057311597a1d", [:make, :rebar3], [], "hexpm", "49fbcfd3682fab1f5d109351b61257676da1a2fdbe295904176d5e521a2ddfe5"},
129
}

examples/route_guide/mix.exs

-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ defmodule RouteGuide.Mixfile do
3333
{:grpc, path: "../../"},
3434
{:protobuf, "~> 0.11"},
3535
{:jason, "~> 1.2"},
36-
{:dialyxir, "~> 1.1", only: [:dev, :test], runtime: false}
3736
]
3837
end
3938
end

examples/route_guide/mix.lock

-3
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
%{
22
"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"},
33
"cowlib": {:hex, :cowlib, "2.11.0", "0b9ff9c346629256c42ebe1eeb769a83c6cb771a6ee5960bd110ab0b9b872063", [:make, :rebar3], [], "hexpm", "2b3e9da0b21c4565751a6d4901c20d1b4cc25cbb7fd50d91d2ab6dd287bc86a9"},
4-
"dialyxir": {:hex, :dialyxir, "1.2.0", "58344b3e87c2e7095304c81a9ae65cb68b613e28340690dfe1a5597fd08dec37", [:mix], [{:erlex, ">= 0.2.6", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "61072136427a851674cab81762be4dbeae7679f85b1272b6d25c3a839aff8463"},
5-
"erlex": {:hex, :erlex, "0.2.6", "c7987d15e899c7a2f34f5420d2a2ea0d659682c06ac607572df55a43753aa12e", [:mix], [], "hexpm", "2ed2e25711feb44d52b17d2780eabf998452f6efda104877a3881c2f8c0c0c75"},
64
"gun": {:hex, :grpc_gun, "2.0.1", "221b792df3a93e8fead96f697cbaf920120deacced85c6cd3329d2e67f0871f8", [:rebar3], [{:cowlib, "~> 2.11", [hex: :cowlib, repo: "hexpm", optional: false]}], "hexpm", "795a65eb9d0ba16697e6b0e1886009ce024799e43bb42753f0c59b029f592831"},
75
"jason": {:hex, :jason, "1.4.0", "e855647bc964a44e2f67df589ccf49105ae039d4179db7f6271dfd3843dc27e6", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "79a3791085b2a0f743ca04cec0f7be26443738779d09302e01318f97bdb82121"},
86
"protobuf": {:hex, :protobuf, "0.11.0", "58d5531abadea3f71135e97bd214da53b21adcdb5b1420aee63f4be8173ec927", [:mix], [{:jason, "~> 1.2", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "30ad9a867a5c5a0616cac9765c4d2c2b7b0030fa81ea6d0c14c2eb5affb6ac52"},
9-
"ranch": {:hex, :ranch, "1.8.0", "8c7a100a139fd57f17327b6413e4167ac559fbc04ca7448e9be9057311597a1d", [:make, :rebar3], [], "hexpm", "49fbcfd3682fab1f5d109351b61257676da1a2fdbe295904176d5e521a2ddfe5"},
107
}

0 commit comments

Comments
 (0)