sdk-reforge 1.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. checksums.yaml +7 -0
  2. data/.envrc.sample +3 -0
  3. data/.github/CODEOWNERS +2 -0
  4. data/.github/pull_request_template.md +8 -0
  5. data/.github/workflows/ruby.yml +48 -0
  6. data/.gitmodules +3 -0
  7. data/.rubocop.yml +13 -0
  8. data/.tool-versions +1 -0
  9. data/CHANGELOG.md +257 -0
  10. data/CODEOWNERS +1 -0
  11. data/Gemfile +29 -0
  12. data/Gemfile.lock +182 -0
  13. data/LICENSE.txt +20 -0
  14. data/README.md +105 -0
  15. data/Rakefile +63 -0
  16. data/VERSION +1 -0
  17. data/compile_protos.sh +20 -0
  18. data/dev/allocation_stats +60 -0
  19. data/dev/benchmark +40 -0
  20. data/dev/console +12 -0
  21. data/dev/script_setup.rb +18 -0
  22. data/lib/prefab_pb.rb +77 -0
  23. data/lib/reforge/caching_http_connection.rb +95 -0
  24. data/lib/reforge/client.rb +133 -0
  25. data/lib/reforge/config_client.rb +275 -0
  26. data/lib/reforge/config_client_presenter.rb +18 -0
  27. data/lib/reforge/config_loader.rb +67 -0
  28. data/lib/reforge/config_resolver.rb +84 -0
  29. data/lib/reforge/config_value_unwrapper.rb +123 -0
  30. data/lib/reforge/config_value_wrapper.rb +18 -0
  31. data/lib/reforge/context.rb +241 -0
  32. data/lib/reforge/context_shape.rb +20 -0
  33. data/lib/reforge/context_shape_aggregator.rb +70 -0
  34. data/lib/reforge/criteria_evaluator.rb +345 -0
  35. data/lib/reforge/duration.rb +58 -0
  36. data/lib/reforge/encryption.rb +65 -0
  37. data/lib/reforge/error.rb +6 -0
  38. data/lib/reforge/errors/env_var_parse_error.rb +11 -0
  39. data/lib/reforge/errors/initialization_timeout_error.rb +12 -0
  40. data/lib/reforge/errors/invalid_sdk_key_error.rb +19 -0
  41. data/lib/reforge/errors/missing_default_error.rb +13 -0
  42. data/lib/reforge/errors/missing_env_var_error.rb +11 -0
  43. data/lib/reforge/errors/uninitialized_error.rb +13 -0
  44. data/lib/reforge/evaluation.rb +53 -0
  45. data/lib/reforge/evaluation_summary_aggregator.rb +86 -0
  46. data/lib/reforge/example_contexts_aggregator.rb +77 -0
  47. data/lib/reforge/exponential_backoff.rb +21 -0
  48. data/lib/reforge/feature_flag_client.rb +43 -0
  49. data/lib/reforge/fixed_size_hash.rb +14 -0
  50. data/lib/reforge/http_connection.rb +45 -0
  51. data/lib/reforge/internal_logger.rb +43 -0
  52. data/lib/reforge/javascript_stub.rb +99 -0
  53. data/lib/reforge/local_config_parser.rb +151 -0
  54. data/lib/reforge/murmer3.rb +50 -0
  55. data/lib/reforge/options.rb +191 -0
  56. data/lib/reforge/periodic_sync.rb +74 -0
  57. data/lib/reforge/prefab.rb +120 -0
  58. data/lib/reforge/rate_limit_cache.rb +41 -0
  59. data/lib/reforge/resolved_config_presenter.rb +86 -0
  60. data/lib/reforge/semver.rb +132 -0
  61. data/lib/reforge/sse_config_client.rb +112 -0
  62. data/lib/reforge/time_helpers.rb +7 -0
  63. data/lib/reforge/weighted_value_resolver.rb +42 -0
  64. data/lib/reforge/yaml_config_parser.rb +34 -0
  65. data/lib/reforge-sdk.rb +57 -0
  66. data/test/fixtures/datafile.json +87 -0
  67. data/test/integration_test.rb +171 -0
  68. data/test/integration_test_helpers.rb +114 -0
  69. data/test/support/common_helpers.rb +201 -0
  70. data/test/support/mock_base_client.rb +41 -0
  71. data/test/support/mock_config_client.rb +19 -0
  72. data/test/support/mock_config_loader.rb +1 -0
  73. data/test/test_caching_http_connection.rb +218 -0
  74. data/test/test_client.rb +351 -0
  75. data/test/test_config_client.rb +84 -0
  76. data/test/test_config_loader.rb +82 -0
  77. data/test/test_config_resolver.rb +502 -0
  78. data/test/test_config_value_unwrapper.rb +270 -0
  79. data/test/test_config_value_wrapper.rb +42 -0
  80. data/test/test_context.rb +271 -0
  81. data/test/test_context_shape.rb +50 -0
  82. data/test/test_context_shape_aggregator.rb +150 -0
  83. data/test/test_criteria_evaluator.rb +1180 -0
  84. data/test/test_duration.rb +37 -0
  85. data/test/test_encryption.rb +16 -0
  86. data/test/test_evaluation_summary_aggregator.rb +162 -0
  87. data/test/test_example_contexts_aggregator.rb +233 -0
  88. data/test/test_exponential_backoff.rb +18 -0
  89. data/test/test_feature_flag_client.rb +16 -0
  90. data/test/test_fixed_size_hash.rb +119 -0
  91. data/test/test_helper.rb +17 -0
  92. data/test/test_integration.rb +75 -0
  93. data/test/test_internal_logger.rb +25 -0
  94. data/test/test_javascript_stub.rb +176 -0
  95. data/test/test_local_config_parser.rb +147 -0
  96. data/test/test_logger_initialization.rb +12 -0
  97. data/test/test_options.rb +93 -0
  98. data/test/test_prefab.rb +16 -0
  99. data/test/test_rate_limit_cache.rb +44 -0
  100. data/test/test_semver.rb +108 -0
  101. data/test/test_sse_config_client.rb +211 -0
  102. data/test/test_weighted_value_resolver.rb +71 -0
  103. metadata +345 -0
data/Rakefile ADDED
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ warn e.message
9
+ warn 'Run `bundle install` to install missing gems'
10
+ exit e.status_code
11
+ end
12
+
13
+ require 'rake'
14
+
15
+ require 'rake/testtask'
16
+ Rake::TestTask.new(:test) do |test|
17
+ test.libs << 'lib' << 'test'
18
+ test.pattern = 'test/**/test_*.rb'
19
+ test.verbose = true
20
+ end
21
+
22
+ task default: :test
23
+
24
+ unless ENV['CI']
25
+ require 'juwelier'
26
+ Juwelier::Tasks.new do |gem|
27
+ # gem is a Gem::Specification... see http://guides.rubygems.org/specification-reference/ for more options
28
+ gem.name = 'sdk-reforge'
29
+ gem.homepage = 'http://github.com/ReforgeHQ/sdk-ruby'
30
+ gem.license = 'MIT'
31
+ gem.summary = %(Reforge Launch Ruby Infrastructure)
32
+ gem.description = %(Feature Flags, Live Config as a service)
33
+ gem.email = 'jeff.dwyer@reforge.com.cloud'
34
+ gem.authors = ['Jeff Dwyer']
35
+
36
+ # dependencies defined in Gemfile
37
+ end
38
+ Juwelier::RubygemsDotOrgTasks.new
39
+
40
+ desc 'Code coverage detail'
41
+ task :simplecov do
42
+ ENV['COVERAGE'] = 'true'
43
+ Rake::Task['test'].execute
44
+ end
45
+
46
+ require 'rdoc/task'
47
+ Rake::RDocTask.new do |rdoc|
48
+ version = File.exist?('VERSION') ? File.read('VERSION') : ''
49
+
50
+ rdoc.rdoc_dir = 'rdoc'
51
+ rdoc.title = "sdk-reforge #{version}"
52
+ rdoc.rdoc_files.include('README*')
53
+ rdoc.rdoc_files.include('lib/**/*.rb')
54
+ end
55
+ end
56
+
57
+ # Add release task for CI
58
+ task :release do
59
+ sh 'gem build sdk-reforge.gemspec'
60
+ version = File.read('VERSION').strip
61
+ gem_file = "sdk-reforge-#{version}.gem"
62
+ sh "gem push #{gem_file}"
63
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 1.9.0
data/compile_protos.sh ADDED
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env bash
2
+
3
+ set -e
4
+
5
+ PROTO_ROOT="${PROTO_ROOT:-..}"
6
+
7
+ gem install grpc-tools
8
+
9
+ (
10
+ cd "$PROTO_ROOT/prefab-cloud"
11
+ git pull --rebase
12
+ )
13
+
14
+ grpc_tools_ruby_protoc -I "$PROTO_ROOT/prefab-cloud/" --ruby_out=lib --grpc_out=lib prefab.proto
15
+
16
+ gsed -i 's/^module Prefab$/module PrefabProto/g' lib/prefab_pb.rb
17
+
18
+ # on M1 you need to
19
+ # 1. run in rosetta
20
+ # 2. mv gems/2.6.0/gems/grpc-tools-1.43.1/bin/x86_64-macos x86-macos
@@ -0,0 +1,60 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'bundler/setup'
5
+
6
+ gemspec = Dir.glob(File.expand_path("../../*.gemspec", __FILE__)).first
7
+ spec = Gem::Specification.load(gemspec)
8
+
9
+ # Add the require paths to the $LOAD_PATH
10
+ spec.require_paths.each do |path|
11
+ full_path = File.expand_path("../" + path, __dir__)
12
+ $LOAD_PATH.unshift(full_path) unless $LOAD_PATH.include?(full_path)
13
+ end
14
+
15
+ spec.require_paths.each do |path|
16
+ require "./lib/reforge-sdk"
17
+ end
18
+
19
+ require 'reforge-sdk'
20
+
21
+ $prefab = Reforge::Client.new(collect_logger_counts: false, collect_evaluation_summaries: false,
22
+ context_upload_mode: :none)
23
+ $prefab.get('a.live.integer')
24
+
25
+ puts '-' * 80
26
+
27
+ require 'allocation_stats'
28
+
29
+ $runs = 100
30
+
31
+ def measure(description)
32
+ puts "Measuring #{description}..."
33
+ stats = $prefab.with_context(user: { email_suffix: 'yahoo.com' }) do
34
+ AllocationStats.trace do
35
+ $runs.times do
36
+ yield
37
+ end
38
+ end
39
+ end
40
+
41
+ allocations = stats.allocations(alias_paths: true).group_by(:sourcefile, :sourceline, :class)
42
+
43
+ if ENV['TOP']
44
+ puts allocations.sort_by_size.to_text.split("\n").first(20)
45
+ end
46
+
47
+ puts "Total allocations: #{allocations.all.values.map(&:size).sum}"
48
+ puts "Total memory: #{allocations.all.values.flatten.map(&:memsize).sum}"
49
+ puts stats.gc_profiler_report
50
+ end
51
+
52
+ measure "no-JIT context (#{$runs} runs)" do
53
+ $prefab.get('a.live.integer')
54
+ end
55
+
56
+ puts "\n\n"
57
+
58
+ measure "with JIT context (#{$runs} runs)" do
59
+ $prefab.get('a.live.integer', { a: { b: "c" } })
60
+ end
data/dev/benchmark ADDED
@@ -0,0 +1,40 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'bundler/setup'
5
+
6
+ gemspec = Dir.glob(File.expand_path("../../*.gemspec", __FILE__)).first
7
+ spec = Gem::Specification.load(gemspec)
8
+
9
+ # Add the require paths to the $LOAD_PATH
10
+ spec.require_paths.each do |path|
11
+ full_path = File.expand_path("../" + path, __dir__)
12
+ $LOAD_PATH.unshift(full_path) unless $LOAD_PATH.include?(full_path)
13
+ end
14
+
15
+ spec.require_paths.each do |path|
16
+ require "./lib/reforge-sdk"
17
+ end
18
+
19
+ require 'reforge-sdk'
20
+ require 'benchmark/ips'
21
+
22
+ prefab = Reforge::Client.new(collect_logger_counts: false, collect_evaluation_summaries: false,
23
+ context_upload_mode: :none)
24
+
25
+ prefab.get('prefab.auth.allowed_origins')
26
+
27
+ prefab.with_context(user: { email_suffix: 'yahoo.com' }) do
28
+ Benchmark.ips do |x|
29
+ x.report("noop") do
30
+ end
31
+
32
+ x.report('prefab.get') do
33
+ prefab.get('prefab.auth.allowed_origins')
34
+ end
35
+
36
+ x.report('prefab.get with jit context') do
37
+ prefab.get('prefab.auth.allowed_origins', { a: { b: "c" } })
38
+ end
39
+ end
40
+ end
data/dev/console ADDED
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env bundle exec ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'irb'
5
+ require_relative "./script_setup"
6
+
7
+ if !ENV['REFORGE_LOG_CLIENT_BOOTSTRAP_LOG_LEVEL']
8
+ puts "run with REFORGE_LOG_CLIENT_BOOTSTRAP_LOG_LEVEL=debug (or trace) for more output"
9
+ end
10
+
11
+ # Start an IRB session
12
+ IRB.start(__FILE__)
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/setup'
4
+
5
+ gemspec = Dir.glob(File.expand_path("../../*.gemspec", __FILE__)).first
6
+ spec = Gem::Specification.load(gemspec)
7
+
8
+ # Add the require paths to the $LOAD_PATH
9
+ spec.require_paths.each do |path|
10
+ full_path = File.expand_path("../" + path, __dir__)
11
+ $LOAD_PATH.unshift(full_path) unless $LOAD_PATH.include?(full_path)
12
+ end
13
+
14
+ spec.require_paths.each do |path|
15
+ require "./lib/reforge-sdk"
16
+ end
17
+
18
+ SemanticLogger.add_appender(io: $stdout)
data/lib/prefab_pb.rb ADDED
@@ -0,0 +1,77 @@
1
+ # frozen_string_literal: true
2
+ # Generated by the protocol buffer compiler. DO NOT EDIT!
3
+ # source: prefab.proto
4
+
5
+ require 'google/protobuf'
6
+
7
+
8
+ descriptor_data = "\n\x0cprefab.proto\x12\x06prefab\"W\n\x14\x43onfigServicePointer\x12\x12\n\nproject_id\x18\x01 \x01(\x03\x12\x13\n\x0bstart_at_id\x18\x02 \x01(\x03\x12\x16\n\x0eproject_env_id\x18\x03 \x01(\x03\"\xf7\x04\n\x0b\x43onfigValue\x12\r\n\x03int\x18\x01 \x01(\x03H\x00\x12\x10\n\x06string\x18\x02 \x01(\tH\x00\x12\x0f\n\x05\x62ytes\x18\x03 \x01(\x0cH\x00\x12\x10\n\x06\x64ouble\x18\x04 \x01(\x01H\x00\x12\x0e\n\x04\x62ool\x18\x05 \x01(\x08H\x00\x12\x31\n\x0fweighted_values\x18\x06 \x01(\x0b\x32\x16.prefab.WeightedValuesH\x00\x12\x33\n\x10limit_definition\x18\x07 \x01(\x0b\x32\x17.prefab.LimitDefinitionH\x00\x12%\n\tlog_level\x18\t \x01(\x0e\x32\x10.prefab.LogLevelH\x00\x12)\n\x0bstring_list\x18\n \x01(\x0b\x32\x12.prefab.StringListH\x00\x12%\n\tint_range\x18\x0b \x01(\x0b\x32\x10.prefab.IntRangeH\x00\x12$\n\x08provided\x18\x0c \x01(\x0b\x32\x10.prefab.ProvidedH\x00\x12\'\n\x08\x64uration\x18\x0f \x01(\x0b\x32\x13.prefab.IsoDurationH\x00\x12\x1c\n\x04json\x18\x10 \x01(\x0b\x32\x0c.prefab.JsonH\x00\x12 \n\x06schema\x18\x11 \x01(\x0b\x32\x0e.prefab.SchemaH\x00\x12\x19\n\x0c\x63onfidential\x18\r \x01(\x08H\x01\x88\x01\x01\x12\x19\n\x0c\x64\x65\x63rypt_with\x18\x0e \x01(\tH\x02\x88\x01\x01\x12\x11\n\x04name\x18\x12 \x01(\tH\x03\x88\x01\x01\x12\x18\n\x0b\x64\x65scription\x18\x13 \x01(\tH\x04\x88\x01\x01\x42\x06\n\x04typeB\x0f\n\r_confidentialB\x0f\n\r_decrypt_withB\x07\n\x05_nameB\x0e\n\x0c_description\"\x14\n\x04Json\x12\x0c\n\x04json\x18\x01 \x01(\t\"!\n\x0bIsoDuration\x12\x12\n\ndefinition\x18\x01 \x01(\t\"b\n\x08Provided\x12+\n\x06source\x18\x01 \x01(\x0e\x32\x16.prefab.ProvidedSourceH\x00\x88\x01\x01\x12\x13\n\x06lookup\x18\x02 \x01(\tH\x01\x88\x01\x01\x42\t\n\x07_sourceB\t\n\x07_lookup\"B\n\x08IntRange\x12\x12\n\x05start\x18\x01 \x01(\x03H\x00\x88\x01\x01\x12\x10\n\x03\x65nd\x18\x02 \x01(\x03H\x01\x88\x01\x01\x42\x08\n\x06_startB\x06\n\x04_end\"\x1c\n\nStringList\x12\x0e\n\x06values\x18\x01 \x03(\t\"C\n\rWeightedValue\x12\x0e\n\x06weight\x18\x01 \x01(\x05\x12\"\n\x05value\x18\x02 \x01(\x0b\x32\x13.prefab.ConfigValue\"~\n\x0eWeightedValues\x12.\n\x0fweighted_values\x18\x01 \x03(\x0b\x32\x15.prefab.WeightedValue\x12\"\n\x15hash_by_property_name\x18\x02 \x01(\tH\x00\x88\x01\x01\x42\x18\n\x16_hash_by_property_name\"X\n\x0e\x41piKeyMetadata\x12\x13\n\x06key_id\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x14\n\x07user_id\x18\x03 \x01(\tH\x01\x88\x01\x01\x42\t\n\x07_key_idB\n\n\x08_user_idJ\x04\x08\x02\x10\x03\"\xa0\x02\n\x07\x43onfigs\x12\x1f\n\x07\x63onfigs\x18\x01 \x03(\x0b\x32\x0e.prefab.Config\x12<\n\x16\x63onfig_service_pointer\x18\x02 \x01(\x0b\x32\x1c.prefab.ConfigServicePointer\x12\x34\n\x0f\x61pikey_metadata\x18\x03 \x01(\x0b\x32\x16.prefab.ApiKeyMetadataH\x00\x88\x01\x01\x12\x30\n\x0f\x64\x65\x66\x61ult_context\x18\x04 \x01(\x0b\x32\x12.prefab.ContextSetH\x01\x88\x01\x01\x12\x17\n\nkeep_alive\x18\x05 \x01(\x08H\x02\x88\x01\x01\x42\x12\n\x10_apikey_metadataB\x12\n\x10_default_contextB\r\n\x0b_keep_alive\"\xa4\x04\n\x06\x43onfig\x12\n\n\x02id\x18\x01 \x01(\x03\x12\x12\n\nproject_id\x18\x02 \x01(\x03\x12\x0b\n\x03key\x18\x03 \x01(\t\x12%\n\nchanged_by\x18\x04 \x01(\x0b\x32\x11.prefab.ChangedBy\x12\x1f\n\x04rows\x18\x05 \x03(\x0b\x32\x11.prefab.ConfigRow\x12-\n\x10\x61llowable_values\x18\x06 \x03(\x0b\x32\x13.prefab.ConfigValue\x12\'\n\x0b\x63onfig_type\x18\x07 \x01(\x0e\x32\x12.prefab.ConfigType\x12\x15\n\x08\x64raft_id\x18\x08 \x01(\x03H\x00\x88\x01\x01\x12,\n\nvalue_type\x18\t \x01(\x0e\x32\x18.prefab.Config.ValueType\x12\x1a\n\x12send_to_client_sdk\x18\n \x01(\x08\x12\x17\n\nschema_key\x18\x0b \x01(\tH\x01\x88\x01\x01\"\xb6\x01\n\tValueType\x12\x16\n\x12NOT_SET_VALUE_TYPE\x10\x00\x12\x07\n\x03INT\x10\x01\x12\n\n\x06STRING\x10\x02\x12\t\n\x05\x42YTES\x10\x03\x12\n\n\x06\x44OUBLE\x10\x04\x12\x08\n\x04\x42OOL\x10\x05\x12\x14\n\x10LIMIT_DEFINITION\x10\x07\x12\r\n\tLOG_LEVEL\x10\t\x12\x0f\n\x0bSTRING_LIST\x10\n\x12\r\n\tINT_RANGE\x10\x0b\x12\x0c\n\x08\x44URATION\x10\x0c\x12\x08\n\x04JSON\x10\rB\x0b\n\t_draft_idB\r\n\x0b_schema_key\"V\n\tChangedBy\x12\x0f\n\x07user_id\x18\x01 \x01(\x03\x12\r\n\x05\x65mail\x18\x02 \x01(\t\x12\x12\n\napi_key_id\x18\x03 \x01(\t\x12\x15\n\ruser_identity\x18\x04 \x01(\t\"\xe4\x01\n\tConfigRow\x12\x1b\n\x0eproject_env_id\x18\x01 \x01(\x03H\x00\x88\x01\x01\x12(\n\x06values\x18\x02 \x03(\x0b\x32\x18.prefab.ConditionalValue\x12\x35\n\nproperties\x18\x03 \x03(\x0b\x32!.prefab.ConfigRow.PropertiesEntry\x1a\x46\n\x0fPropertiesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\"\n\x05value\x18\x02 \x01(\x0b\x32\x13.prefab.ConfigValue:\x02\x38\x01\x42\x11\n\x0f_project_env_id\"[\n\x10\x43onditionalValue\x12#\n\x08\x63riteria\x18\x01 \x03(\x0b\x32\x11.prefab.Criterion\x12\"\n\x05value\x18\x02 \x01(\x0b\x32\x13.prefab.ConfigValue\"\x96\x06\n\tCriterion\x12\x15\n\rproperty_name\x18\x01 \x01(\t\x12\x35\n\x08operator\x18\x02 \x01(\x0e\x32#.prefab.Criterion.CriterionOperator\x12+\n\x0evalue_to_match\x18\x03 \x01(\x0b\x32\x13.prefab.ConfigValue\"\x8d\x05\n\x11\x43riterionOperator\x12\x0b\n\x07NOT_SET\x10\x00\x12\x11\n\rLOOKUP_KEY_IN\x10\x01\x12\x15\n\x11LOOKUP_KEY_NOT_IN\x10\x02\x12\n\n\x06IN_SEG\x10\x03\x12\x0e\n\nNOT_IN_SEG\x10\x04\x12\x0f\n\x0b\x41LWAYS_TRUE\x10\x05\x12\x12\n\x0ePROP_IS_ONE_OF\x10\x06\x12\x16\n\x12PROP_IS_NOT_ONE_OF\x10\x07\x12\x19\n\x15PROP_ENDS_WITH_ONE_OF\x10\x08\x12!\n\x1dPROP_DOES_NOT_END_WITH_ONE_OF\x10\t\x12\x16\n\x12HIERARCHICAL_MATCH\x10\n\x12\x10\n\x0cIN_INT_RANGE\x10\x0b\x12\x1b\n\x17PROP_STARTS_WITH_ONE_OF\x10\x0c\x12#\n\x1fPROP_DOES_NOT_START_WITH_ONE_OF\x10\r\x12\x18\n\x14PROP_CONTAINS_ONE_OF\x10\x0e\x12 \n\x1cPROP_DOES_NOT_CONTAIN_ONE_OF\x10\x0f\x12\x12\n\x0ePROP_LESS_THAN\x10\x10\x12\x1b\n\x17PROP_LESS_THAN_OR_EQUAL\x10\x11\x12\x15\n\x11PROP_GREATER_THAN\x10\x12\x12\x1e\n\x1aPROP_GREATER_THAN_OR_EQUAL\x10\x13\x12\x0f\n\x0bPROP_BEFORE\x10\x14\x12\x0e\n\nPROP_AFTER\x10\x15\x12\x10\n\x0cPROP_MATCHES\x10\x16\x12\x17\n\x13PROP_DOES_NOT_MATCH\x10\x17\x12\x19\n\x15PROP_SEMVER_LESS_THAN\x10\x18\x12\x15\n\x11PROP_SEMVER_EQUAL\x10\x19\x12\x1c\n\x18PROP_SEMVER_GREATER_THAN\x10\x1a\"\x89\x01\n\x07Loggers\x12\x1f\n\x07loggers\x18\x01 \x03(\x0b\x32\x0e.prefab.Logger\x12\x10\n\x08start_at\x18\x02 \x01(\x03\x12\x0e\n\x06\x65nd_at\x18\x03 \x01(\x03\x12\x15\n\rinstance_hash\x18\x04 \x01(\t\x12\x16\n\tnamespace\x18\x05 \x01(\tH\x00\x88\x01\x01\x42\x0c\n\n_namespace\"\xd9\x01\n\x06Logger\x12\x13\n\x0blogger_name\x18\x01 \x01(\t\x12\x13\n\x06traces\x18\x02 \x01(\x03H\x00\x88\x01\x01\x12\x13\n\x06\x64\x65\x62ugs\x18\x03 \x01(\x03H\x01\x88\x01\x01\x12\x12\n\x05infos\x18\x04 \x01(\x03H\x02\x88\x01\x01\x12\x12\n\x05warns\x18\x05 \x01(\x03H\x03\x88\x01\x01\x12\x13\n\x06\x65rrors\x18\x06 \x01(\x03H\x04\x88\x01\x01\x12\x13\n\x06\x66\x61tals\x18\x07 \x01(\x03H\x05\x88\x01\x01\x42\t\n\x07_tracesB\t\n\x07_debugsB\x08\n\x06_infosB\x08\n\x06_warnsB\t\n\x07_errorsB\t\n\x07_fatals\"\x16\n\x14LoggerReportResponse\"\xdb\x03\n\rLimitResponse\x12\x0e\n\x06passed\x18\x01 \x01(\x08\x12\x12\n\nexpires_at\x18\x02 \x01(\x03\x12\x16\n\x0e\x65nforced_group\x18\x03 \x01(\t\x12\x16\n\x0e\x63urrent_bucket\x18\x04 \x01(\x03\x12\x14\n\x0cpolicy_group\x18\x05 \x01(\t\x12;\n\x0bpolicy_name\x18\x06 \x01(\x0e\x32&.prefab.LimitResponse.LimitPolicyNames\x12\x14\n\x0cpolicy_limit\x18\x07 \x01(\x05\x12\x0e\n\x06\x61mount\x18\x08 \x01(\x03\x12\x16\n\x0elimit_reset_at\x18\t \x01(\x03\x12\x39\n\x0csafety_level\x18\n \x01(\x0e\x32#.prefab.LimitDefinition.SafetyLevel\"\xa9\x01\n\x10LimitPolicyNames\x12\x0b\n\x07NOT_SET\x10\x00\x12\x14\n\x10SECONDLY_ROLLING\x10\x01\x12\x14\n\x10MINUTELY_ROLLING\x10\x03\x12\x12\n\x0eHOURLY_ROLLING\x10\x05\x12\x11\n\rDAILY_ROLLING\x10\x07\x12\x13\n\x0fMONTHLY_ROLLING\x10\x08\x12\x0c\n\x08INFINITE\x10\t\x12\x12\n\x0eYEARLY_ROLLING\x10\n\"\x99\x02\n\x0cLimitRequest\x12\x12\n\naccount_id\x18\x01 \x01(\x03\x12\x16\n\x0e\x61\x63quire_amount\x18\x02 \x01(\x05\x12\x0e\n\x06groups\x18\x03 \x03(\t\x12:\n\x0elimit_combiner\x18\x04 \x01(\x0e\x32\".prefab.LimitRequest.LimitCombiner\x12\x1e\n\x16\x61llow_partial_response\x18\x05 \x01(\x08\x12\x39\n\x0csafety_level\x18\x06 \x01(\x0e\x32#.prefab.LimitDefinition.SafetyLevel\"6\n\rLimitCombiner\x12\x0b\n\x07NOT_SET\x10\x00\x12\x0b\n\x07MINIMUM\x10\x01\x12\x0b\n\x07MAXIMUM\x10\x02\"/\n\nContextSet\x12!\n\x08\x63ontexts\x18\x01 \x03(\x0b\x32\x0f.prefab.Context\"\x96\x01\n\x07\x43ontext\x12\x11\n\x04type\x18\x01 \x01(\tH\x00\x88\x01\x01\x12+\n\x06values\x18\x02 \x03(\x0b\x32\x1b.prefab.Context.ValuesEntry\x1a\x42\n\x0bValuesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\"\n\x05value\x18\x02 \x01(\x0b\x32\x13.prefab.ConfigValue:\x02\x38\x01\x42\x07\n\x05_type\"\x93\x01\n\x08Identity\x12\x13\n\x06lookup\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x34\n\nattributes\x18\x02 \x03(\x0b\x32 .prefab.Identity.AttributesEntry\x1a\x31\n\x0f\x41ttributesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\t\n\x07_lookup\"\xd6\x02\n\x18\x43onfigEvaluationMetaData\x12\x1d\n\x10\x63onfig_row_index\x18\x01 \x01(\x03H\x00\x88\x01\x01\x12$\n\x17\x63onditional_value_index\x18\x02 \x01(\x03H\x01\x88\x01\x01\x12!\n\x14weighted_value_index\x18\x03 \x01(\x03H\x02\x88\x01\x01\x12%\n\x04type\x18\x04 \x01(\x0e\x32\x12.prefab.ConfigTypeH\x03\x88\x01\x01\x12\x0f\n\x02id\x18\x05 \x01(\x03H\x04\x88\x01\x01\x12\x31\n\nvalue_type\x18\x06 \x01(\x0e\x32\x18.prefab.Config.ValueTypeH\x05\x88\x01\x01\x42\x13\n\x11_config_row_indexB\x1a\n\x18_conditional_value_indexB\x17\n\x15_weighted_value_indexB\x07\n\x05_typeB\x05\n\x03_idB\r\n\x0b_value_type\"\x8b\x03\n\x11\x43lientConfigValue\x12\r\n\x03int\x18\x01 \x01(\x03H\x00\x12\x10\n\x06string\x18\x02 \x01(\tH\x00\x12\x10\n\x06\x64ouble\x18\x03 \x01(\x01H\x00\x12\x0e\n\x04\x62ool\x18\x04 \x01(\x08H\x00\x12%\n\tlog_level\x18\x05 \x01(\x0e\x32\x10.prefab.LogLevelH\x00\x12)\n\x0bstring_list\x18\x07 \x01(\x0b\x32\x12.prefab.StringListH\x00\x12%\n\tint_range\x18\x08 \x01(\x0b\x32\x10.prefab.IntRangeH\x00\x12*\n\x08\x64uration\x18\t \x01(\x0b\x32\x16.prefab.ClientDurationH\x00\x12\x1c\n\x04json\x18\n \x01(\x0b\x32\x0c.prefab.JsonH\x00\x12I\n\x1a\x63onfig_evaluation_metadata\x18\x06 \x01(\x0b\x32 .prefab.ConfigEvaluationMetaDataH\x01\x88\x01\x01\x42\x06\n\x04typeB\x1d\n\x1b_config_evaluation_metadata\"D\n\x0e\x43lientDuration\x12\x0f\n\x07seconds\x18\x01 \x01(\x03\x12\r\n\x05nanos\x18\x02 \x01(\x05\x12\x12\n\ndefinition\x18\x03 \x01(\t\"\xa4\x02\n\x11\x43onfigEvaluations\x12\x35\n\x06values\x18\x01 \x03(\x0b\x32%.prefab.ConfigEvaluations.ValuesEntry\x12\x34\n\x0f\x61pikey_metadata\x18\x02 \x01(\x0b\x32\x16.prefab.ApiKeyMetadataH\x00\x88\x01\x01\x12\x30\n\x0f\x64\x65\x66\x61ult_context\x18\x03 \x01(\x0b\x32\x12.prefab.ContextSetH\x01\x88\x01\x01\x1aH\n\x0bValuesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12(\n\x05value\x18\x02 \x01(\x0b\x32\x19.prefab.ClientConfigValue:\x02\x38\x01\x42\x12\n\x10_apikey_metadataB\x12\n\x10_default_context\"\xa8\x02\n\x0fLimitDefinition\x12;\n\x0bpolicy_name\x18\x02 \x01(\x0e\x32&.prefab.LimitResponse.LimitPolicyNames\x12\r\n\x05limit\x18\x03 \x01(\x05\x12\r\n\x05\x62urst\x18\x04 \x01(\x05\x12\x12\n\naccount_id\x18\x05 \x01(\x03\x12\x15\n\rlast_modified\x18\x06 \x01(\x03\x12\x12\n\nreturnable\x18\x07 \x01(\x08\x12\x39\n\x0csafety_level\x18\x08 \x01(\x0e\x32#.prefab.LimitDefinition.SafetyLevel\"@\n\x0bSafetyLevel\x12\x0b\n\x07NOT_SET\x10\x00\x12\x12\n\x0eL4_BEST_EFFORT\x10\x04\x12\x10\n\x0cL5_BOMBPROOF\x10\x05\"@\n\x10LimitDefinitions\x12,\n\x0b\x64\x65\x66initions\x18\x01 \x03(\x0b\x32\x17.prefab.LimitDefinition\"\x8a\x01\n\x0f\x42ufferedRequest\x12\x12\n\naccount_id\x18\x01 \x01(\x03\x12\x0e\n\x06method\x18\x02 \x01(\t\x12\x0b\n\x03uri\x18\x03 \x01(\t\x12\x0c\n\x04\x62ody\x18\x04 \x01(\t\x12\x14\n\x0climit_groups\x18\x05 \x03(\t\x12\x14\n\x0c\x63ontent_type\x18\x06 \x01(\t\x12\x0c\n\x04\x66ifo\x18\x07 \x01(\x08\"\x94\x01\n\x0c\x42\x61tchRequest\x12\x12\n\naccount_id\x18\x01 \x01(\x03\x12\x0e\n\x06method\x18\x02 \x01(\t\x12\x0b\n\x03uri\x18\x03 \x01(\t\x12\x0c\n\x04\x62ody\x18\x04 \x01(\t\x12\x14\n\x0climit_groups\x18\x05 \x03(\t\x12\x16\n\x0e\x62\x61tch_template\x18\x06 \x01(\t\x12\x17\n\x0f\x62\x61tch_separator\x18\x07 \x01(\t\" \n\rBasicResponse\x12\x0f\n\x07message\x18\x01 \x01(\t\"3\n\x10\x43reationResponse\x12\x0f\n\x07message\x18\x01 \x01(\t\x12\x0e\n\x06new_id\x18\x02 \x01(\x03\"h\n\x07IdBlock\x12\x12\n\nproject_id\x18\x01 \x01(\x03\x12\x16\n\x0eproject_env_id\x18\x02 \x01(\x03\x12\x15\n\rsequence_name\x18\x03 \x01(\t\x12\r\n\x05start\x18\x04 \x01(\x03\x12\x0b\n\x03\x65nd\x18\x05 \x01(\x03\"a\n\x0eIdBlockRequest\x12\x12\n\nproject_id\x18\x01 \x01(\x03\x12\x16\n\x0eproject_env_id\x18\x02 \x01(\x03\x12\x15\n\rsequence_name\x18\x03 \x01(\t\x12\x0c\n\x04size\x18\x04 \x01(\x03\"\x8a\x01\n\x0c\x43ontextShape\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x39\n\x0b\x66ield_types\x18\x02 \x03(\x0b\x32$.prefab.ContextShape.FieldTypesEntry\x1a\x31\n\x0f\x46ieldTypesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x05:\x02\x38\x01\"[\n\rContextShapes\x12$\n\x06shapes\x18\x01 \x03(\x0b\x32\x14.prefab.ContextShape\x12\x16\n\tnamespace\x18\x02 \x01(\tH\x00\x88\x01\x01\x42\x0c\n\n_namespace\"C\n\rEvaluatedKeys\x12\x0c\n\x04keys\x18\x01 \x03(\t\x12\x16\n\tnamespace\x18\x02 \x01(\tH\x00\x88\x01\x01\x42\x0c\n\n_namespace\"\x93\x01\n\x0f\x45valuatedConfig\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x16\n\x0e\x63onfig_version\x18\x02 \x01(\x03\x12#\n\x06result\x18\x03 \x01(\x0b\x32\x13.prefab.ConfigValue\x12#\n\x07\x63ontext\x18\x04 \x01(\x0b\x32\x12.prefab.ContextSet\x12\x11\n\ttimestamp\x18\x05 \x01(\x03\"<\n\x10\x45valuatedConfigs\x12(\n\x07\x63onfigs\x18\x01 \x03(\x0b\x32\x17.prefab.EvaluatedConfig\"\xc4\x03\n\x17\x43onfigEvaluationCounter\x12\r\n\x05\x63ount\x18\x01 \x01(\x03\x12\x16\n\tconfig_id\x18\x02 \x01(\x03H\x00\x88\x01\x01\x12\x1b\n\x0eselected_index\x18\x03 \x01(\rH\x01\x88\x01\x01\x12\x30\n\x0eselected_value\x18\x04 \x01(\x0b\x32\x13.prefab.ConfigValueH\x02\x88\x01\x01\x12\x1d\n\x10\x63onfig_row_index\x18\x05 \x01(\rH\x03\x88\x01\x01\x12$\n\x17\x63onditional_value_index\x18\x06 \x01(\rH\x04\x88\x01\x01\x12!\n\x14weighted_value_index\x18\x07 \x01(\rH\x05\x88\x01\x01\x12\x36\n\x06reason\x18\x08 \x01(\x0e\x32&.prefab.ConfigEvaluationCounter.Reason\"\x15\n\x06Reason\x12\x0b\n\x07UNKNOWN\x10\x00\x42\x0c\n\n_config_idB\x11\n\x0f_selected_indexB\x11\n\x0f_selected_valueB\x13\n\x11_config_row_indexB\x1a\n\x18_conditional_value_indexB\x17\n\x15_weighted_value_index\"{\n\x17\x43onfigEvaluationSummary\x12\x0b\n\x03key\x18\x01 \x01(\t\x12 \n\x04type\x18\x02 \x01(\x0e\x32\x12.prefab.ConfigType\x12\x31\n\x08\x63ounters\x18\x03 \x03(\x0b\x32\x1f.prefab.ConfigEvaluationCounter\"k\n\x19\x43onfigEvaluationSummaries\x12\r\n\x05start\x18\x01 \x01(\x03\x12\x0b\n\x03\x65nd\x18\x02 \x01(\x03\x12\x32\n\tsummaries\x18\x03 \x03(\x0b\x32\x1f.prefab.ConfigEvaluationSummary\"Z\n\x15LoggersTelemetryEvent\x12\x1f\n\x07loggers\x18\x01 \x03(\x0b\x32\x0e.prefab.Logger\x12\x10\n\x08start_at\x18\x02 \x01(\x03\x12\x0e\n\x06\x65nd_at\x18\x03 \x01(\x03\"\x98\x02\n\x0eTelemetryEvent\x12\x36\n\tsummaries\x18\x02 \x01(\x0b\x32!.prefab.ConfigEvaluationSummariesH\x00\x12\x33\n\x10\x65xample_contexts\x18\x03 \x01(\x0b\x32\x17.prefab.ExampleContextsH\x00\x12+\n\x0c\x63lient_stats\x18\x04 \x01(\x0b\x32\x13.prefab.ClientStatsH\x00\x12\x30\n\x07loggers\x18\x05 \x01(\x0b\x32\x1d.prefab.LoggersTelemetryEventH\x00\x12/\n\x0e\x63ontext_shapes\x18\x06 \x01(\x0b\x32\x15.prefab.ContextShapesH\x00\x42\t\n\x07payload\"P\n\x0fTelemetryEvents\x12\x15\n\rinstance_hash\x18\x01 \x01(\t\x12&\n\x06\x65vents\x18\x02 \x03(\x0b\x32\x16.prefab.TelemetryEvent\"*\n\x17TelemetryEventsResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\";\n\x0f\x45xampleContexts\x12(\n\x08\x65xamples\x18\x01 \x03(\x0b\x32\x16.prefab.ExampleContext\"K\n\x0e\x45xampleContext\x12\x11\n\ttimestamp\x18\x01 \x01(\x03\x12&\n\ncontextSet\x18\x02 \x01(\x0b\x32\x12.prefab.ContextSet\"F\n\x0b\x43lientStats\x12\r\n\x05start\x18\x01 \x01(\x03\x12\x0b\n\x03\x65nd\x18\x02 \x01(\x03\x12\x1b\n\x13\x64ropped_event_count\x18\x03 \x01(\x04\"}\n\x06Schema\x12\x0e\n\x06schema\x18\x01 \x01(\t\x12.\n\x0bschema_type\x18\x02 \x01(\x0e\x32\x19.prefab.Schema.SchemaType\"3\n\nSchemaType\x12\x0b\n\x07UNKNOWN\x10\x00\x12\x07\n\x03ZOD\x10\x01\x12\x0f\n\x0bJSON_SCHEMA\x10\x02*:\n\x0eProvidedSource\x12\x1b\n\x17PROVIDED_SOURCE_NOT_SET\x10\x00\x12\x0b\n\x07\x45NV_VAR\x10\x01*\x8e\x01\n\nConfigType\x12\x17\n\x13NOT_SET_CONFIG_TYPE\x10\x00\x12\n\n\x06\x43ONFIG\x10\x01\x12\x10\n\x0c\x46\x45\x41TURE_FLAG\x10\x02\x12\r\n\tLOG_LEVEL\x10\x03\x12\x0b\n\x07SEGMENT\x10\x04\x12\x14\n\x10LIMIT_DEFINITION\x10\x05\x12\x0b\n\x07\x44\x45LETED\x10\x06\x12\n\n\x06SCHEMA\x10\x07*a\n\x08LogLevel\x12\x15\n\x11NOT_SET_LOG_LEVEL\x10\x00\x12\t\n\x05TRACE\x10\x01\x12\t\n\x05\x44\x45\x42UG\x10\x02\x12\x08\n\x04INFO\x10\x03\x12\x08\n\x04WARN\x10\x05\x12\t\n\x05\x45RROR\x10\x06\x12\t\n\x05\x46\x41TAL\x10\t*G\n\tOnFailure\x12\x0b\n\x07NOT_SET\x10\x00\x12\x10\n\x0cLOG_AND_PASS\x10\x01\x12\x10\n\x0cLOG_AND_FAIL\x10\x02\x12\t\n\x05THROW\x10\x03\x42L\n\x13\x63loud.prefab.domainB\x06PrefabZ-github.com/prefab-cloud/prefab-cloud-go/protob\x06proto3"
9
+
10
+ pool = ::Google::Protobuf::DescriptorPool.generated_pool
11
+ pool.add_serialized_file(descriptor_data)
12
+
13
+ module PrefabProto
14
+ ConfigServicePointer = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.ConfigServicePointer").msgclass
15
+ ConfigValue = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.ConfigValue").msgclass
16
+ Json = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.Json").msgclass
17
+ IsoDuration = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.IsoDuration").msgclass
18
+ Provided = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.Provided").msgclass
19
+ IntRange = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.IntRange").msgclass
20
+ StringList = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.StringList").msgclass
21
+ WeightedValue = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.WeightedValue").msgclass
22
+ WeightedValues = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.WeightedValues").msgclass
23
+ ApiKeyMetadata = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.ApiKeyMetadata").msgclass
24
+ Configs = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.Configs").msgclass
25
+ Config = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.Config").msgclass
26
+ Config::ValueType = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.Config.ValueType").enummodule
27
+ ChangedBy = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.ChangedBy").msgclass
28
+ ConfigRow = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.ConfigRow").msgclass
29
+ ConditionalValue = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.ConditionalValue").msgclass
30
+ Criterion = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.Criterion").msgclass
31
+ Criterion::CriterionOperator = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.Criterion.CriterionOperator").enummodule
32
+ Loggers = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.Loggers").msgclass
33
+ Logger = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.Logger").msgclass
34
+ LoggerReportResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.LoggerReportResponse").msgclass
35
+ LimitResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.LimitResponse").msgclass
36
+ LimitResponse::LimitPolicyNames = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.LimitResponse.LimitPolicyNames").enummodule
37
+ LimitRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.LimitRequest").msgclass
38
+ LimitRequest::LimitCombiner = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.LimitRequest.LimitCombiner").enummodule
39
+ ContextSet = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.ContextSet").msgclass
40
+ Context = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.Context").msgclass
41
+ Identity = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.Identity").msgclass
42
+ ConfigEvaluationMetaData = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.ConfigEvaluationMetaData").msgclass
43
+ ClientConfigValue = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.ClientConfigValue").msgclass
44
+ ClientDuration = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.ClientDuration").msgclass
45
+ ConfigEvaluations = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.ConfigEvaluations").msgclass
46
+ LimitDefinition = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.LimitDefinition").msgclass
47
+ LimitDefinition::SafetyLevel = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.LimitDefinition.SafetyLevel").enummodule
48
+ LimitDefinitions = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.LimitDefinitions").msgclass
49
+ BufferedRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.BufferedRequest").msgclass
50
+ BatchRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.BatchRequest").msgclass
51
+ BasicResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.BasicResponse").msgclass
52
+ CreationResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.CreationResponse").msgclass
53
+ IdBlock = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.IdBlock").msgclass
54
+ IdBlockRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.IdBlockRequest").msgclass
55
+ ContextShape = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.ContextShape").msgclass
56
+ ContextShapes = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.ContextShapes").msgclass
57
+ EvaluatedKeys = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.EvaluatedKeys").msgclass
58
+ EvaluatedConfig = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.EvaluatedConfig").msgclass
59
+ EvaluatedConfigs = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.EvaluatedConfigs").msgclass
60
+ ConfigEvaluationCounter = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.ConfigEvaluationCounter").msgclass
61
+ ConfigEvaluationCounter::Reason = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.ConfigEvaluationCounter.Reason").enummodule
62
+ ConfigEvaluationSummary = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.ConfigEvaluationSummary").msgclass
63
+ ConfigEvaluationSummaries = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.ConfigEvaluationSummaries").msgclass
64
+ LoggersTelemetryEvent = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.LoggersTelemetryEvent").msgclass
65
+ TelemetryEvent = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.TelemetryEvent").msgclass
66
+ TelemetryEvents = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.TelemetryEvents").msgclass
67
+ TelemetryEventsResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.TelemetryEventsResponse").msgclass
68
+ ExampleContexts = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.ExampleContexts").msgclass
69
+ ExampleContext = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.ExampleContext").msgclass
70
+ ClientStats = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.ClientStats").msgclass
71
+ Schema = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.Schema").msgclass
72
+ Schema::SchemaType = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.Schema.SchemaType").enummodule
73
+ ProvidedSource = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.ProvidedSource").enummodule
74
+ ConfigType = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.ConfigType").enummodule
75
+ LogLevel = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.LogLevel").enummodule
76
+ OnFailure = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.OnFailure").enummodule
77
+ end
@@ -0,0 +1,95 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Reforge
4
+ class CachingHttpConnection
5
+ CACHE_SIZE = 2.freeze
6
+ CacheEntry = Struct.new(:data, :etag, :expires_at)
7
+
8
+ class << self
9
+ def cache
10
+ @cache ||= FixedSizeHash.new(CACHE_SIZE)
11
+ end
12
+
13
+ def reset_cache!
14
+ @cache = FixedSizeHash.new(CACHE_SIZE)
15
+ end
16
+ end
17
+
18
+ def initialize(uri, api_key)
19
+ @connection = HttpConnection.new(uri, api_key)
20
+ end
21
+
22
+ def get(path)
23
+ now = Time.now.to_i
24
+ cache_key = "#{@connection.uri}#{path}"
25
+ cached = self.class.cache[cache_key]
26
+
27
+ # Check if we have a valid cached response
28
+ if cached&.data && cached.expires_at && now < cached.expires_at
29
+ return Faraday::Response.new(
30
+ status: 200,
31
+ body: cached.data,
32
+ response_headers: {
33
+ 'ETag' => cached.etag,
34
+ 'X-Cache' => 'HIT',
35
+ 'X-Cache-Expires-At' => cached.expires_at.to_s
36
+ }
37
+ )
38
+ end
39
+
40
+ # Make request with conditional GET if we have an ETag
41
+ response = if cached&.etag
42
+ @connection.get(path, { 'If-None-Match' => cached.etag })
43
+ else
44
+ @connection.get(path)
45
+ end
46
+
47
+ # Handle 304 Not Modified
48
+ if response.status == 304 && cached&.data
49
+ return Faraday::Response.new(
50
+ status: 200,
51
+ body: cached.data,
52
+ response_headers: {
53
+ 'ETag' => cached.etag,
54
+ 'X-Cache' => 'HIT',
55
+ 'X-Cache-Expires-At' => cached.expires_at.to_s
56
+ }
57
+ )
58
+ end
59
+
60
+ # Parse caching headers
61
+ cache_control = response.headers['Cache-Control'].to_s
62
+ etag = response.headers['ETag']
63
+
64
+ # Always add X-Cache header
65
+ response.headers['X-Cache'] = 'MISS'
66
+
67
+ # Don't cache if no-store is present
68
+ return response if cache_control.include?('no-store')
69
+
70
+ # Calculate expiration
71
+ max_age = cache_control.match(/max-age=(\d+)/)&.captures&.first&.to_i
72
+ expires_at = max_age ? now + max_age : nil
73
+
74
+ # Cache the response if we have caching headers
75
+ if etag || expires_at
76
+ self.class.cache[cache_key] = CacheEntry.new(
77
+ response.body,
78
+ etag,
79
+ expires_at
80
+ )
81
+ end
82
+
83
+ response
84
+ end
85
+
86
+ # Delegate other methods to the underlying connection
87
+ def post(path, body)
88
+ @connection.post(path, body)
89
+ end
90
+
91
+ def uri
92
+ @connection.uri
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,133 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'uuid'
4
+
5
+ module Reforge
6
+ class Client
7
+ LOG = Reforge::InternalLogger.new(self)
8
+ MAX_SLEEP_SEC = 10
9
+ BASE_SLEEP_SEC = 0.5
10
+
11
+ attr_reader :namespace, :interceptor, :sdk_key, :options, :instance_hash
12
+
13
+ def initialize(options = Reforge::Options.new)
14
+ @options = options.is_a?(Reforge::Options) ? options : Reforge::Options.new(options)
15
+ @namespace = @options.namespace
16
+ @stubs = {}
17
+ @instance_hash = ::UUID.new.generate
18
+
19
+ if @options.local_only?
20
+ LOG.debug 'Reforge SDK Running in Local Mode'
21
+ elsif @options.datafile?
22
+ LOG.debug 'Reforge SDK Running in DataFile Mode'
23
+ else
24
+ @sdk_key = @options.sdk_key
25
+ raise Reforge::Errors::InvalidSdkKeyError, @sdk_key if @sdk_key.nil? || @sdk_key.empty? || sdk_key.count('-') < 1
26
+ end
27
+
28
+ context.clear
29
+
30
+ Reforge::Context.global_context = @options.global_context
31
+
32
+ # start config client
33
+ config_client
34
+ end
35
+
36
+ def with_context(properties, &block)
37
+ Reforge::Context.with_context(properties, &block)
38
+ end
39
+
40
+ def context
41
+ Reforge::Context.current
42
+ end
43
+
44
+ def config_client(timeout: 5.0)
45
+ @config_client ||= Reforge::ConfigClient.new(self, timeout)
46
+ end
47
+
48
+ def stop
49
+ @config_client.stop
50
+ end
51
+
52
+ def feature_flag_client
53
+ @feature_flag_client ||= Reforge::FeatureFlagClient.new(self)
54
+ end
55
+
56
+ def context_shape_aggregator
57
+ return nil if @options.collect_max_shapes <= 0
58
+
59
+ @context_shape_aggregator ||= ContextShapeAggregator.new(client: self, max_shapes: @options.collect_max_shapes,
60
+ sync_interval: @options.collect_sync_interval)
61
+ end
62
+
63
+ def example_contexts_aggregator
64
+ return nil if @options.collect_max_example_contexts <= 0
65
+
66
+ @example_contexts_aggregator ||= ExampleContextsAggregator.new(
67
+ client: self,
68
+ max_contexts: @options.collect_max_example_contexts,
69
+ sync_interval: @options.collect_sync_interval
70
+ )
71
+ end
72
+
73
+ def evaluation_summary_aggregator
74
+ return nil if @options.collect_max_evaluation_summaries <= 0
75
+
76
+ @evaluation_summary_aggregator ||= EvaluationSummaryAggregator.new(
77
+ client: self,
78
+ max_keys: @options.collect_max_evaluation_summaries,
79
+ sync_interval: @options.collect_sync_interval
80
+ )
81
+ end
82
+
83
+ def set_rails_loggers
84
+ warn '[DEPRECATION] `set_rails_loggers` is deprecated since 1.6. Please use semantic_logger or `Prefab.log_filter` instead.'
85
+ end
86
+
87
+ def on_update(&block)
88
+ resolver.on_update(&block)
89
+ end
90
+
91
+ def enabled?(feature_name, jit_context = NO_DEFAULT_PROVIDED)
92
+ feature_flag_client.feature_is_on_for?(feature_name, jit_context)
93
+ end
94
+
95
+ def get(key, default = NO_DEFAULT_PROVIDED, jit_context = NO_DEFAULT_PROVIDED)
96
+ if is_ff?(key)
97
+ feature_flag_client.get(key, jit_context, default: default)
98
+ else
99
+ config_client.get(key, default, jit_context)
100
+ end
101
+ end
102
+
103
+ def post(path, body)
104
+ Reforge::HttpConnection.new(@options.telemetry_destination, @sdk_key).post(path, body)
105
+ end
106
+
107
+ def inspect
108
+ "#<Reforge::Client:#{object_id} namespace=#{namespace}>"
109
+ end
110
+
111
+ def resolver
112
+ config_client.resolver
113
+ end
114
+
115
+ # When starting a forked process, use this to re-use the options
116
+ # on_worker_boot do
117
+ # Prefab.fork
118
+ # end
119
+ def fork
120
+ Reforge::Client.new(@options.for_fork)
121
+ end
122
+
123
+ def defined?(key)
124
+ !!config_client.send(:raw, key)
125
+ end
126
+
127
+ def is_ff?(key)
128
+ raw = config_client.send(:raw, key)
129
+
130
+ raw && raw.allowable_values.any?
131
+ end
132
+ end
133
+ end