<commit_before>module CacheShoe
  # Handles cache reads and invalidations
  class Cacher
    attr_reader :scope

    def initialize(scope)
      @scope = scope
    end

    def fetch(&block)
      cache_hit = true
      result = cache.fetch(scope.cache_key) do
        cache_hit = false
        on_cache_miss scope.cache_key
        Result.new(yield)
      end
      on_cache_hit(scope.cache_key) if cache_hit
      result.unwrap
    end

    def invalidate(&block)
      on_cache_clear

      yield
    end

    private

    def on_cache_hit(key_val)
      if config.on_cache
        config.on_cache.call(key_val, :hit)
      end
      logger.info "cache hit #{key_val}"
    end

    def on_cache_miss(key_val)
      if config.on_cache
        config.on_cache.call(key_val, :miss)
      end
      logger.info "cache miss #{key_val}"
    end

    def get_cache_args(key_extractor, *args)
      case key_extractor
      when PASS_THROUGH then args
      when Proc         then [key_extractor.call(*args)].flatten
      when Symbol       then [args.first.send(key_extractor)]
      else
        fail "Can't create a cache key from #{key_extractor.inspect}"
      end
    end

    def on_cache_clear
      scope.key_extractors.each do |key_extractor|
        begin
          cache_args = get_cache_args(key_extractor, *(scope.args))
          cached_key = scope.cache_key(cache_args)
          logger.info "Clearing cache from #{scope.clearing_method}: #{cached_key}"
          if config.on_cache_clear
            config.on_cache_clear.call(
              cached_key, scope.clearing_method)
          end
          cache.delete cached_key
        rescue
          logger.error "Failed to clear cache from #{scope.class_name}." \
            "#{scope.clearing_method}, because the key extractor raised"
        end
      end
    end

    def cache
      config.cache
    end

    def logger
      config.logger
    end
<commit_msg>Move most of on_cache_clear to invalidate<commit_after>module CacheShoe
  # Handles cache reads and invalidations
  class Cacher
    attr_reader :scope

    def initialize(scope)
      @scope = scope
    end

    def fetch(&block)
      cache_hit = true
      result = cache.fetch(scope.cache_key) do
        cache_hit = false
        on_cache_miss scope.cache_key
        Result.new(yield)
      end
      on_cache_hit(scope.cache_key) if cache_hit
      result.unwrap
    end

    def invalidate(&block)
      scope.key_extractors.each do |key_extractor|
        begin
          cache_args = get_cache_args(key_extractor, *(scope.args))
          cached_key = scope.cache_key(cache_args)
          on_cache_clear cached_key
          logger.info "Clearing cache from #{scope.clearing_method}: #{cached_key}"
          cache.delete cached_key
        rescue
          logger.error "Failed to clear cache from #{scope.class_name}." \
            "#{scope.clearing_method}, because the key extractor raised"
        end
      end

      yield
    end

    private

    def on_cache_hit(key_val)
      if config.on_cache
        config.on_cache.call(key_val, :hit)
      end
      logger.info "cache hit #{key_val}"
    end

    def on_cache_miss(key_val)
      if config.on_cache
        config.on_cache.call(key_val, :miss)
      end
      logger.info "cache miss #{key_val}"
    end

    def get_cache_args(key_extractor, *args)
      case key_extractor
      when PASS_THROUGH then args
      when Proc         then [key_extractor.call(*args)].flatten
      when Symbol       then [args.first.send(key_extractor)]
      else
        fail "Can't create a cache key from #{key_extractor.inspect}"
      end
    end

    def on_cache_clear(cached_key)
      return unless config.on_cache_clear

      config.on_cache_clear.call(cached_key, scope.clearing_method)
    end

    def cache
      config.cache
    end

    def logger
      config.logger
    end

{'fraction_non_alphanumeric': 0.07106076210092688, 'fraction_numerical': 0.0, 'mean_word_length': 2.19227608874281, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1517739', 'n_tokens_mistral': 1216, 'n_tokens_neox': 1186, 'n_words': 289}