bipolar_cache 0.1.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 00fb9f8f43d45504192121714c562545f1d9815f39801461c3bcda66cb7e26e6
4
+ data.tar.gz: e5e4e33e2ec9cc2566229fc301c2e7e94935a7c58035131fa5a0a8101f59494c
5
+ SHA512:
6
+ metadata.gz: d6f667231620b0f8f7b3ff02be2ebf196dfa8c82ae8308f1fb25ee4bcc8ec1fdd51b827ba05245eb1877f15942d6931f2b316189f9b91a7b84b58beec5c81db6
7
+ data.tar.gz: 293f9bd8cfb8259351657b5ff038f157df257bab913a7b0e5526835032dd5a807545dbe395a6f62ecbd44597495a608be63ab92ffe82508b79afa68dc54a9bf7
data/.rubocop.yml ADDED
@@ -0,0 +1,19 @@
1
+ AllCops:
2
+ TargetRubyVersion: 3.0
3
+ SuggestExtensions: false
4
+ NewCops: disable
5
+
6
+ Metrics/AbcSize:
7
+ Enabled: false
8
+
9
+ Metrics/MethodLength:
10
+ Enabled: false
11
+
12
+ Style/Documentation:
13
+ Enabled: false
14
+
15
+ Style/StringLiterals:
16
+ EnforcedStyle: double_quotes
17
+
18
+ Style/StringLiteralsInInterpolation:
19
+ EnforcedStyle: double_quotes
data/README.md ADDED
@@ -0,0 +1,27 @@
1
+ # BipolarCache
2
+
3
+ Probabalistic caching toolkit useful for caching of database counters, and other operations.
4
+
5
+ ## Installation
6
+
7
+ Install the gem and add to the application's Gemfile by executing:
8
+
9
+ $ bundle add bipolar_cache
10
+
11
+ If bundler is not being used to manage dependencies, install the gem by executing:
12
+
13
+ $ gem install bipolar_cache
14
+
15
+ ## Usage
16
+
17
+
18
+
19
+ ## Development
20
+
21
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
22
+
23
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
24
+
25
+ ## Contributing
26
+
27
+ Bug reports and pull requests are welcome on GitHub at https://github.com/rubakas/bipolar_cache.
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "minitest/test_task"
5
+
6
+ Minitest::TestTask.create
7
+
8
+ require "rubocop/rake_task"
9
+
10
+ RuboCop::RakeTask.new
11
+
12
+ task default: %i[test rubocop]
@@ -0,0 +1,143 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BipolarCache
4
+ module Sequel
5
+ module PluginAlpha
6
+ module ClassMethods
7
+ def instance_dataset_bipolar_count_cache(name, **opts)
8
+ opts = opts.merge({ name: name })
9
+ method_name = opts[:method] || "#{name}_count"
10
+
11
+ define_method method_name do
12
+ bcsp_cache(**fetch_or_build_procs(**opts))
13
+ end
14
+
15
+ define_method "#{method_name}_refresh!" do
16
+ procs = fetch_or_build_procs(**opts)
17
+ actual_value = procs[:actual].call
18
+ procs[:update].call(actual_value) if actual_value != procs[:cached].call
19
+ actual_value
20
+ end
21
+
22
+ define_method "#{method_name}_increment!" do |by: 1|
23
+ procs = fetch_or_build_procs(**opts)
24
+
25
+ procs[:update].call(by + procs[:cached].call)
26
+ end
27
+
28
+ define_method "#{method_name}_decrement!" do |by: 1|
29
+ procs = fetch_or_build_procs(**opts)
30
+
31
+ procs[:update].call((-by) + procs[:cached].call)
32
+ end
33
+ end
34
+ end
35
+
36
+ def self.included(base)
37
+ base.extend ClassMethods
38
+ end
39
+
40
+ def bcsp_cache(**procs)
41
+ BipolarCache.read!(**procs)
42
+ end
43
+
44
+ def fetch_or_build_procs(**opts)
45
+ # create cached store for instance procs, if none
46
+ instance_variable_set(:@bcsp_proc_store, {}) unless instance_variable_defined?(:@bcsp_proc_store)
47
+
48
+ if instance_variable_get(:@bcsp_proc_store)[opts[:name]].nil?
49
+ instance_variable_get(:@bcsp_proc_store)[opts[:name]] =
50
+ {
51
+ actual: bcsp_proc_actual_from(**opts),
52
+ cached: bcsp_proc_cached_from(**opts),
53
+ update: bcsp_proc_update_from(**opts),
54
+ chance: bcsp_proc_chance_from(**opts),
55
+ rescue: bcsp_proc_rescue_from(**opts),
56
+ if: bcsp_proc_if_from(**opts)
57
+ }
58
+ end
59
+
60
+ # stored procs
61
+ instance_variable_get(:@bcsp_proc_store)[opts[:name]]
62
+ end
63
+
64
+ def bcsp_proc_actual_from(**opts)
65
+ case opts[:actual]
66
+ when Proc
67
+ opts[:actual]
68
+ when String, Symbol
69
+ -> { send(opts[:actual]) }
70
+ else
71
+ -> { send("#{opts[:name]}_dataset").count }
72
+ end
73
+ end
74
+
75
+ def bcsp_proc_cached_from(**opts)
76
+ case opts[:cached]
77
+ when Proc
78
+ opts[:cached]
79
+ when String, Symbol
80
+ -> { send(opts[:cached]) }
81
+ else
82
+ -> { send("#{opts[:name]}_count_cache") }
83
+ end
84
+ end
85
+
86
+ def bcsp_proc_update_from(**opts)
87
+ cache_name = if opts[:cached].is_a?(String) || opts[:cached].is_a?(Symbol)
88
+ opts[:cached]
89
+ else
90
+ "#{opts[:name]}_count_cache"
91
+ end
92
+
93
+ case opts[:update]
94
+ when Proc
95
+ opts[:update]
96
+ when String, Symbol
97
+ -> { send(opts[:update]) }
98
+ else
99
+ ->(value) { update({ cache_name => value }) }
100
+ end
101
+ end
102
+
103
+ def bcsp_proc_chance_from(**opts)
104
+ case opts[:chance]
105
+ when Proc
106
+ opts[:chance]
107
+ when Integer, Float
108
+ normalised_chance = if opts[:chance] > 1
109
+ opts[:chance] / 100
110
+ else
111
+ opts[:chance]
112
+ end
113
+ ->(_value) { normalised_chance }
114
+ else # default
115
+ ->(value) { value < 10 ? 0.1 : 0.9 }
116
+ end
117
+ end
118
+
119
+ def bcsp_proc_rescue_from(**opts)
120
+ if opts[:rescue].is_a? Proc
121
+ opts[:rescue]
122
+ else # default
123
+ lambda { |e|
124
+ e.inspect
125
+ 0
126
+ }
127
+ end
128
+ end
129
+
130
+ def bcsp_proc_if_from(**opts)
131
+ case opts[:if]
132
+ when Proc
133
+ opts[:if]
134
+ when TrueClass, FalseClass
135
+ value = opts[:if]
136
+ -> { value }
137
+ else # default
138
+ -> { true }
139
+ end
140
+ end
141
+ end
142
+ end
143
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BipolarCache
4
+ VERSION = "0.1.0"
5
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "bipolar_cache/version"
4
+
5
+ module BipolarCache
6
+ class Error < StandardError; end
7
+
8
+ ##
9
+ # It may read actual value,
10
+ # it may read cached value,
11
+ # or it may write actual value into cache!
12
+ # It depends on chance.
13
+ # Call it at your peril.
14
+ #
15
+ # @param actual [Proc] callable to perform an operation (cacheable)
16
+ # @param cached [Proc] callable to read cached value
17
+ # @param chance [Proc(Object)] callable to compute chance of cache hit
18
+ # @param if [Proc] callable to enable/disable caching
19
+ # @param rescue [Proc(StandardError)] callable to be invoked on exception
20
+ # @param update [Proc(Object)] callable to update cached value
21
+ # @return [Object]
22
+ def self.read!(**procs)
23
+ return procs[:actual].call unless procs[:if].call
24
+
25
+ cached_value = procs[:cached].call
26
+
27
+ if procs[:chance].call(cached_value) > rand
28
+ cached_value
29
+ else
30
+ actual_value = procs[:actual].call
31
+ procs[:update].call(actual_value) if cached_value != actual_value
32
+
33
+ actual_value
34
+ end
35
+ rescue StandardError => e
36
+ procs[:rescue].call(e) if procs[:rescue].is_a?(Proc)
37
+ end
38
+ end
@@ -0,0 +1,4 @@
1
+ module BipolarCache
2
+ VERSION: String
3
+ # See the writing guide of rbs: https://github.com/ruby/rbs#guides
4
+ end
metadata ADDED
@@ -0,0 +1,53 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: bipolar_cache
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Andriy Tyurnikov
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2024-04-11 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Probabalistic caching toolkit useful for caching of database counters,
14
+ and other operations.
15
+ email:
16
+ - Andriy.Tyurnikov@gmail.com
17
+ executables: []
18
+ extensions: []
19
+ extra_rdoc_files: []
20
+ files:
21
+ - ".rubocop.yml"
22
+ - README.md
23
+ - Rakefile
24
+ - lib/bipolar_cache.rb
25
+ - lib/bipolar_cache/sequel/plugin_alpha.rb
26
+ - lib/bipolar_cache/version.rb
27
+ - sig/bipolar_cache.rbs
28
+ homepage: https://github.com/rubakas/bipolar_cache
29
+ licenses: []
30
+ metadata:
31
+ homepage_uri: https://github.com/rubakas/bipolar_cache
32
+ source_code_uri: https://github.com/rubakas/bipolar_cache
33
+ changelog_uri: https://github.com/rubakas/bipolar_cache
34
+ post_install_message:
35
+ rdoc_options: []
36
+ require_paths:
37
+ - lib
38
+ required_ruby_version: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: 3.0.0
43
+ required_rubygems_version: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ requirements: []
49
+ rubygems_version: 3.5.6
50
+ signing_key:
51
+ specification_version: 4
52
+ summary: BipolarCache. Probabalistic caching toolkit.
53
+ test_files: []