fino 1.3.1 → 1.5.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c47c47b3ab49c1eac2959185f67a6cc62e952936c7693f1e1d3d95843afaae88
4
- data.tar.gz: da1f3fea78b8d9adbf58a3209c87e6c8acd717371dafe7618f9a2522e744fc0d
3
+ metadata.gz: 23a8486cb9d7c402ff499051da385a911437dd8a4d9a49df5712ef3e439f0b0d
4
+ data.tar.gz: cdd83bdb9542a59f4c0e4f409e76231a40028acf25e2293de84e45873c296b26
5
5
  SHA512:
6
- metadata.gz: bbadb8e1f7f954e7c1f0d9d1a0d7f6455236e67c6dfdaad87a02b9659b3a130f4c7be93cad53f9c486fad6cecd335a308e696ee82b91b1404f2a7fa31048c15c
7
- data.tar.gz: '0797cdb045a602b6f9b79ce8f772f7085c857d9addb3d664d74f3a3790676afe046b4c5d81ad4d6b2865b4c244b6debc7bc2ac6ed87cb255adf66fea4a57d9be'
6
+ metadata.gz: 59315d14709d165cfe989d66324ca823f8fb13cd8c140246d6bb9542876d49446a9b52654ac15b34b39a7bdb8f9b79bba9e4d065ab8e9d35e2150a3862f32e7d
7
+ data.tar.gz: a9fc49c4e631b8a6812ff51401597591886a42e6a354feed62bdd8e308a1ebef66469485fdc83e647ad53e1a057d5860411e5ff4c15193b6a57fe72b7910b041
data/lib/fino/adapter.rb CHANGED
@@ -1,11 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Fino::Adapter
4
- def read(setting_definition)
4
+ def read(setting_key)
5
5
  raise NotImplementedError
6
6
  end
7
7
 
8
- def read_multi(setting_definitions)
8
+ def read_multi(setting_keys)
9
9
  raise NotImplementedError
10
10
  end
11
11
 
@@ -13,6 +13,10 @@ module Fino::Adapter
13
13
  raise NotImplementedError
14
14
  end
15
15
 
16
+ def read_persisted_setting_keys
17
+ raise NotImplementedError
18
+ end
19
+
16
20
  def fetch_value_from(raw_adapter_data)
17
21
  raise NotImplementedError
18
22
  end
@@ -28,13 +28,11 @@ class Fino::Definition::Setting
28
28
  end
29
29
 
30
30
  def default
31
- return @default if defined?(@default)
32
-
33
- @default = options[:default]
31
+ defined?(@default) ? @default : @default = options[:default]
34
32
  end
35
33
 
36
34
  def description
37
- options[:description]
35
+ defined?(@description) ? @description : @description = options[:description]
38
36
  end
39
37
 
40
38
  def path
data/lib/fino/library.rb CHANGED
@@ -81,6 +81,10 @@ class Fino::Library
81
81
  pipeline.read_multi(setting_definitions)
82
82
  end
83
83
 
84
+ def persisted_keys
85
+ adapter.read_persisted_setting_keys
86
+ end
87
+
84
88
  private
85
89
 
86
90
  attr_reader :configuration
@@ -97,7 +101,11 @@ class Fino::Library
97
101
  end
98
102
 
99
103
  def storage
100
- Fino::Pipe::Storage.new(configuration.adapter_builder_block.call)
104
+ Fino::Pipe::Storage.new(adapter)
105
+ end
106
+
107
+ def adapter
108
+ @adapter ||= configuration.adapter_builder_block.call
101
109
  end
102
110
 
103
111
  def cache
@@ -8,11 +8,11 @@ class Fino::Pipe::Storage
8
8
  end
9
9
 
10
10
  def read(setting_definition)
11
- to_setting(setting_definition, adapter.read(setting_definition))
11
+ to_setting(setting_definition, adapter.read(setting_definition.key))
12
12
  end
13
13
 
14
14
  def read_multi(setting_definitions)
15
- setting_definitions.zip(adapter.read_multi(setting_definitions)).map do |definition, raw_data|
15
+ setting_definitions.zip(adapter.read_multi(setting_definitions.map(&:key))).map do |definition, raw_data|
16
16
  to_setting(definition, raw_data)
17
17
  end
18
18
  end
@@ -2,6 +2,7 @@
2
2
 
3
3
  class Fino::Settings::Float
4
4
  include Fino::Setting
5
+ include Fino::Settings::Numeric
5
6
 
6
7
  self.type_identifier = :float
7
8
 
@@ -2,6 +2,7 @@
2
2
 
3
3
  class Fino::Settings::Integer
4
4
  include Fino::Setting
5
+ include Fino::Settings::Numeric
5
6
 
6
7
  self.type_identifier = :integer
7
8
 
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Fino::Settings::Numeric
4
+ module Unit
5
+ class Generic
6
+ attr_reader :name, :short_name
7
+
8
+ def initialize(name, short_name = nil)
9
+ @name = name
10
+ @short_name = short_name || name
11
+ end
12
+ end
13
+
14
+ class Milliseconds < Generic
15
+ def initialize = super("Milliseconds", "ms")
16
+ end
17
+
18
+ module_function
19
+
20
+ def for(identifier)
21
+ case identifier
22
+ when :ms
23
+ Milliseconds.new
24
+ else
25
+ Generic.new(identifier.to_s.capitalize)
26
+ end
27
+ end
28
+ end
29
+
30
+ def unit
31
+ return unless (identifier = definition.options[:unit])
32
+
33
+ @unit ||= Unit.for(identifier)
34
+ end
35
+
36
+ private
37
+
38
+ def inspectable_attributes
39
+ additional_attributes = {}
40
+ additional_attributes[:unit] = unit.short_name if unit
41
+
42
+ super.merge(additional_attributes)
43
+ end
44
+ end
@@ -0,0 +1,76 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Fino
4
+ module Solid
5
+ class Adapter
6
+ include Fino::Adapter
7
+
8
+ SCOPE_PREFIX = "s"
9
+ VARIANT_PREFIX = "v"
10
+ VALUE_KEY = "v"
11
+
12
+ def read(setting_key)
13
+ setting = Fino::Solid::Setting.find_by(key: setting_key)
14
+ setting&.data || {}
15
+ end
16
+
17
+ def read_multi(setting_keys)
18
+ settings_by_key = Fino::Solid::Setting.where(key: setting_keys).index_by(&:key)
19
+
20
+ setting_keys.map { |key| settings_by_key[key]&.data || {} }
21
+ end
22
+
23
+ def write(setting_definition, value, overrides, variants)
24
+ serialize_value = ->(raw_value) { setting_definition.type_class.serialize(raw_value) }
25
+
26
+ data = { VALUE_KEY => serialize_value.call(value) }
27
+
28
+ overrides.each do |scope, scope_value|
29
+ data["#{SCOPE_PREFIX}/#{scope}/#{VALUE_KEY}"] = serialize_value.call(scope_value)
30
+ end
31
+
32
+ variants.each do |variant|
33
+ next if variant.value == Fino::AbTesting::Variant::CONTROL_VALUE
34
+
35
+ data["#{VARIANT_PREFIX}/#{variant.percentage}/#{VALUE_KEY}"] = serialize_value.call(variant.value)
36
+ end
37
+
38
+ Fino::Solid::Setting.upsert(
39
+ { key: setting_definition.key, data: data },
40
+ unique_by: :key
41
+ )
42
+ end
43
+
44
+ def read_persisted_setting_keys
45
+ Fino::Solid::Setting.pluck(:key)
46
+ end
47
+
48
+ def clear(setting_key)
49
+ Fino::Solid::Setting.where(key: setting_key).delete_all > 0
50
+ end
51
+
52
+ def fetch_value_from(raw_adapter_data)
53
+ raw_adapter_data.key?(VALUE_KEY) ? raw_adapter_data.delete(VALUE_KEY) : Fino::EMPTINESS
54
+ end
55
+
56
+ def fetch_raw_overrides_from(raw_adapter_data)
57
+ raw_adapter_data.each_with_object({}) do |(key, value), memo|
58
+ next unless key.start_with?("#{SCOPE_PREFIX}/")
59
+
60
+ scope = key.split("/", 3)[1]
61
+ memo[scope] = value
62
+ end
63
+ end
64
+
65
+ def fetch_raw_variants_from(raw_adapter_data)
66
+ raw_adapter_data.each_with_object([]) do |(key, value), memo|
67
+ next unless key.start_with?("#{VARIANT_PREFIX}/")
68
+
69
+ percentage = key.split("/", 3)[1]
70
+
71
+ memo << { percentage: percentage.to_f, value: value }
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails/generators"
4
+ require "rails/generators/active_record"
5
+
6
+ module Fino
7
+ module Solid
8
+ module Generators
9
+ class InstallGenerator < ::Rails::Generators::Base
10
+ include ::ActiveRecord::Generators::Migration
11
+
12
+ source_root File.expand_path("templates", __dir__)
13
+
14
+ def copy_migration
15
+ migration_template "create_fino_settings.rb.tt", File.join(db_migrate_path, "create_fino_settings.rb")
16
+ end
17
+
18
+ private
19
+
20
+ def db_migrate_path
21
+ "db/migrate"
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Fino
4
+ module Solid
5
+ class Railtie < ::Rails::Railtie
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Fino
4
+ module Solid
5
+ class Record < ActiveRecord::Base
6
+ self.abstract_class = true
7
+
8
+ connects_to(**Fino::Solid.connects_to) if Fino::Solid.connects_to
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Fino
4
+ module Solid
5
+ class Setting < Record
6
+ self.table_name = "fino_settings"
7
+
8
+ serialize :data, coder: JSON
9
+
10
+ validates :key, presence: true, uniqueness: true
11
+ end
12
+ end
13
+ end
data/lib/fino/solid.rb ADDED
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_record"
4
+
5
+ module Fino
6
+ module Solid
7
+ mattr_accessor :connects_to
8
+
9
+ class << self
10
+ def configure(&block)
11
+ instance_eval(&block)
12
+ end
13
+ end
14
+ end
15
+ end
16
+
17
+ require "fino/solid/record"
18
+ require "fino/solid/setting"
19
+ require "fino/solid/adapter"
20
+ require "fino/solid/railtie" if defined?(Rails::Railtie)
21
+
22
+ require "fino/solid/generators/install/install_generator"
data/lib/fino/version.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Fino
4
- VERSION = "1.3.1"
4
+ VERSION = "1.5.0"
5
5
  REQUIRED_RUBY_VERSION = ">= 3.0.0"
6
6
  end
data/lib/fino-solid.rb ADDED
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "fino"
4
+ require "fino/solid"
data/lib/fino.rb CHANGED
@@ -91,6 +91,11 @@ Zeitwerk::Loader.for_gem.tap do |l|
91
91
  root_relative_path.call("lib/fino/redis.rb"),
92
92
  root_relative_path.call("lib/fino/redis/"),
93
93
 
94
+ # Fino Solid
95
+ root_relative_path.call("lib/fino-solid.rb"),
96
+ root_relative_path.call("lib/fino/solid.rb"),
97
+ root_relative_path.call("lib/fino/solid/"),
98
+
94
99
  # Other
95
100
  root_relative_path.call("lib/fino/metadata.rb"),
96
101
  root_relative_path.call("lib/fino/railtie.rb")
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fino
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.1
4
+ version: 1.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Egor Iskrenkov
@@ -31,6 +31,7 @@ extra_rdoc_files: []
31
31
  files:
32
32
  - LICENSE
33
33
  - README.md
34
+ - lib/fino-solid.rb
34
35
  - lib/fino.rb
35
36
  - lib/fino/ab_testing/experiment.rb
36
37
  - lib/fino/ab_testing/variant.rb
@@ -57,8 +58,15 @@ files:
57
58
  - lib/fino/settings/boolean.rb
58
59
  - lib/fino/settings/float.rb
59
60
  - lib/fino/settings/integer.rb
61
+ - lib/fino/settings/numeric.rb
60
62
  - lib/fino/settings/section.rb
61
63
  - lib/fino/settings/string.rb
64
+ - lib/fino/solid.rb
65
+ - lib/fino/solid/adapter.rb
66
+ - lib/fino/solid/generators/install/install_generator.rb
67
+ - lib/fino/solid/railtie.rb
68
+ - lib/fino/solid/record.rb
69
+ - lib/fino/solid/setting.rb
62
70
  - lib/fino/version.rb
63
71
  homepage: https://github.com/eiskrenkov/fino
64
72
  licenses: