Class: Patriarch::ToolServices::RedisExtractorService

Inherits:
Service
  • Object
show all
Defined in:
lib/patriarch/tool_services/redis_extractor_service.rb

Overview

Service providing methods that extract information from Redis Database like which entities behaved on me or i behaved on and when without knowing how the internals work. Methods are hence wrapped into sugar when called from models For instance with add_behaviour :like, :on => [:item] embedded in model User we build a tool method called items_i_like_ids that knows how to call #get_ids_from_sorted_set but does not care about internals

Instance Method Summary collapse

Instance Method Details

#get_ids_from_sorted_set(calling_entity, redis_key, options = {}) ⇒ Object

This gets ids stored in a given Redis::SortedSet and returns in an adapted format. Hence it supports various options.

Base options are born from those supported by Redis::SortedSet and allow some sorting on score with options :from and :limit Original options were :from and :to More on this in redis-objects documentation

Bipartite / With scores When storing data in bipartite transactions there is 2 protagonists hence, each protagonist only has on id to remember The output format is thus [id1,id2, …] or [ [id1,score1], [id2,score2], …] if called with option :with_scores

Tripartite / With scores / protagonist type When storing data in tripartite there are 3 protagonists. Each of them needs to know about the 2 others most of the time. We store then triplets built like this : [actor,target,medium]. Triplets are marshalled. We choose which of the protagonist we want to retrieve information about thanks to option :protagonist_type Values can be :actor, :target or :medium The output format is thus [id_protagonist_type1, id_protagonist_type2, …] or [[id_pt1, score1], [id_pt2,score2]] if called with option :with_scores

Sometimes we want to know it all from target or actor point of view we hence call with option :with_medium Option :with_scores is not supported here Output format is thus [=> actor_id1, :target1 => target_id1, :medium1 => medium_id1, …, …]

For more information about redis dao return type, please go on github.com/nateware and visit redis-objects



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/patriarch/tool_services/redis_extractor_service.rb', line 31

def get_ids_from_sorted_set(calling_entity,redis_key,options={})
  from = options[:from] || 0
  limit = options[:limit] || :infinity
  
  if limit == :infinity
    to = -1
  else  
    to = from + limit -1
  end 

  if options[:tripartite]
    dao = Redis::SortedSet.new("#{calling_entity.class.name.underscore}:#{calling_entity.id}:#{redis_key}", :marshal => true)
  else  
    dao = Redis::SortedSet.new("#{calling_entity.class.name.underscore}:#{calling_entity.id}:#{redis_key}")
  end

  if options[:with_scores] 
    # Do not use this anymore, go take the right redis objects not using this kind of methods ...
    ids_with_scores_from_redis = dao.revrange(from,to,:with_scores => true) || []
    result = ids_with_scores_from_redis
  else
    ids_from_redis = dao.revrange(from,to) || []
    result = ids_from_redis      
  end

  if options[:with_medium]
    if options[:with_scores]
      raise Exception, "with_scores options is not supported along with_medium"
    end
    result.map!{ |triplet_id| {:actor => triplet_id[0].to_i, :target => triplet_id[1].to_i, :medium => triplet_id[2].to_i}  }
    return result        
  else 
    if options[:tripartite]
      if options[:with_scores]
        if options[:protagonist_type] == :actor
          result.map!{ |triplet_id_with_score| [triplet_id_with_score.first[0],tuple.last]}
        elsif options[:protagonist_type] == :target
          result.map!{ |triplet_id_with_score| [triplet_id_with_score.first[1],tuple.last]}
        elsif options[:protagonist_type] == :medium
          result.map!{ |triplet_id_with_score| [triplet_id_with_score.first[2],tuple.last]}          
        end
      else
        if options[:protagonist_type] == :actor
          result.map!{ |triplet_id| triplet_id[0] }
        elsif options[:protagonist_type] == :target
          result.map!{ |triplet_id| triplet_id[1] }
        elsif options[:protagonist_type] == :medium
          result.map!{ |triplet_id| triplet_id[2] }          
        end
      end
    end
  end      

  # This sanitizes strings returned by Redis::Objects into integers.
  result.map! do |x| 
    if x.is_a? Array
      x[0].to_i
      x
      # FIXME Bullshit détecté ici
    else 
      x.to_i
    end
  end
  result
end

#get_models_from_ids(calling_entity, model, get_id_method, options = {}) ⇒ Object

Tool method allowing to instantiate models from ids we find with method #get_ids_from_sorted_sets



98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/patriarch/tool_services/redis_extractor_service.rb', line 98

def get_models_from_ids(calling_entity,model,get_id_method,options={})        
  if options[:with_medium]
    id_hash_from_redis = calling_entity.send(get_id_method,options)
    return id_hash_from_redis
  end

  if options[:with_scores] 
    ids_with_scores_from_redis = calling_entity.send(get_id_method,options)
    ids_with_scores_from_redis.map! do |id,score|
      [model.find(id),score]
    end
  else
    ids_from_redis = calling_entity.send(get_id_method,options)
    model.find(ids_from_redis)
  end
end