### Start gRPC Emulator with Docker Compose Source: https://hexdocs.pm/grpc_connection_pool/readme.md Starts the Google Pub/Sub emulator using Docker Compose. Ensure Docker Compose is installed and configured. ```bash # Using Docker Compose (if available) docker-compose up -d ``` -------------------------------- ### Complete Application Module Examples Source: https://hexdocs.pm/grpc_connection_pool/readme.md Full application module implementations for single and multiple pool setups. ```elixir # lib/my_app/application.ex defmodule MyApp.Application do use Application def start(_type, _args) do # Single pool from config {:ok, config} = GrpcConnectionPool.Config.from_env(:my_app) children = [ # Your other processes... {GrpcConnectionPool, config} ] opts = [strategy: :one_for_one, name: MyApp.Supervisor] Supervisor.start_link(children, opts) end end ``` ```elixir # lib/my_app/application.ex defmodule MyApp.Application do use Application def start(_type, _args) do # Load configurations for different services {:ok, service_a_config} = GrpcConnectionPool.Config.from_env(:my_app, :service_a) {:ok, service_b_config} = GrpcConnectionPool.Config.from_env(:my_app, :service_b) children = [ # Your other services... {GrpcConnectionPool, service_a_config}, {GrpcConnectionPool, service_b_config} ] opts = [strategy: :one_for_one, name: MyApp.Supervisor] Supervisor.start_link(children, opts) end end ``` -------------------------------- ### Production Configuration Example Source: https://hexdocs.pm/grpc_connection_pool/readme.md Standard production setup using default SSL settings. ```elixir # For a production gRPC service with SSL config :my_app, GrpcConnectionPool, endpoint: [ type: :production, host: "api.example.com", port: 443, ssl: [] # Use default SSL settings ], pool: [ size: 10, name: MyApp.GrpcPool ], connection: [ keepalive: 30_000, # Send keepalive every 30 seconds ping_interval: 25_000, # Ping every 25 seconds to keep warm health_check: true ] ``` -------------------------------- ### Development Setup for gRPC Connection Pool Source: https://hexdocs.pm/grpc_connection_pool/readme.md Clone the repository, install dependencies, and run tests to set up the development environment for the gRPC connection pool. ```bash git clone https://github.com/nyo16/grpc_connection_pool.git cd grpc_connection_pool mix deps.get mix test ``` -------------------------------- ### Start a Pool Source: https://hexdocs.pm/grpc_connection_pool/GrpcConnectionPool.md Initialize and start a connection pool for production or local development environments. ```elixir # Production gRPC service {:ok, config} = GrpcConnectionPool.Config.production( host: "api.example.com", port: 443, pool_size: 10 ) {:ok, _pid} = GrpcConnectionPool.start_link(config) # Local development {:ok, config} = GrpcConnectionPool.Config.local(port: 9090) {:ok, _pid} = GrpcConnectionPool.start_link(config) ``` -------------------------------- ### Start gRPC Emulator Manually Source: https://hexdocs.pm/grpc_connection_pool/readme.md Manually starts the Google Pub/Sub emulator using a Docker container. This command exposes the emulator on port 8085. ```bash # Or manually docker run --rm -p 8085:8085 google/cloud-sdk:emulators-pubsub \ /google-cloud-sdk/bin/gcloud beta emulators pubsub start \ --host-port=0.0.0.0:8085 --project=test-project ``` -------------------------------- ### Start and Await Pool Readiness Source: https://hexdocs.pm/grpc_connection_pool/GrpcConnectionPool.Pool.md Starts a new connection pool and then blocks until at least one channel is connected or a timeout is reached. Useful for application startup. ```elixir {:ok, _} = GrpcConnectionPool.Pool.start_link(config) :ok = GrpcConnectionPool.Pool.await_ready(MyPool, 5_000) ``` -------------------------------- ### start_link Source: https://hexdocs.pm/grpc_connection_pool/index.html Starts a new connection pool with the provided configuration. ```APIDOC ## start_link(config, opts) ### Description Starts a connection pool with the given configuration. ### Parameters #### Arguments - **config** (map) - Required - Configuration settings for the pool. - **opts** (list) - Optional - Additional options (defaults to []). ### Response - **{:ok, pid}** - Returns the PID of the started pool process. ``` -------------------------------- ### GrpcConnectionPool.start_link Source: https://hexdocs.pm/grpc_connection_pool/GrpcConnectionPool.md Starts a connection pool with the given configuration. ```APIDOC ## POST /pool/start_link ### Description Starts a connection pool with the given configuration. This is a convenience function that delegates to `GrpcConnectionPool.Pool.start_link/2`. ### Method POST ### Endpoint /pool/start_link ### Parameters #### Request Body - **config** (object) - Required - Configuration for the connection pool. Example: `{:ok, config} = GrpcConnectionPool.Config.production(host: "api.example.com")` ### Request Example ```json { "config": { "host": "api.example.com", "port": 443 } } ``` ### Response #### Success Response (200) - **status** (string) - Indicates the result of the operation, e.g., :ok - **pid** (pid) - The process identifier of the started connection pool #### Response Example ```json { "status": ":ok", "pid": "<0.123.456>" } ``` ``` -------------------------------- ### Configure and Start Test gRPC Connection Pool Source: https://hexdocs.pm/grpc_connection_pool/readme.md Sets up a local gRPC connection pool for testing purposes. It configures the pool to connect to a local service and starts the pool process. ```elixir # In your test helper defmodule MyApp.TestHelper do def start_test_pool do {:ok, config} = GrpcConnectionPool.Config.local( host: "localhost", port: 8085, # Your test service port pool_size: 1 ) {:ok, _pid} = GrpcConnectionPool.start_link(config, name: TestPool) end def stop_test_pool do GrpcConnectionPool.stop(TestPool) end end # In your tests defmodule MyApp.GrpcTest do use ExUnit.Case setup do MyApp.TestHelper.start_test_pool() on_exit(&MyApp.TestHelper.stop_test_pool/0) end test "grpc operation works" do operation = fn channel -> # Your gRPC test operation end assert {:ok, result} = GrpcConnectionPool.execute(operation, pool: TestPool) end end ``` -------------------------------- ### Configure gRPC Connection Pool Source: https://hexdocs.pm/grpc_connection_pool/GrpcConnectionPool.Config.md Examples of initializing the GrpcConnectionPool.Config struct for various scenarios. ```elixir config = %GrpcConnectionPool.Config{ endpoint: %{ type: :production, host: "api.example.com", port: 443, ssl: [] }, pool: %{ size: 10, name: MyApp.GrpcPool } } ``` ```elixir config = %GrpcConnectionPool.Config{ endpoint: %{ type: :test, host: "localhost", port: 9090 }, pool: %{ size: 3 } } ``` ```elixir config = %GrpcConnectionPool.Config{ endpoint: %{ type: :production, host: "secure-api.example.com", port: 443, credentials: GRPC.Credential.new(ssl: [ verify: :verify_peer, cacertfile: "/path/to/ca.pem" ]) } } ``` ```elixir config = %GrpcConnectionPool.Config{ endpoint: %{ type: :production, host: "api.example.com", port: 443, interceptors: [MyApp.LoggingInterceptor, MyApp.AuthInterceptor] } } ``` -------------------------------- ### Start Production Pool Source: https://hexdocs.pm/grpc_connection_pool/index.html Start a gRPC connection pool for a production gRPC service. Ensure to configure the host, port, and desired pool size. ```elixir # Production gRPC service {:ok, config} = GrpcConnectionPool.Config.production( host: "api.example.com", port: 443, pool_size: 10 ) {:ok, _pid} = GrpcConnectionPool.start_link(config) ``` -------------------------------- ### Start Local Development Pool Source: https://hexdocs.pm/grpc_connection_pool/index.html Start a gRPC connection pool for local development. Specify the local port for the gRPC service. ```elixir # Local development {:ok, config} = GrpcConnectionPool.Config.local(port: 9090) {:ok, _pid} = GrpcConnectionPool.start_link(config) ``` -------------------------------- ### Start Emulator Pool for Tests Source: https://hexdocs.pm/grpc_connection_pool/index.html Configure and start a gRPC connection pool specifically for testing with emulators. Assign a name to the test pool for easy access within tests. ```elixir # Start emulator pool for tests {:ok, config} = GrpcConnectionPool.Config.local( host: "localhost", port: 8085, pool_size: 2 ) {:ok, _pid} = GrpcConnectionPool.start_link(config, name: TestPool) # Use in tests test "my grpc operation" do assert {:ok, channel} = GrpcConnectionPool.get_channel(TestPool) # Use channel for gRPC calls end ``` -------------------------------- ### Basic GrpcConnectionPool Usage Source: https://hexdocs.pm/grpc_connection_pool/readme.md Demonstrates how to create a production configuration, start a connection pool, and execute gRPC operations using the pool. Ensure your gRPC service stub and request/response types are defined. ```elixir # Create configuration {:ok, config} = GrpcConnectionPool.Config.production( host: "api.example.com", port: 443, pool_size: 5 ) # Start pool {:ok, _pid} = GrpcConnectionPool.start_link(config) # Execute gRPC operations operation = fn channel -> request = %MyService.ListRequest{} MyService.Stub.list(channel, request) end {:ok, response} = GrpcConnectionPool.execute(operation) ``` -------------------------------- ### Multiple Service Configuration Example Source: https://hexdocs.pm/grpc_connection_pool/readme.md Defining separate pools for multiple distinct gRPC services. ```elixir # Configuration for multiple gRPC services config :my_app, :service_a, endpoint: [ type: :production, host: "service-a.example.com", port: 443 ], pool: [ size: 5, name: MyApp.ServiceAPool ] config :my_app, :service_b, endpoint: [ type: :production, host: "service-b.example.com", port: 443 ], pool: [ size: 8, name: MyApp.ServiceBPool ] ``` -------------------------------- ### Start gRPC Connection Pool Source: https://hexdocs.pm/grpc_connection_pool/index.html Initializes a new gRPC connection pool with provided configuration. Requires a configuration object and optional arguments. ```elixir {:ok, config} = GrpcConnectionPool.Config.production(host: "api.example.com") {:ok, pid} = GrpcConnectionPool.start_link(config) ``` -------------------------------- ### Start gRPC Connection Pool Source: https://hexdocs.pm/grpc_connection_pool/GrpcConnectionPool.Pool.md Starts a new gRPC connection pool with the provided configuration. An optional name can be provided to override the name specified in the config. ```elixir @spec start_link( GrpcConnectionPool.Config.t() | keyword(), keyword() ) :: Supervisor.on_start() Starts a new connection pool. ## Options - `:name` — Pool name (overrides config name) ## Examples {:ok, config} = GrpcConnectionPool.Config.production(host: "api.example.com", pool_size: 8) {:ok, pid} = GrpcConnectionPool.Pool.start_link(config) ``` -------------------------------- ### Start gRPC Connection Worker Source: https://hexdocs.pm/grpc_connection_pool/GrpcConnectionPool.Worker.md Starts a new gRPC connection worker process. Requires configuration, registry name, and pool name. ```elixir @spec start_link(keyword()) :: GenServer.on_start() ``` -------------------------------- ### Local Development Configuration for GrpcConnectionPool Source: https://hexdocs.pm/grpc_connection_pool/readme.md Shows how to configure and start a GrpcConnectionPool for local development, typically connecting to a gRPC server running on localhost. ```elixir {:ok, config} = GrpcConnectionPool.Config.local( host: "localhost", port: 9090, pool_size: 3 ) {:ok, _pid} = GrpcConnectionPool.start_link(config) ``` -------------------------------- ### Start Multiple Pools Source: https://hexdocs.pm/grpc_connection_pool/index.html Configure and start multiple named gRPC connection pools for different services. This allows managing connections to distinct gRPC endpoints independently. ```elixir # Start multiple pools for different services {:ok, service_a_config} = GrpcConnectionPool.Config.production( host: "service-a.example.com", pool_name: ServiceA.Pool ) {:ok, service_b_config} = GrpcConnectionPool.Config.production( host: "service-b.example.com", pool_name: ServiceB.Pool ) children = [ {GrpcConnectionPool, service_a_config}, {GrpcConnectionPool, service_b_config} ] # Use specific pools {:ok, channel_a} = GrpcConnectionPool.get_channel(ServiceA.Pool) {:ok, channel_b} = GrpcConnectionPool.get_channel(ServiceB.Pool) ``` -------------------------------- ### Advanced SSL Configuration Source: https://hexdocs.pm/grpc_connection_pool/readme.md Custom SSL setup using client certificates for secure connections. ```elixir # Custom SSL configuration with client certificates config :my_app, GrpcConnectionPool, endpoint: [ type: :production, host: "secure-api.example.com", port: 443, credentials: GRPC.Credential.new(ssl: [ verify: :verify_peer, cacertfile: "/path/to/ca.pem", certfile: "/path/to/client.pem", keyfile: "/path/to/client-key.pem" ]) ] ``` -------------------------------- ### GrpcConnectionPool.Worker - start_link Source: https://hexdocs.pm/grpc_connection_pool/GrpcConnectionPool.Worker.md Starts a new gRPC connection worker process. ```APIDOC ## start_link ### Description Starts a connection worker. ### Method POST ### Endpoint `/grpc_connection_pool/worker/start_link` ### Parameters #### Query Parameters - **config** (GrpcConnectionPool.Config) - Required - The configuration for the connection pool. - **registry_name** (Registry.name()) - Required - The name of the registry for self-registration. - **pool_name** (atom()) - Required - The name of the pool for telemetry. ### Request Example ```json { "config": {...}, "registry_name": :my_registry, "pool_name": :my_pool } ``` ### Response #### Success Response (200) - **GenServer.on_start()** - The result of starting the GenServer process. ``` -------------------------------- ### GrpcConnectionPool.Worker - child_spec Source: https://hexdocs.pm/grpc_connection_pool/GrpcConnectionPool.Worker.md Returns a specification to start the GrpcConnectionPool.Worker module under a supervisor. ```APIDOC ## child_spec ### Description Returns a specification to start this module under a supervisor. See `Supervisor`. ``` -------------------------------- ### Get Channel Convenience Source: https://hexdocs.pm/grpc_connection_pool/GrpcConnectionPool.md Retrieve a channel from the default or a specific pool. ```elixir case GrpcConnectionPool.get_channel() do {:ok, channel} -> request = %MyService.ListRequest{} MyService.Stub.list(channel, request) {:error, :not_connected} -> {:error, :unavailable} end # Use specific pool {:ok, channel} = GrpcConnectionPool.get_channel(MyApp.CustomPool) ``` -------------------------------- ### Initialize and Use Backoff State Source: https://hexdocs.pm/grpc_connection_pool/GrpcConnectionPool.Backoff.md Initialize backoff state with min and max delays. On connection failure, get the next delay and schedule a reconnect. On successful connection, reset the backoff state. ```elixir state = GrpcConnectionPool.Backoff.new(min: 1000, max: 30_000) # On connection failure, get next delay {delay_ms, new_state} = GrpcConnectionPool.Backoff.fail(state) Process.send_after(self(), :reconnect, delay_ms) # On successful connection, reset backoff new_state = GrpcConnectionPool.Backoff.succeed(state) ``` -------------------------------- ### Get Channel and Make Request Source: https://hexdocs.pm/grpc_connection_pool/index.html Retrieve a gRPC channel from the pool and use it to make a service call. Handles the case where no connection is available. ```elixir case GrpcConnectionPool.get_channel() do {:ok, channel} -> request = %MyService.ListRequest{} MyService.Stub.list(channel, request) {:error, :not_connected} -> {:error, :unavailable} end ``` -------------------------------- ### Get Child Specification for Supervision Source: https://hexdocs.pm/grpc_connection_pool/index.html Generate a child specification for the GrpcConnectionPool, suitable for inclusion in Elixir supervision trees. This ensures the pool is managed by the OTP system. ```elixir children = [ {GrpcConnectionPool, [ endpoint: [type: :production, host: "api.example.com"], pool: [size: 10] ]}] ] ``` -------------------------------- ### Implement Strategy Initialization Source: https://hexdocs.pm/grpc_connection_pool/GrpcConnectionPool.Strategy.md Callback for initializing the strategy state during pool startup. ```elixir @callback init(pool_name :: atom(), pool_size :: pos_integer()) :: state() ``` -------------------------------- ### production/1 Source: https://hexdocs.pm/grpc_connection_pool/GrpcConnectionPool.Config.md Creates a production-ready configuration with SSL support. ```APIDOC ## production/1 ### Description Creates a production configuration with SSL enabled. ### Parameters #### Options - **:host** (string) - Required - Hostname. - **:port** (integer) - Optional - Port (default: 443). - **:pool_size** (integer) - Optional - Number of connections (default: 5). - **:pool_name** (atom) - Optional - Pool name (default: auto-generated). - **:ssl** (keyword) - Optional - SSL configuration (default: []). ### Response #### Success Response - **{:ok, t()}** - Returns the configuration struct. #### Error Response - **{:error, String.t()}** - Returns an error message if configuration fails. ``` -------------------------------- ### Configure Runtime Environment Source: https://hexdocs.pm/grpc_connection_pool/readme.md Set up dynamic configuration in config/runtime.exs using system environment variables. ```elixir import Config if config_env() == :prod do # Get configuration from environment variables grpc_host = System.get_env("GRPC_HOST") || "api.example.com" grpc_port = System.get_env("GRPC_PORT", "443") |> String.to_integer() pool_size = System.get_env("GRPC_POOL_SIZE", "10") |> String.to_integer() config :my_app, GrpcConnectionPool, endpoint: [ type: :production, host: grpc_host, port: grpc_port ], pool: [size: pool_size] end ``` -------------------------------- ### GrpcConnectionPool.status Source: https://hexdocs.pm/grpc_connection_pool/GrpcConnectionPool.md Gets pool status and statistics. ```APIDOC ## GET /pool/status ### Description Gets pool status and statistics. ### Method GET ### Endpoint /pool/status ### Parameters #### Query Parameters - **pool_name** (string) - Optional - The name of the pool to get status for. If not provided, status for the default pool is returned. ### Response #### Success Response (200) - **status** (map) - A map containing status and statistics of the connection pool. #### Response Example ```json { "status": { "active_connections": 5, "idle_connections": 2, "total_workers": 10, "requests_processed": 1000 } } ``` ``` -------------------------------- ### Initialize GrpcConnectionPool Config Source: https://hexdocs.pm/grpc_connection_pool/readme.md Create a new configuration struct programmatically using GrpcConnectionPool.Config.new/1. ```elixir {:ok, config} = GrpcConnectionPool.Config.new([ endpoint: [ type: :production, # :production, :local, or custom atom host: "api.example.com", # Required: gRPC server hostname port: 443, # Required: gRPC server port ssl: [], # SSL options ([] for default SSL) credentials: nil, # Custom GRPC.Credential (overrides ssl) interceptors: nil, # List of gRPC client interceptors (modules) retry_config: [ # Optional: retry configuration max_attempts: 3, base_delay: 1000, max_delay: 5000 ] ], pool: [ size: 5, # Number of connections in pool name: MyApp.GrpcPool, # Pool name (must be unique) strategy: :round_robin # :round_robin | :random | :power_of_two | CustomModule ], connection: [ keepalive: 30_000, # HTTP/2 keepalive interval ping_interval: 25_000, # Ping interval to keep connections warm health_check: true, # Enable connection health monitoring suppress_connection_errors: false # Suppress gun_down/gun_error logs (useful for GCP endpoints) ] ]) ``` -------------------------------- ### GrpcConnectionPool.Config.new Source: https://hexdocs.pm/grpc_connection_pool/GrpcConnectionPool.Config.md Initializes a new configuration object using explicit options. ```APIDOC ## Configuration Initialization ### Description Creates a new configuration for the gRPC connection pool using a keyword list of options. ### Parameters #### Request Body - **endpoint** (keyword) - Required - Configuration for the gRPC endpoint including :type, :host, and :port. - **pool** (keyword) - Optional - Configuration for the pool including :size and :name. ``` -------------------------------- ### new/1 Source: https://hexdocs.pm/grpc_connection_pool/GrpcConnectionPool.Config.md Creates a new pool configuration from keyword options. ```APIDOC ## new(options) ### Description Creates a new pool configuration from keyword options or environment variables. ### Parameters #### Options - **endpoint** (map) - Optional - Endpoint configuration (type, host, port, ssl, credentials, retry_config, interceptors) - **pool** (map) - Optional - Pool configuration (size, name, checkout_timeout) - **connection** (map) - Optional - Connection settings (keepalive, health_check, ping_interval) ### Response - **{:ok, t()}** - Success response. - **{:error, String.t()}** - Error response if configuration is invalid. ``` -------------------------------- ### Configure Development Environment Source: https://hexdocs.pm/grpc_connection_pool/readme.md Set up a local connection pool with disabled pinging for development environments. ```elixir # config/dev.exs config :my_app, GrpcConnectionPool, endpoint: [ type: :local, host: "localhost", port: 9090 # Local gRPC server ], pool: [size: 2], # Smaller pool for development connection: [ ping_interval: nil # Disable pinging for local development ] ``` -------------------------------- ### Get Pool Status and Statistics Source: https://hexdocs.pm/grpc_connection_pool/GrpcConnectionPool.Pool.md Retrieves the current status and statistics of the specified connection pool. ```elixir @spec status(atom()) :: map() Gets pool status and statistics. ``` -------------------------------- ### from_env/2 Source: https://hexdocs.pm/grpc_connection_pool/GrpcConnectionPool.Config.md Creates a pool configuration from application environment variables. ```APIDOC ## from_env(app, key) ### Description Creates a pool configuration from application environment variables based on the provided application and key. ### Parameters #### Arguments - **app** (atom) - Required - The application name. - **key** (atom) - Required - The configuration key. ### Response - **{:ok, t()}** - Success response containing the configuration struct. - **{:error, String.t()}** - Error response if configuration is invalid. ``` -------------------------------- ### Get All Worker PIDs Source: https://hexdocs.pm/grpc_connection_pool/GrpcConnectionPool.Pool.md Retrieves a list of all worker PIDs currently active in the specified connection pool. ```elixir @spec get_all_pids(atom()) :: [pid()] Gets all worker PIDs in the pool. ``` -------------------------------- ### Initialize gRPC Connection Pool Configuration Source: https://hexdocs.pm/grpc_connection_pool/GrpcConnectionPool.Config.md Create a configuration object using either explicit options or existing application environment settings. ```elixir # From explicit options {:ok, config} = GrpcConnectionPool.Config.new([ endpoint: [type: :test, host: "localhost", port: 9090], pool: [size: 8, name: MyApp.CustomPool] ]) # From application environment {:ok, config} = GrpcConnectionPool.Config.from_env(:my_app) ``` -------------------------------- ### Get gRPC Channel Status Source: https://hexdocs.pm/grpc_connection_pool/GrpcConnectionPool.Worker.md Retrieves the current gRPC channel if the worker is connected. Returns an error if not connected. ```elixir @spec get_channel(pid()) :: {:ok, GRPC.Channel.t()} | {:error, :not_connected} ``` -------------------------------- ### Load Configuration from Environment Source: https://hexdocs.pm/grpc_connection_pool/readme.md Load pool configurations using the application environment. ```elixir # Single pool {:ok, config} = GrpcConnectionPool.Config.from_env(:my_app) # Multiple pools {:ok, service_a_config} = GrpcConnectionPool.Config.from_env(:my_app, :service_a) {:ok, service_b_config} = GrpcConnectionPool.Config.from_env(:my_app, :service_b) ``` -------------------------------- ### Check gRPC Connection Status Source: https://hexdocs.pm/grpc_connection_pool/GrpcConnectionPool.Worker.md Gets the current connection status of the gRPC worker. Returns either :connected or :disconnected. ```elixir @spec status(pid()) :: :connected | :disconnected ``` -------------------------------- ### Reset Backoff State After Success Source: https://hexdocs.pm/grpc_connection_pool/GrpcConnectionPool.Backoff.md Resets the backoff state after a successful connection. This ensures that the next failure will start with the minimum delay again. ```elixir state = GrpcConnectionPool.Backoff.new(min: 1000, max: 30_000) {_delay, failed_state} = GrpcConnectionPool.Backoff.fail(state) reset_state = GrpcConnectionPool.Backoff.succeed(failed_state) # reset_state is back to initial state ``` -------------------------------- ### GrpcConnectionPool.Config.from_env Source: https://hexdocs.pm/grpc_connection_pool/GrpcConnectionPool.Config.md Loads configuration from the application environment. ```APIDOC ## Load from Environment ### Description Loads the gRPC connection pool configuration from the specified application environment key. ### Parameters #### Query Parameters - **app_name** (atom) - Required - The application name to fetch configuration from. ``` -------------------------------- ### local/1 Source: https://hexdocs.pm/grpc_connection_pool/GrpcConnectionPool.Config.md Creates a local or test configuration without SSL. ```APIDOC ## local(options) ### Description Creates a local/test configuration without SSL enabled. ### Parameters #### Options - **:host** (String.t) - Optional - Hostname (default: "localhost") - **:port** (pos_integer) - Optional - Port (default: 9090) - **:pool_size** (pos_integer) - Optional - Number of connections (default: 3) - **:pool_name** (atom) - Optional - Pool name (default: auto-generated) ### Response - **{:ok, t()}** - Success response containing the local configuration. ``` -------------------------------- ### Get gRPC Pool Status Source: https://hexdocs.pm/grpc_connection_pool/index.html Retrieves the current status and statistics of the gRPC connection pool. Can query a specific pool by name. ```elixir status = GrpcConnectionPool.status() status = GrpcConnectionPool.status(MyApp.CustomPool) ``` -------------------------------- ### Configure Production Environment Source: https://hexdocs.pm/grpc_connection_pool/readme.md Optimize pool size and connection keepalive settings for production traffic. ```elixir # config/prod.exs config :my_app, GrpcConnectionPool, endpoint: [ type: :production, host: "api.example.com", port: 443, ssl: [] # Use default SSL ], pool: [ size: 20, # Large pool for production load checkout_timeout: 10_000 ], connection: [ keepalive: 30_000, ping_interval: 25_000, health_check: true ] ``` -------------------------------- ### Configuration Functions Source: https://hexdocs.pm/grpc_connection_pool/GrpcConnectionPool.Config.md Functions for creating and retrieving configuration settings. ```elixir @spec from_env(atom(), atom()) :: {:ok, t()} | {:error, String.t()} ``` ```elixir config :my_app, GrpcConnectionPool, endpoint: [type: :production, host: "api.example.com", port: 443], pool: [size: 10], connection: [keepalive: 45_000] ``` ```elixir @spec get_endpoint(t()) :: {String.t(), pos_integer(), keyword()} ``` ```elixir @spec get_retry_config(t()) :: retry_config() | nil ``` ```elixir @spec local(keyword()) :: {:ok, t()} ``` ```elixir @spec new(keyword()) :: {:ok, t()} | {:error, String.t()} ``` -------------------------------- ### Configure via config/config.exs Source: https://hexdocs.pm/grpc_connection_pool/readme.md Define connection pool settings within the application's configuration files for single or multiple services. ```elixir # Single service configuration config :my_app, GrpcConnectionPool, endpoint: [ type: :production, host: "api.example.com", port: 443, ssl: [] ], pool: [ size: 10, name: MyApp.GrpcPool ], connection: [ ping_interval: 30_000 ] # Multiple service configuration config :my_app, :service_a, endpoint: [type: :production, host: "service-a.example.com"], pool: [size: 5, name: MyApp.ServiceA.Pool] config :my_app, :service_b, endpoint: [type: :production, host: "service-b.example.com"], pool: [size: 8, name: MyApp.ServiceB.Pool] ``` -------------------------------- ### Get gRPC Channel from Pool Source: https://hexdocs.pm/grpc_connection_pool/index.html Retrieves a gRPC channel for immediate use. Handles connection errors gracefully. Can specify a custom pool. ```elixir case GrpcConnectionPool.get_channel() do {:ok, channel} -> request = %MyService.ListRequest{} MyService.Stub.list(channel, request) {:error, :not_connected} -> {:error, :unavailable} end ``` ```elixir # Use specific pool {:ok, channel} = GrpcConnectionPool.get_channel(MyApp.CustomPool) ``` -------------------------------- ### Add Dependencies Source: https://hexdocs.pm/grpc_connection_pool/GrpcConnectionPool.md Include the library and gRPC dependency in your mix.exs file. ```elixir def deps do [ {:grpc_connection_pool, "~> 0.1.0"}, {:grpc, "~> 0.10.2"} ] end ``` -------------------------------- ### Implement Custom gRPC Connection Pool Strategy Source: https://hexdocs.pm/grpc_connection_pool/readme.md Implement the `GrpcConnectionPool.Strategy` behaviour to define custom connection selection logic. The `init/2` function returns initial state, and `select/3` must return `{:ok, index}`. ```elixir defmodule MyApp.WeightedStrategy do @behaviour GrpcConnectionPool.Strategy @impl true def init(_pool_name, _pool_size) do # Return any state — stored in :persistent_term %{weights: [0.5, 0.3, 0.2]} end @impl true def select(state, channel_count, _ets_table) do # Must return {:ok, index} where 0 <= index < channel_count {:ok, weighted_random(state.weights, channel_count)} end defp weighted_random(_weights, count), do: :rand.uniform(count) - 1 end ``` -------------------------------- ### GrpcConnectionPool.Strategy Modules Source: https://hexdocs.pm/grpc_connection_pool/api-reference.md Documentation for available connection selection strategies including PowerOfTwo, Random, and RoundRobin. ```APIDOC ## GrpcConnectionPool.Strategy ### Description Defines the behaviour for connection selection strategies. ### Available Strategies - **PowerOfTwo**: Power-of-two-choices with least-recently-used tiebreak. - **Random**: Random channel selection. - **RoundRobin**: Lock-free round-robin channel selection using :atomics. ``` -------------------------------- ### Get Next Delay After Failure Source: https://hexdocs.pm/grpc_connection_pool/GrpcConnectionPool.Backoff.md Increments the backoff delay after a connection failure. Returns a tuple with the delay in milliseconds and the updated backoff state. The delay will be between the configured min and max values, with jitter applied. ```elixir state = GrpcConnectionPool.Backoff.new(min: 1000, max: 30_000) {delay, new_state} = GrpcConnectionPool.Backoff.fail(state) # delay will be between 1000 and 2000 (with jitter) ``` -------------------------------- ### Configure Pool with Keyword List Source: https://hexdocs.pm/grpc_connection_pool/index.html Create a connection pool configuration using a keyword list. This allows detailed customization of endpoint, pool, and connection settings. ```elixir # From keyword list config = GrpcConnectionPool.Config.new([ endpoint: [ type: :production, host: "api.example.com", port: 443, ssl: [] ], pool: [size: 10, name: MyApp.GrpcPool], connection: [ping_interval: 30_000] ]) ``` -------------------------------- ### Get a Connected gRPC Channel Source: https://hexdocs.pm/grpc_connection_pool/GrpcConnectionPool.Pool.md Retrieves a connected gRPC channel from the pool using the configured selection strategy. This operation has zero GenServer calls and reads directly from ETS. Returns an error if no healthy connections are available. ```elixir @spec get_channel(atom()) :: {:ok, GRPC.Channel.t()} | {:error, :not_connected} Gets a gRPC channel from the pool. Zero GenServer calls — reads directly from ETS using the configured selection strategy (default: atomics-based round-robin). ## Returns - `{:ok, channel}` — Successfully retrieved a connected channel - `{:error, :not_connected}` — No healthy connections available ## Examples case GrpcConnectionPool.Pool.get_channel() do {:ok, channel} -> MyService.Stub.call(channel, request) {:error, :not_connected} -> {:error, :unavailable} end ``` -------------------------------- ### Configure Pool from Application Environment Source: https://hexdocs.pm/grpc_connection_pool/index.html Load connection pool configuration from the application's environment file (e.g., config/config.exs). This promotes centralized configuration management. ```elixir # From application environment # config/config.exs config :my_app, GrpcConnectionPool, endpoint: [type: :production, host: "api.example.com"], pool: [size: 8] {:ok, config} = GrpcConnectionPool.Config.from_env(:my_app) ``` -------------------------------- ### Local Development Configuration Source: https://hexdocs.pm/grpc_connection_pool/readme.md Minimal configuration for local development environments without SSL. ```elixir # For local development with a gRPC server (no SSL) config :my_app, GrpcConnectionPool, endpoint: [ type: :local, host: "localhost", port: 9090 ], pool: [ size: 3, # Smaller pool for development name: MyApp.DevPool ] ``` -------------------------------- ### Run All Tests Source: https://hexdocs.pm/grpc_connection_pool/readme.md Executes all tests, including unit and integration tests. ```bash mix test ``` -------------------------------- ### Implement a Custom Strategy Source: https://hexdocs.pm/grpc_connection_pool/GrpcConnectionPool.Strategy.md Define a module implementing the GrpcConnectionPool.Strategy behaviour to provide custom channel selection logic. ```elixir defmodule MyApp.WeightedStrategy do @behaviour GrpcConnectionPool.Strategy @impl true def init(_pool_name, _pool_size), do: %{} @impl true def select(_state, channel_count, _ets_table) do # Custom selection logic {:ok, :rand.uniform(channel_count) - 1} end end ``` -------------------------------- ### Environment-Specific Configuration Source: https://hexdocs.pm/grpc_connection_pool/readme.md Dynamic configuration selection based on the current Mix environment. ```elixir # Different configurations per environment using Mix.env() case Mix.env() do :prod -> config :my_app, GrpcConnectionPool, endpoint: [ type: :production, host: "api.example.com", port: 443 ], pool: [size: 20] # Large pool for production :dev -> config :my_app, GrpcConnectionPool, endpoint: [ type: :local, host: "localhost", port: 9090 ], pool: [size: 3] # Small pool for development :test -> config :my_app, GrpcConnectionPool, endpoint: [ type: :test, host: "localhost", port: 8085 ], pool: [size: 1], # Minimal pool for tests connection: [ ping_interval: nil # No pinging needed in tests ] end ``` -------------------------------- ### Run Integration Tests Source: https://hexdocs.pm/grpc_connection_pool/readme.md Executes integration tests that require the gRPC emulator to be running. ```bash mix test --only emulator ``` -------------------------------- ### Add Dependencies Source: https://hexdocs.pm/grpc_connection_pool/index.html Add the grpc_connection_pool and grpc libraries to your project's dependencies. ```elixir def deps do [ {:grpc_connection_pool, ">~ 0.1.0"}, {:grpc, ">~ 0.10.2"} ] end ``` -------------------------------- ### Strategy Callbacks Source: https://hexdocs.pm/grpc_connection_pool/GrpcConnectionPool.Strategy.md Details the callbacks required for implementing a custom GrpcConnectionPool strategy. ```APIDOC # `state` ```elixir @type state() :: term() ``` # `init` ```elixir @callback init(pool_name :: atom(), pool_size :: pos_integer()) :: state() ``` Initialize strategy state for a pool. Called once during pool startup. The returned state is stored in `:persistent_term` and passed to `select/3` on each call. # `select` ```elixir @callback select(state(), channel_count :: pos_integer(), ets_table :: atom()) :: {:ok, non_neg_integer()} ``` Select a channel index from the pool. Must return an index in the range `0..channel_count-1`. Called on every `get_channel` invocation — must be fast. ``` -------------------------------- ### Test Environment Configuration Source: https://hexdocs.pm/grpc_connection_pool/readme.md Configuration optimized for testing, including emulator support and disabled pinging. ```elixir # For testing with Google Pub/Sub emulator or similar config :my_app, GrpcConnectionPool, endpoint: [ type: :test, host: "localhost", port: 8085, retry_config: [ max_attempts: 3, base_delay: 1000, max_delay: 5000 ] ], pool: [ size: 2, # Small pool for tests name: MyApp.TestPool ], connection: [ ping_interval: nil # Disable pinging in tests ] ``` -------------------------------- ### Implement Channel Selection Source: https://hexdocs.pm/grpc_connection_pool/GrpcConnectionPool.Strategy.md Callback for selecting a channel index, which must return a value between 0 and channel_count-1. ```elixir @callback select(state(), channel_count :: pos_integer(), ets_table :: atom()) :: {:ok, non_neg_integer()} ``` -------------------------------- ### Run Unit Tests Source: https://hexdocs.pm/grpc_connection_pool/readme.md Executes unit tests, excluding any tests tagged with 'emulator'. ```bash mix test --exclude emulator ``` -------------------------------- ### Configure Test Environment Source: https://hexdocs.pm/grpc_connection_pool/readme.md Configure minimal pool settings and disable health checks for testing against emulators. ```elixir # config/test.exs config :my_app, GrpcConnectionPool, endpoint: [ type: :test, host: "localhost", port: 8085, # Emulator port retry_config: [ max_attempts: 3, base_delay: 500, # Faster retries for tests max_delay: 2000 ] ], pool: [size: 1], # Minimal pool for tests connection: [ ping_interval: nil, # No pinging needed in tests health_check: false # Disable health checks in tests ] ``` -------------------------------- ### await_ready Source: https://hexdocs.pm/grpc_connection_pool/GrpcConnectionPool.md Blocks until at least one channel is connected or the specified timeout is reached. ```APIDOC ## await_ready ### Description Blocks until at least one channel is connected or timeout is reached. ### Parameters - **pool_name** (atom) - Optional - Pool name (default: Pool) - **timeout** (integer) - Optional - Max wait in milliseconds (default: 10_000) ### Request Example GrpcConnectionPool.await_ready(MyApp.Pool, 5_000) ### Response - **:ok** (atom) - Returned when a channel is ready. ``` -------------------------------- ### GrpcConnectionPool.PoolState Overview Source: https://hexdocs.pm/grpc_connection_pool/GrpcConnectionPool.PoolState.md Details about the ETS table structure and the purpose of the PoolState GenServer. ```APIDOC ## GrpcConnectionPool.PoolState ### Description This GenServer owns the pool's ETS table and acts as its own heir for crash resilience. If the process crashes, the table is inherited by the replacement process started by the supervisor. The ETS table stores: - `{:channel, index}` — `{channel, last_used_at}` for O(1) indexed access - `:channel_count` — number of connected channels (atomic updates) - `:pool_size` — expected pool size - `:config` — pool configuration (also stored in :persistent_term) - `:channel_slots` — maps worker PIDs to their slot indices - `:scaling_lock` — lock for scaling operations ### Child Specification Returns a specification to start this module under a supervisor. See `Supervisor`. ``` -------------------------------- ### Add grpc_connection_pool to mix.exs Source: https://hexdocs.pm/grpc_connection_pool/readme.md Add the grpc_connection_pool and its required peer dependency grpc to your project's mix.exs file. ```elixir def deps do [ {:grpc_connection_pool, "~> 0.3.0"}, {:grpc, "~> 0.11.5"} # Required peer dependency ] end ``` -------------------------------- ### Configure Pools Manually Source: https://hexdocs.pm/grpc_connection_pool/readme.md Create pool configurations programmatically without relying on the application environment. ```elixir def start(_type, _args) do # Create configurations programmatically {:ok, user_service_config} = GrpcConnectionPool.Config.production( host: "users.example.com", pool_name: MyApp.UserService.Pool, pool_size: 5 ) {:ok, payment_service_config} = GrpcConnectionPool.Config.production( host: "payments.example.com", pool_name: MyApp.PaymentService.Pool, pool_size: 3 ) children = [ {GrpcConnectionPool, user_service_config}, {GrpcConnectionPool, payment_service_config} ] Supervisor.start_link(children, strategy: :one_for_one) end ``` -------------------------------- ### Configure Custom SSL Source: https://hexdocs.pm/grpc_connection_pool/readme.md Define client certificates and CA files within the endpoint configuration for secure connections. ```elixir # For services requiring client certificates ssl_config = [ verify: :verify_peer, cacertfile: "/path/to/ca.pem", certfile: "/path/to/client.pem", keyfile: "/path/to/client-key.pem" ] {:ok, config} = GrpcConnectionPool.Config.new([ endpoint: [ type: :production, host: "secure-api.example.com", port: 443, ssl: ssl_config ], pool: [size: 5] ]) ``` -------------------------------- ### GrpcConnectionPool.Strategy.Random Source: https://hexdocs.pm/grpc_connection_pool/GrpcConnectionPool.Strategy.Random.md Documentation for the Random channel selection strategy used in gRPC connection pooling. ```APIDOC ## Random Channel Selection Strategy ### Description The `GrpcConnectionPool.Strategy.Random` module implements a random selection strategy for gRPC channels. This is particularly useful for batch jobs or correlated callers where round-robin selection might lead to hot-spotting on a single connection. ### Usage This strategy is intended to be used within the `GrpcConnectionPool` configuration to determine how channels are picked for outgoing requests. ``` -------------------------------- ### Configure Connection Pool Source: https://hexdocs.pm/grpc_connection_pool/GrpcConnectionPool.md Define pool configuration using keyword lists or application environment settings. ```elixir # From keyword list config = GrpcConnectionPool.Config.new([ endpoint: [ type: :production, host: "api.example.com", port: 443, ssl: [] ], pool: [size: 10, name: MyApp.GrpcPool], connection: [ping_interval: 30_000] ]) # From application environment # config/config.exs config :my_app, GrpcConnectionPool, endpoint: [type: :production, host: "api.example.com"], pool: [size: 8] {:ok, config} = GrpcConnectionPool.Config.from_env(:my_app) ``` -------------------------------- ### Configure a Custom Strategy Source: https://hexdocs.pm/grpc_connection_pool/GrpcConnectionPool.Strategy.md Pass the custom strategy module to the pool configuration. ```elixir config = GrpcConnectionPool.Config.new( pool: [strategy: MyApp.WeightedStrategy] ) ``` -------------------------------- ### Configure gRPC Connection Pool with Random Strategy Source: https://hexdocs.pm/grpc_connection_pool/readme.md Creates a new gRPC connection pool configuration specifying a 'random' strategy for channel selection. This is useful for distributing load evenly. ```elixir {:ok, config} = GrpcConnectionPool.Config.new( endpoint: [host: "api.example.com", port: 443], pool: [size: 10, strategy: :random] ) ``` -------------------------------- ### await_ready/2 Source: https://hexdocs.pm/grpc_connection_pool/index.html Blocks execution until at least one channel in the specified pool is connected or the timeout is reached. ```APIDOC ## await_ready(pool_name, timeout) ### Description Blocks until at least one channel is connected or timeout is reached. ### Parameters - **pool_name** (atom) - Optional - Pool name (default: Pool) - **timeout** (integer) - Optional - Max wait in milliseconds (default: 10000) ### Request Example :ok = GrpcConnectionPool.await_ready(MyApp.Pool, 5000) ``` -------------------------------- ### Define Production Configuration Source: https://hexdocs.pm/grpc_connection_pool/GrpcConnectionPool.Config.md Specifies the production configuration function signature for SSL-enabled connections. ```elixir @spec production(keyword()) :: {:ok, t()} | {:error, String.t()} ``` -------------------------------- ### Define Configuration Types Source: https://hexdocs.pm/grpc_connection_pool/GrpcConnectionPool.Config.md Type definitions for the various configuration components. ```elixir @type connection_config() :: %{ keepalive: pos_integer(), health_check: boolean(), ping_interval: pos_integer() | nil, suppress_connection_errors: boolean(), backoff_min: pos_integer(), backoff_max: pos_integer(), max_reconnect_attempts: pos_integer() } ``` ```elixir @type endpoint_config() :: %{ type: endpoint_type(), host: String.t() | nil, port: pos_integer() | nil, ssl: keyword() | boolean() | nil, credentials: GRPC.Credential.t() | nil, retry_config: retry_config() | nil, interceptors: [module()] | nil } ``` ```elixir @type endpoint_type() :: atom() ``` ```elixir @type pool_config() :: %{ size: pos_integer(), name: atom() | nil, telemetry_interval: pos_integer(), strategy: atom() } ``` ```elixir @type retry_config() :: %{ max_attempts: pos_integer(), base_delay: pos_integer(), max_delay: pos_integer() } ``` ```elixir @type t() :: %GrpcConnectionPool.Config{ connection: connection_config(), endpoint: endpoint_config(), pool: pool_config() } ``` -------------------------------- ### Configure Custom Credentials Source: https://hexdocs.pm/grpc_connection_pool/index.html Configure a connection pool to use custom credentials, such as SSL certificates for secure communication with a gRPC endpoint. ```elixir config = GrpcConnectionPool.Config.new([ endpoint: [ type: :production, host: "secure-api.example.com", port: 443, credentials: GRPC.Credential.new(ssl: [ verify: :verify_peer, cacertfile: "/path/to/ca.pem" ]) ] ]) ```