<commit_before>require 'redis'
require 'core_ext/hash' unless defined?(ActiveSupport)
require 'redis/marshal'
require 'redis/tracked_hash'

if defined?(Rack::Session)
  require "rack/session/abstract/id"
  require 'rack/session/redis_hash'
end

require 'securerandom'

class Redis
  class NativeHash < TrackedHash

    attr_accessor :namespace

    def initialize(*args)
      super(nil)
      track!
      if args.first.kind_of?(String) or args.first.kind_of?(Symbol)
        self.namespace = args.shift
      elsif !self.instance_of?(NativeHash) # use class name as default namespace for user defined classes
        self.namespace = self.class.to_s.downcase
      end
      data = args.shift
      update(data) if data.kind_of?(Hash)
    end

    def []=(key, value)
      super(convert_key(key), value)
    end
    alias_method :store, :[]=

    def fetch(key, *extras)
      super(convert_key(key),*extras)
    end

    def [](key)
       super convert_key(key)
    end

    def key?(key)
      super convert_key(key)
    end
    alias_method :include?, :key?
    alias_method :has_key?, :key?
    alias_method :member?,  :key?

    def delete(key)
      super convert_key(key)
    end

    def values_at(*indices)
      indices.collect { |key| self[ convert_key(key) ] }
    end

    def key
      @key ||= self.class.generate_key
    end

    def key=(new_key)
      renew_key(new_key)
    end

    attr_writer :version
    def version
      @version ||= self.class.generate_key
    end

    def save( attempt = 0 )
      fail "Unable to save Redis::Hash after max attempts." if attempt > 5
      redis.watch redis_key
      latest_version = redis.hget(redis_key, "__version")
      reload! unless ( latest_version.nil? || latest_version == self.version )
      self.version = nil # generate new version token
      changed_keys = (self.changed + self.added).uniq
      changes = []
      changed_keys.each do |key|
        changes.push( key, Redis::Marshal.dump(self[key]) )
      end
      deleted_keys = self.deleted
      unless deleted_keys.empty? and changes.empty?
        success = redis.multi do
          redis.hmset( redis_key, *changes.push("__version", self.version) ) unless changes.empty?
          deleted_keys.each { |key| redis.hdel( redis_key, key) }
        end
        if success
          untrack!; track! #reset!
        else
          save( attempt + 1 )
        end
      else
        redis.unwatch
      end
    end

    def update(data)
      v = case data
        when self.class
          data.version
        when ::Hash
          data.delete("__version")
        end
      self.version = v unless v.nil?
      super(data.stringify_keys!)
    end

    def reload!
      self.update( self.class.find( {namespace=>key} ) )
    end
    alias_method :reload, :reload!

    def destroy
      redis.del( redis_key )
      untrack!
      clear
      self.key = nil
    end

    def renew_key(new_key = nil)
      unless @key.nil? || @key == new_key
        redis.del( redis_key )
        original.clear
      end
      @key = new_key
      key
    end

    def self.redis
      @@redis ||= Redis.new
    end

    def self.redis=(resource)
      @@redis = resource
    end

    def self.generate_key
      t = Time.now
      t.strftime('%Y%m%d%H%M%S.') + t.usec.to_s.rjust(6,'0') + '.' + SecureRandom.hex(16)
    end

    def self.find(params)<commit_msg>Converted Redis::NativeHash.generate_key to instance method to make it easier to overwrite in subclasses.<commit_after>require 'redis'
require 'core_ext/hash' unless defined?(ActiveSupport)
require 'redis/marshal'
require 'redis/tracked_hash'

if defined?(Rack::Session)
  require "rack/session/abstract/id"
  require 'rack/session/redis_hash'
end

require 'securerandom'

class Redis
  class NativeHash < TrackedHash

    attr_accessor :namespace

    def initialize(*args)
      super(nil)
      track!
      if args.first.kind_of?(String) or args.first.kind_of?(Symbol)
        self.namespace = args.shift
      elsif !self.instance_of?(NativeHash) # use class name as default namespace for user defined classes
        self.namespace = self.class.to_s.downcase
      end
      data = args.shift
      update(data) if data.kind_of?(Hash)
    end

    def []=(key, value)
      super(convert_key(key), value)
    end
    alias_method :store, :[]=

    def fetch(key, *extras)
      super(convert_key(key),*extras)
    end

    def [](key)
       super convert_key(key)
    end

    def key?(key)
      super convert_key(key)
    end
    alias_method :include?, :key?
    alias_method :has_key?, :key?
    alias_method :member?,  :key?

    def delete(key)
      super convert_key(key)
    end

    def values_at(*indices)
      indices.collect { |key| self[ convert_key(key) ] }
    end

    def key
      @key ||= self.class.generate_key
    end

    def key=(new_key)
      renew_key(new_key)
    end

    attr_writer :version
    def version
      @version ||= self.class.generate_key
    end

    def save( attempt = 0 )
      fail "Unable to save Redis::Hash after max attempts." if attempt > 5
      redis.watch redis_key
      latest_version = redis.hget(redis_key, "__version")
      reload! unless ( latest_version.nil? || latest_version == self.version )
      self.version = nil # generate new version token
      changed_keys = (self.changed + self.added).uniq
      changes = []
      changed_keys.each do |key|
        changes.push( key, Redis::Marshal.dump(self[key]) )
      end
      deleted_keys = self.deleted
      unless deleted_keys.empty? and changes.empty?
        success = redis.multi do
          redis.hmset( redis_key, *changes.push("__version", self.version) ) unless changes.empty?
          deleted_keys.each { |key| redis.hdel( redis_key, key) }
        end
        if success
          untrack!; track! #reset!
        else
          save( attempt + 1 )
        end
      else
        redis.unwatch
      end
    end

    def update(data)
      v = case data
        when self.class
          data.version
        when ::Hash
          data.delete("__version")
        end
      self.version = v unless v.nil?
      super(data.stringify_keys!)
    end

    def reload!
      self.update( self.class.find( {namespace=>key} ) )
    end
    alias_method :reload, :reload!

    def destroy
      redis.del( redis_key )
      untrack!
      clear
      self.key = nil
    end

    def renew_key(new_key = nil)
      unless @key.nil? || @key == new_key
        redis.del( redis_key )
        original.clear
      end
      @key = new_key
      key
    end

    def generate_key
      t = Time.now
      t.strftime('%Y%m%d%H%M%S.') + t.usec.to_s.rjust(6,'0') + '.' + SecureRandom.hex(16)
    end

    def self.redis
      @@redis ||= Redis.new
    end

    def self.redis=(resource)
      @@redis = resource
    end

    def self.find(params)
{'fraction_non_alphanumeric': 0.10605397520058352, 'fraction_numerical': 0.0020423048869438365, 'mean_word_length': 2.274116523400191, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 7, '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': '5290930', 'n_tokens_mistral': 2268, 'n_tokens_neox': 2221, 'n_words': 541}