Class: ActiveRecord::Turntable::Cluster

Inherits:
Object
  • Object
show all
Defined in:
lib/active_record/turntable/cluster.rb

Constant Summary collapse

DEFAULT_CONFIG =
{
  "shards" => [],
  "algorithm" => "range",
}.with_indifferent_access

Instance Method Summary collapse

Constructor Details

#initialize(cluster_spec, options = {}) ⇒ Cluster

Returns a new instance of Cluster.



11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/active_record/turntable/cluster.rb', line 11

def initialize(cluster_spec, options = {})
  @config = DEFAULT_CONFIG.merge(cluster_spec)
  @options = options.with_indifferent_access
  @shards = {}.with_indifferent_access

  # setup sequencer
  seq = (@options[:seq] || @config[:seq])
  if seq 
    if seq.values.size > 0 && seq.values.first["seq_type"] == "mysql"
      @seq_shard = SeqShard.new(seq.values.first)
    end
  end

  # setup shards
  @config[:shards].each do |spec|
    @shards[spec["connection"]] ||= Shard.new(spec)
  end

  # setup algorithm
  alg_name = "ActiveRecord::Turntable::Algorithm::#{@config["algorithm"].camelize}Algorithm"
  @algorithm = alg_name.constantize.new(@config)
end

Instance Method Details

#select_shard(key) ⇒ Object



49
50
51
52
# File 'lib/active_record/turntable/cluster.rb', line 49

def select_shard(key)
  ActiveSupport::Deprecation.warn "Cluster#select_shard is deprecated, use shard_for() instead.", caller
  shard_for(key)
end

#seqObject



34
35
36
# File 'lib/active_record/turntable/cluster.rb', line 34

def seq
  @seq_shard
end

#shard_for(key) ⇒ Object



42
43
44
45
46
47
# File 'lib/active_record/turntable/cluster.rb', line 42

def shard_for(key)
  @shards[@algorithm.calculate(key)]
rescue
  raise ActiveRecord::Turntable::CannotSpecifyShardError,
    "cannot select_shard for key:#{key}"
end

#shardsObject



38
39
40
# File 'lib/active_record/turntable/cluster.rb', line 38

def shards
  @shards
end

#shards_transaction(shards = [], options = {}, in_recursion = false, &block) ⇒ Object



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/active_record/turntable/cluster.rb', line 54

def shards_transaction(shards = [], options = {}, in_recursion = false, &block)
  unless in_recursion
    shards = Array.wrap(shards).dup
    if shards.blank?
      shards = @shards.values.dup
    end
  end
  shard = to_shard(shards.shift)
  if shards.present?
    shard.connection.transaction(options) do
      shards_transaction(shards, options, true, &block)
    end
  else
    shard.connection.transaction(options) do
      block.call
    end
  end
end

#to_shard(shard_or_object) ⇒ Object



73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/active_record/turntable/cluster.rb', line 73

def to_shard(shard_or_object)
  case shard_or_object
  when ActiveRecord::Turntable::Shard
    shard_or_object
  when ActiveRecord::Base
    shard_or_object.turntable_shard
  when Numeric, String
    shard_for(shard_or_object)
  when Symbol
    shards[shard_or_object]
  else
    raise ActiveRecord::Turntable::TurntableError,
            "transaction cannot call to object: #{shard_or_object}"
  end
end

#weighted_shards(key = nil) ⇒ Object



89
90
91
92
93
# File 'lib/active_record/turntable/cluster.rb', line 89

def weighted_shards(key = nil)
  Hash[@algorithm.calculate_used_shards_with_weight(key).map do |k,v|
    [@shards[k], v]
  end]
end