Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/rails-flag-definition-cache-provider.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"posthog-rails": minor
---

Add `config.flag_definition_cache_provider` to the `PostHog.init` block so Rails apps can share feature flag definitions across processes via an external cache (for example Redis). The generated initializer now documents the option.
10 changes: 10 additions & 0 deletions posthog-rails/examples/posthog.rb
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,16 @@
# Feature flag request timeout in seconds (default: 3)
config.feature_flag_request_timeout_seconds = 3

# Distributed flag definition cache (optional, for local evaluation)
# Share flag definitions across processes (Puma workers, Sidekiq, pods) via an
# external cache so only one process polls PostHog. Pass any object implementing
# the PostHog::FlagDefinitionCacheProvider interface. A Redis implementation is
# in the posthog-ruby repo under examples/redis_flag_cache.rb.
# config.flag_definition_cache_provider = RedisFlagCache.new(
# Redis.new(url: ENV.fetch('REDIS_URL')),
# service_key: "#{Rails.application.class.module_parent_name.underscore}-#{Rails.env}"
# )

# Error callback - called when PostHog encounters an error
# config.on_error = proc { |status, message|
# Rails.logger.error("[PostHog] Error #{status}: #{message}")
Expand Down
10 changes: 10 additions & 0 deletions posthog-rails/lib/generators/posthog/templates/posthog.rb
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,16 @@
# Feature flag request timeout in seconds (default: 3)
config.feature_flag_request_timeout_seconds = 3

# Distributed flag definition cache (optional, for local evaluation)
# Share flag definitions across processes (Puma workers, Sidekiq, pods) via an
# external cache so only one process polls PostHog. Pass any object implementing
# the PostHog::FlagDefinitionCacheProvider interface. A Redis implementation is
# in the posthog-ruby repo under examples/redis_flag_cache.rb.
# config.flag_definition_cache_provider = RedisFlagCache.new(
# Redis.new(url: ENV.fetch('REDIS_URL')),
# service_key: "#{Rails.application.class.module_parent_name.underscore}-#{Rails.env}"
# )

# Error callback - called when PostHog encounters an error
# config.on_error = proc { |status, message|
# Rails.logger.error("[PostHog] Error #{status}: #{message}")
Expand Down
10 changes: 10 additions & 0 deletions posthog-rails/lib/posthog/rails/railtie.rb
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,16 @@ def before_send=(value)
@base_options[:before_send] = value
end

# An object implementing the {PostHog::FlagDefinitionCacheProvider} interface so multiple
# Rails processes (Puma workers, Sidekiq, Kubernetes pods) can share flag definitions
# through an external cache instead of each polling PostHog independently.
#
# @param value [Object, nil]
# @return [Object, nil]
def flag_definition_cache_provider=(value)
@base_options[:flag_definition_cache_provider] = value
end

# @return [Hash] Core SDK options suitable for {PostHog::Client.new}.
def to_client_options
@base_options
Expand Down
1 change: 1 addition & 0 deletions public_api_snapshot.txt
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,7 @@ instance_method PostHog::Rails::InitConfig#before_send=(value)
instance_method PostHog::Rails::InitConfig#compress_request=(value)
instance_method PostHog::Rails::InitConfig#feature_flag_request_timeout_seconds=(value)
instance_method PostHog::Rails::InitConfig#feature_flags_polling_interval=(value)
instance_method PostHog::Rails::InitConfig#flag_definition_cache_provider=(value)
instance_method PostHog::Rails::InitConfig#host=(value)
instance_method PostHog::Rails::InitConfig#max_queue_size=(value)
instance_method PostHog::Rails::InitConfig#on_error=(value)
Expand Down
33 changes: 33 additions & 0 deletions spec/posthog/rails/railtie_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,39 @@
)
end

it 'passes a flag definition cache provider from the init block to the client' do
stub_request(:get, %r{https://us\.i\.posthog\.com/flags/definitions})
.to_return(status: 200, body: { flags: [], group_type_mapping: {}, cohorts: {} }.to_json)
provider = double(
'FlagCache',
flag_definitions: nil,
should_fetch_flag_definitions?: true,
on_flag_definitions_received: nil,
shutdown: nil
)

PostHog.init do |config|
config.api_key = 'phc_test'
config.secret_key = 'phs_test'
config.flag_definition_cache_provider = provider
config.test_mode = true
end
Comment thread
marandaneto marked this conversation as resolved.

expect(provider).to have_received(:on_flag_definitions_received).with(hash_including(:flags))
ensure
PostHog.client&.shutdown
end

it 'validates the flag definition cache provider interface' do
expect do
PostHog.init do |config|
config.api_key = 'phc_test'
config.flag_definition_cache_provider = Object.new
config.test_mode = true
end
end.to raise_error(ArgumentError, /flag_definitions/)
end

it 'uses the Rails user agent for event and feature flag requests' do
batch_request = stub_request(:post, 'https://us.i.posthog.com/batch/').to_return(status: 200, body: '{}')
flags_request = stub_request(:post, 'https://us.i.posthog.com/flags/?v=2')
Expand Down
Loading