Packages

Elixir API wrapper for Google Pubsub service (grpc endpoint)

Current section

Files

Jump to
google_pubsub_grpc lib google_api_pub_sub_grpc.ex
Raw

lib/google_api_pub_sub_grpc.ex

defmodule Google.Pubsub.GRPC do
@moduledoc """
Google.Pubsub.GRPC is a thin wrapper around gRPC-based Google Pubsub Service.
It uses [grpc package](https://hex.pm/packages/grpc) for grpc communication, and
doesn't attempt to add much more to the code generated by `protoc` (mostly adding
support for the pubsub emulator, token authorization, as well as some examples).
## Installation
Add the following to your `mix.exs`:
```elixir
def deps do
[
{:goth, "~> 1.2.0"},
{:cowlib, "~> 2.9.0", override: true},
{:google_protos, "~> 0.1.0"},
{:grpc, github: "elixir-grpc/grpc", override: true},
{:google_pubsub_grpc, "~> 0.1.0"}
]
end
```
"""
require Logger
@emulator_host_env "PUBSUB_EMULATOR_HOST"
@googleapis_endpoint "pubsub.googleapis.com:443"
@oath_scope "https://www.googleapis.com/auth/pubsub"
@doc """
Obtains a connection (channel) with gRPC server.
Authorization tokens are by default generated by Goth, but can be overriden,
if so desired.
## Examples
Google.Pubsub.GRPC.channel()
Google.Pubsub.GRPC.channel(interceptors: [GRPC.Logger.Client])
Google.Pubsub.GRPC.channel(interceptors: [GRPC.Logger.Client, level: :info])
Google.Pubsub.GRPC.channel(accepted_compressors: [GRPC.Compressor.Gzip])
Google.Pubsub.GRPC.channel(headers: ["authorization": "my custom token"])
"""
@spec channel(opts :: Keyword.t()) ::
{:ok, %GRPC.Channel{}} | {:error, %GRPC.RPCError{}}
def channel(opts \\ []) do
opts = Keyword.merge(connect_defaults(), opts)
case GRPC.Stub.connect(endpoint(), opts) do
{:ok, channel} ->
{:ok, channel}
err ->
Logger.error("Failed to connect to endpoint #{endpoint()}")
err
end
end
def full_project_id do
"projects/#{project_id()}"
end
def full_topic_name(name) do
"projects/#{project_id()}/topics/#{name}"
end
def full_subscription_name(name) do
"projects/#{project_id()}/subscriptions/#{name}"
end
def stripped_name(full_name) do
String.replace(full_name, ~r(^.*/), "")
end
defp using_pubsub_emulator? do
!is_nil(System.get_env(@emulator_host_env))
end
defp endpoint do
case using_pubsub_emulator?() do
true -> System.get_env(@emulator_host_env)
false -> @googleapis_endpoint
end
end
defp connect_defaults do
case using_pubsub_emulator?() do
true ->
[headers: [authorization: "Dummy token"]]
false ->
{:ok, token} = Goth.Token.for_scope(@oath_scope)
[headers: [authorization: "#{token.type} #{token.token}"], cred: %{ssl: []}]
end
end
defp project_id do
# Goth will raise on start-up if can't determine the project, so this should always work
Goth.Config.get(:project_id) |> elem(1)
end
end