cache_json 1.2.1 → 1.2.6
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 +4 -4
- data/Gemfile.lock +3 -3
- data/README.md +38 -0
- data/lib/cache_json/adapters/redis.rb +4 -0
- data/lib/cache_json/base.rb +10 -1
- data/lib/cache_json/version.rb +1 -1
- data/lib/cache_json/worker.rb +56 -43
- metadata +6 -6
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 44125f970020a38afcbd640051d4f9b6d5565530b753d1e63079401d1ef607b2
         | 
| 4 | 
            +
              data.tar.gz: 8a6d4e5469e88e118ff40cc346b80d422002a2e36cde0318538b452a530ffa1b
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: b76526fafe43e2f8e51b785c18672fbf7f60c1ddd86ec98185499284bf40441c3dff96e3b55a771eb275ab33656548f6d012dd135c69b408057d5366cedd60af
         | 
| 7 | 
            +
              data.tar.gz: 7ab99f8451f502bae4c9f4805507f0bbdedec4c57b29117c869f079647482342b1b54c9d1bd96495928175122918623fc22a18691b34e0961f28c0fbfe05f70f
         | 
    
        data/Gemfile.lock
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            PATH
         | 
| 2 2 | 
             
              remote: .
         | 
| 3 3 | 
             
              specs:
         | 
| 4 | 
            -
                cache_json (1.2. | 
| 4 | 
            +
                cache_json (1.2.6)
         | 
| 5 5 | 
             
                  redis (>= 3.3.5, < 5)
         | 
| 6 6 |  | 
| 7 7 | 
             
            GEM
         | 
| @@ -15,7 +15,7 @@ GEM | |
| 15 15 | 
             
                parallel (1.19.1)
         | 
| 16 16 | 
             
                parser (2.7.0.3)
         | 
| 17 17 | 
             
                  ast (~> 2.4.0)
         | 
| 18 | 
            -
                rack (2.2. | 
| 18 | 
            +
                rack (2.2.3)
         | 
| 19 19 | 
             
                rack-protection (2.0.8.1)
         | 
| 20 20 | 
             
                  rack
         | 
| 21 21 | 
             
                rainbow (3.0.0)
         | 
| @@ -66,4 +66,4 @@ DEPENDENCIES | |
| 66 66 | 
             
              timecop (~> 0.9.1)
         | 
| 67 67 |  | 
| 68 68 | 
             
            BUNDLED WITH
         | 
| 69 | 
            -
               2. | 
| 69 | 
            +
               2.2.3
         | 
    
        data/README.md
    CHANGED
    
    | @@ -54,6 +54,44 @@ CacheJSON.configure do |config| | |
| 54 54 | 
             
            end
         | 
| 55 55 | 
             
            ```
         | 
| 56 56 |  | 
| 57 | 
            +
            ## Automatic refreshing (Sidekiq)
         | 
| 58 | 
            +
             | 
| 59 | 
            +
            There is a simple Sidekiq job that lets you pre-compute selected classes with specified ranges of arguments. All you have to do is add a `refresh` option:
         | 
| 60 | 
            +
             | 
| 61 | 
            +
            ```ruby
         | 
| 62 | 
            +
            class ExpensiveJob
         | 
| 63 | 
            +
             | 
| 64 | 
            +
              include CacheJSON::Base
         | 
| 65 | 
            +
             | 
| 66 | 
            +
             | 
| 67 | 
            +
              cache_json_options(
         | 
| 68 | 
            +
                time_to_expire: 1.hour,
         | 
| 69 | 
            +
                refresh: {
         | 
| 70 | 
            +
                  buffer: 5.minutes,
         | 
| 71 | 
            +
                  arguments: {
         | 
| 72 | 
            +
                    first: (5..10),
         | 
| 73 | 
            +
                    second: ['one option', 'another option'],
         | 
| 74 | 
            +
                    third: 'the only option',
         | 
| 75 | 
            +
                    fourth: -> { ['proc result'] }
         | 
| 76 | 
            +
                  }
         | 
| 77 | 
            +
                }
         | 
| 78 | 
            +
              )
         | 
| 79 | 
            +
              ...
         | 
| 80 | 
            +
            end
         | 
| 81 | 
            +
            ```
         | 
| 82 | 
            +
             | 
| 83 | 
            +
            The Sidekiq job will take the Cartesian product of all the argument ranges/arrays (all the combinations).
         | 
| 84 | 
            +
             | 
| 85 | 
            +
            We leave it to you to schedule the job. If you're using https://github.com/moove-it/sidekiq-scheduler, you can do something like this:
         | 
| 86 | 
            +
             | 
| 87 | 
            +
            ```yml
         | 
| 88 | 
            +
            cache_json_worker:
         | 
| 89 | 
            +
              every: "20s"
         | 
| 90 | 
            +
              class: CacheJSON::Worker
         | 
| 91 | 
            +
            ```
         | 
| 92 | 
            +
             | 
| 93 | 
            +
            Whenever the worker runs, it checks which results have expired, and refreshes only those. If you pass in the `buffer` option, it will actually refresh keys that are that far away from expiring. In the example above, the worker will refresh the cache 5 minutes before it expires. This is good if you want to avoid cache misses altogether.
         | 
| 94 | 
            +
             | 
| 57 95 | 
             
            ## Development
         | 
| 58 96 |  | 
| 59 97 | 
             
            After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
         | 
    
        data/lib/cache_json/base.rb
    CHANGED
    
    | @@ -8,7 +8,7 @@ module CacheJSON | |
| 8 8 | 
             
                  base.extend(ClassMethods)
         | 
| 9 9 | 
             
                end
         | 
| 10 10 |  | 
| 11 | 
            -
                def results(args)
         | 
| 11 | 
            +
                def results(args = {})
         | 
| 12 12 | 
             
                  raise ArgumentError, 'Must use keyword arguments' unless args.is_a?(Hash)
         | 
| 13 13 |  | 
| 14 14 | 
             
                  options = self.class.cache_json_full_options
         | 
| @@ -17,6 +17,11 @@ module CacheJSON | |
| 17 17 | 
             
                    JSON.parse(refresh_cache!(args: args, cache: cache).to_json) # stringify keys
         | 
| 18 18 | 
             
                end
         | 
| 19 19 |  | 
| 20 | 
            +
                def cache_expiring_soon?(args:, cache: nil)
         | 
| 21 | 
            +
                  cache ||= Cache.new(args: args, options: self.class.cache_json_full_options)
         | 
| 22 | 
            +
                  cache.cache_expiring_soon?
         | 
| 23 | 
            +
                end
         | 
| 24 | 
            +
             | 
| 20 25 | 
             
                def clear_cache!
         | 
| 21 26 | 
             
                  Cache.new(options: self.class.cache_json_full_options).clear_cache!
         | 
| 22 27 | 
             
                end
         | 
| @@ -54,6 +59,10 @@ module CacheJSON | |
| 54 59 | 
             
                    adapter.clear_cache!
         | 
| 55 60 | 
             
                  end
         | 
| 56 61 |  | 
| 62 | 
            +
                  def cache_expiring_soon?
         | 
| 63 | 
            +
                    adapter.cache_expiring_soon?
         | 
| 64 | 
            +
                  end
         | 
| 65 | 
            +
             | 
| 57 66 | 
             
                  def adapter
         | 
| 58 67 | 
             
                    @adapter ||= CacheJSON::Adapters::Redis.new(args: args, options: options)
         | 
| 59 68 | 
             
                  end
         | 
    
        data/lib/cache_json/version.rb
    CHANGED
    
    
    
        data/lib/cache_json/worker.rb
    CHANGED
    
    | @@ -5,7 +5,6 @@ begin | |
| 5 5 | 
             
            rescue LoadError
         | 
| 6 6 | 
             
              nil
         | 
| 7 7 | 
             
            end
         | 
| 8 | 
            -
             | 
| 9 8 | 
             
            module CacheJSON
         | 
| 10 9 | 
             
              class Worker
         | 
| 11 10 | 
             
                if defined?(Sidekiq)
         | 
| @@ -18,66 +17,80 @@ module CacheJSON | |
| 18 17 | 
             
                  end
         | 
| 19 18 | 
             
                end
         | 
| 20 19 |  | 
| 21 | 
            -
                def perform( | 
| 20 | 
            +
                def perform(params="{}")
         | 
| 21 | 
            +
                  parsed_params = JSON.parse(params)
         | 
| 22 | 
            +
                  klass = parsed_params["klass"]
         | 
| 23 | 
            +
                  args = (parsed_params["args"] || {}).transform_keys(&:to_sym)
         | 
| 22 24 | 
             
                  if klass
         | 
| 23 | 
            -
                    klass. | 
| 25 | 
            +
                    klass = Object.const_get(klass)
         | 
| 26 | 
            +
                    klass.new.refresh_cache!(args: args) if should_refresh?(klass, args)
         | 
| 24 27 | 
             
                  else
         | 
| 25 | 
            -
                     | 
| 28 | 
            +
                    AllPermutations.new.results.each do |perm|
         | 
| 29 | 
            +
                      if should_refresh?(perm[:klass], perm[:args])
         | 
| 30 | 
            +
                        perm[:klass] = perm[:klass].to_s
         | 
| 31 | 
            +
                        CacheJSON::Worker.perform_async(perm.to_json)
         | 
| 32 | 
            +
                      end
         | 
| 33 | 
            +
                    end
         | 
| 26 34 | 
             
                  end
         | 
| 27 35 | 
             
                end
         | 
| 28 36 |  | 
| 29 37 | 
             
                private
         | 
| 30 38 |  | 
| 31 | 
            -
                def  | 
| 32 | 
            -
                   | 
| 33 | 
            -
                    all_argument_permutations(klass).each do |args|
         | 
| 34 | 
            -
                      CacheJSON::Worker.new.perform(klass: klass, args: args) if should_refresh?(klass, args)
         | 
| 35 | 
            -
                    end
         | 
| 36 | 
            -
                  end
         | 
| 39 | 
            +
                def should_refresh?(klass, args)
         | 
| 40 | 
            +
                  !klass.new.check_cache(args: args) || klass.new.cache_expiring_soon?(args: args)
         | 
| 37 41 | 
             
                end
         | 
| 38 42 |  | 
| 39 | 
            -
                 | 
| 40 | 
            -
                   | 
| 41 | 
            -
             | 
| 42 | 
            -
             | 
| 43 | 
            +
                class AllPermutations
         | 
| 44 | 
            +
                  def results
         | 
| 45 | 
            +
                    all_cache_classes.flat_map do |klass|
         | 
| 46 | 
            +
                      all_argument_permutations(klass).map do |args|
         | 
| 47 | 
            +
                        {
         | 
| 48 | 
            +
                          klass: klass,
         | 
| 49 | 
            +
                          args: args
         | 
| 50 | 
            +
                        }
         | 
| 51 | 
            +
                      end
         | 
| 52 | 
            +
                    end
         | 
| 43 53 | 
             
                  end
         | 
| 44 | 
            -
                end
         | 
| 45 54 |  | 
| 46 | 
            -
             | 
| 47 | 
            -
             | 
| 48 | 
            -
             | 
| 49 | 
            -
             | 
| 50 | 
            -
             | 
| 51 | 
            -
                    []
         | 
| 55 | 
            +
                  def all_cache_classes
         | 
| 56 | 
            +
                    # TODO: make this more efficient
         | 
| 57 | 
            +
                    ObjectSpace.each_object(Class).select do |klass|
         | 
| 58 | 
            +
                      klass.included_modules.include? CacheJSON::Base
         | 
| 59 | 
            +
                    end
         | 
| 52 60 | 
             
                  end
         | 
| 53 | 
            -
                end
         | 
| 54 61 |  | 
| 55 | 
            -
             | 
| 56 | 
            -
             | 
| 57 | 
            -
             | 
| 58 | 
            -
             | 
| 59 | 
            -
             | 
| 60 | 
            -
             | 
| 61 | 
            -
                    values_for_key(non_fixed_points, pivot_key).flat_map do |pivot_key_value|
         | 
| 62 | 
            -
                      new_fixed_points = fixed_points.merge(Hash[pivot_key, pivot_key_value])
         | 
| 63 | 
            -
                      all_combinations_with_fixed_points(new_fixed_points, full_hash)
         | 
| 62 | 
            +
                  def all_argument_permutations(klass)
         | 
| 63 | 
            +
                    refresh_options = klass.cache_json_full_options[:refresh]
         | 
| 64 | 
            +
                    if refresh_options
         | 
| 65 | 
            +
                      all_combinations_with_fixed_points({}, refresh_options[:arguments])
         | 
| 66 | 
            +
                    else
         | 
| 67 | 
            +
                      []
         | 
| 64 68 | 
             
                    end
         | 
| 65 69 | 
             
                  end
         | 
| 66 | 
            -
                end
         | 
| 67 70 |  | 
| 68 | 
            -
             | 
| 69 | 
            -
             | 
| 70 | 
            -
             | 
| 71 | 
            -
             | 
| 72 | 
            -
             | 
| 73 | 
            -
             | 
| 74 | 
            -
             | 
| 75 | 
            -
             | 
| 71 | 
            +
                  def all_combinations_with_fixed_points(fixed_points, full_hash)
         | 
| 72 | 
            +
                    non_fixed_points = full_hash.dup.delete_if { |k, _| fixed_points.key?(k) }
         | 
| 73 | 
            +
                    if non_fixed_points.empty?
         | 
| 74 | 
            +
                      [fixed_points]
         | 
| 75 | 
            +
                    else
         | 
| 76 | 
            +
                      pivot_key = non_fixed_points.keys.first
         | 
| 77 | 
            +
                      values_for_key(non_fixed_points, pivot_key).flat_map do |pivot_key_value|
         | 
| 78 | 
            +
                        new_fixed_points = fixed_points.merge(Hash[pivot_key, pivot_key_value])
         | 
| 79 | 
            +
                        all_combinations_with_fixed_points(new_fixed_points, full_hash)
         | 
| 80 | 
            +
                      end
         | 
| 81 | 
            +
                    end
         | 
| 76 82 | 
             
                  end
         | 
| 77 | 
            -
                end
         | 
| 78 83 |  | 
| 79 | 
            -
             | 
| 80 | 
            -
             | 
| 84 | 
            +
                  def values_for_key(hsh, key)
         | 
| 85 | 
            +
                    pivot_key_values = hsh[key]
         | 
| 86 | 
            +
                    if pivot_key_values.is_a?(Proc)
         | 
| 87 | 
            +
                      pivot_key_values.call
         | 
| 88 | 
            +
                    elsif pivot_key_values.is_a?(Range) || pivot_key_values.is_a?(Array)
         | 
| 89 | 
            +
                      pivot_key_values
         | 
| 90 | 
            +
                    else
         | 
| 91 | 
            +
                      [pivot_key_values]
         | 
| 92 | 
            +
                    end
         | 
| 93 | 
            +
                  end
         | 
| 81 94 | 
             
                end
         | 
| 82 95 | 
             
              end
         | 
| 83 96 | 
             
            end
         | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: cache_json
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 1.2. | 
| 4 | 
            +
              version: 1.2.6
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Paul Gut
         | 
| 8 | 
            -
            autorequire: | 
| 8 | 
            +
            autorequire:
         | 
| 9 9 | 
             
            bindir: exe
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date:  | 
| 11 | 
            +
            date: 2021-04-17 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: redis
         | 
| @@ -166,7 +166,7 @@ licenses: | |
| 166 166 | 
             
            metadata:
         | 
| 167 167 | 
             
              homepage_uri: https://github.com/loopsupport/cache_json
         | 
| 168 168 | 
             
              source_code_uri: https://github.com/loopsupport/cache_json
         | 
| 169 | 
            -
            post_install_message: | 
| 169 | 
            +
            post_install_message:
         | 
| 170 170 | 
             
            rdoc_options: []
         | 
| 171 171 | 
             
            require_paths:
         | 
| 172 172 | 
             
            - lib
         | 
| @@ -181,8 +181,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement | |
| 181 181 | 
             
                - !ruby/object:Gem::Version
         | 
| 182 182 | 
             
                  version: '0'
         | 
| 183 183 | 
             
            requirements: []
         | 
| 184 | 
            -
            rubygems_version: 3. | 
| 185 | 
            -
            signing_key: | 
| 184 | 
            +
            rubygems_version: 3.2.3
         | 
| 185 | 
            +
            signing_key:
         | 
| 186 186 | 
             
            specification_version: 4
         | 
| 187 187 | 
             
            summary: Extremely simple Redis caching for any Ruby class
         | 
| 188 188 | 
             
            test_files: []
         |