# google_pubsub_grpc
API wrapper around [Google Pub Sub gRPC protocol](https://cloud.google.com/pubsub/docs/reference/rpc). Code in `lib/google/pubsub/v1/pubsub.pb.ex` is generated using the `protoc` utility. Check [protobuf-elixir package](https://github.com/tony612/protobuf-elixir) for more details, if interested.
The only thing this package adds to the auto-generated client code is a few helper methods.
## 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"},
{:google_pubsub_grpc, "~> 0.2.0-beta.1"}
]
end
```
## Configuration
Set the environment variable `GOOGLE_APPLICATION_CREDENTIALS` to point to a gcloud credentials file.
The [goth package](https://github.com/peburrows/goth) shows more ways to configure access, e.g.:
```elixir
config :goth, json: File.read!(System.get_env("GOOGLE_APPLICATION_CREDENTIALS"))
```
After configuration, Google project id is available by calling helper functions `Google.Pubsub.GRPC.project_id()` or `Google.Pubsub.GRPC.full_project_id()` (with `"projects/"` prepended to it.
## Emulator Support
Method `Google.Pubsub.GRPC.channel` checks environment variable `PUBSUB_EMULATOR_HOST` and if present (e.g. `localhost:8787`) uses its value as the server endpoint.
```elixir
{:ok, channel} = Google.Pubsub.GRPC.channel()
```
To define Google project id for the emulator use goth configuration like so:
```elixir
config :goth, json: nil, project_id: "emulator-project-id"
```
## API Usage
Note that project id, topic and subscription names are passed to the grpc client in their "full" form, e.g. `"projects/my-project/topics/my-topic"`. There are a couple of helper functions in the `Google.Api.PubSub.GRPC` module to convert between the full form and its shorter variant, e.g. `"my-topic"`.
To get a channel (connection to server):
```elixir
{:ok, channel} = Google.Pubsub.GRPC.channel()
```
Additional options are `interceptors` and `accepted_compressors`:
```elixir
{:ok, channel} = Google.Pubsub.GRPC.channel(interceptors: [GRPC.Logger.Client])
{:ok, channel} = Google.Pubsub.GRPC.channel(interceptors: [{GRPC.Logger.Client, level: :info}]
{:ok, channel} = Google.Pubsub.GRPC.channel(accepted_compressors: [GRPC.Compressor.Gzip])
```
To get the list of topics:
```elixir
request =
Google.Pubsub.V1.ListTopicsRequest.new(project: Google.Pubsub.GRPC.full_project_id())
{:ok, response} = channel |> Google.Pubsub.V1.Publisher.Stub.list_topics(request)
```
To get topic's details:
```elixir
request =
Google.Pubsub.V1.GetTopicRequest.new(
topic: Google.Pubsub.GRPC.full_topic_name("my-topic")
)
{:ok, response} = channel |> Google.Pubsub.V1.Publisher.Stub.get_topic(request)
```
To create a new topic:
```elixir
{:ok, topic} =
channel
|> Google.Pubsub.V1.Publisher.Stub.create_topic(%Google.Pubsub.V1.Topic{
name: Google.Pubsub.GRPC.full_topic_name("my-topic")
})
```
To delete a topic:
```elixir
{:ok, _} =
channel
|> Google.Pubsub.V1.Publisher.Stub.delete_topic(%Google.Pubsub.V1.Topic{
name: Google.Pubsub.GRPC.full_topic_name("my-topic")
})
```
To create a new subscription on a topic:
```elixir
{:ok, subscription} =
channel
|> Google.Pubsub.V1.Subscriber.Stub.create_subscription(%Google.Pubsub.V1.Subscription{
topic: Google.Pubsub.GRPC.full_topic_name("my-topic"),
name: Google.Pubsub.GRPC.full_subscription_name("my-subscription")
})
```
To delete a subscription:
```elixir
request = %Google.Pubsub.V1.DeleteSubscriptionRequest{
subscription: Google.Pubsub.GRPC.full_subscription_name("my-subscription")
}
{:ok, _} = channel |> Google.Pubsub.V1.Subscriber.Stub.delete_subscription(request)
```
To publish a message on a topic:
```elixir
message = %Google.Pubsub.V1.PubsubMessage{data: "string"}
request = %Google.Pubsub.V1.PublishRequest{
topic: Google.Pubsub.GRPC.full_topic_name("my-topic"),
messages: [message]
}
{:ok, response} = channel |> Google.Pubsub.V1.Publisher.Stub.publish(request)
```
To pull messages from a subscription:
```elixir
request = %Google.Pubsub.V1.PullRequest{
subscription: Google.Pubsub.GRPC.full_subscription_name("my-subscription"),
max_messages: 10
}
{:ok, response} = channel |> Google.Pubsub.V1.Subscriber.Stub.pull(request)
```
To acknowledge received messages:
```elixir
request = %Google.Pubsub.V1.AcknowledgeRequest{
subscription: Google.Pubsub.GRPC.full_subscription_name("my-subscription"),
ack_ids: Enum.map(messages, fn m -> m.ack_id end)
}
{:ok, response} = channel |> Google.Pubsub.V1.Subscriber.Stub.acknowledge(request)
'``