Class: Jetpants::Topology

Inherits:
Object show all
Defined in:
lib/jetpants/topology.rb

Overview

Topology maintains a list of all DB pools/shards, and is responsible for reading/writing configurations and manages spare box assignments. Much of this behavior needs to be overridden by a plugin to actually be useful. The implementation here is just a stub.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeTopology

Returns a new instance of Topology.



10
11
12
13
14
15
# File 'lib/jetpants/topology.rb', line 10

def initialize
  @pools  = [] # array of Pool objects
  # We intentionally don't call load_pools here. The caller must do that.
  # This allows Jetpants module to create Jetpants.topology object, and THEN
  # invoke load_pools, which might then refer back to Jetpants.topology.
end

Instance Attribute Details

#poolsObject (readonly)

Returns the value of attribute pools.



8
9
10
# File 'lib/jetpants/topology.rb', line 8

def pools
  @pools
end

Class Method Details

.method_added(name) ⇒ Object



35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/jetpants/topology.rb', line 35

def method_added(name)
  if @do_sync || @synchronized_methods[name]
    lock = @lock
    @do_sync = false
    @synchronized_methods[name] = false # prevent infinite recursion from the following line
    alias_method "#{name}_without_synchronization".to_sym, name
    define_method name do |*args|
      result = nil
      lock.synchronize {result = send "#{name}_without_synchronization".to_sym, *args}
      result
    end
    @synchronized_methods[name] = true # remember it is synchronized, to re-apply wrapper if method overridden by a plugin
  end
end

.synchronizedObject

Decorator that causes the next method to be wrapped in a mutex (only affects the next method definition, not ALL subsequent method definitions) If the method is subsequently overridden by a plugin, the new version will be synchronized as well, even if the decorator is omitted.



31
32
33
# File 'lib/jetpants/topology.rb', line 31

def synchronized
  @do_sync = true
end

Instance Method Details

#claim_spare(options = {}) ⇒ Object

Nicer inteface into claim_spares when only one DB is desired – returns a single Jetpants::DB object instead of an array.



143
144
145
# File 'lib/jetpants/topology.rb', line 143

def claim_spare(options={})
  claim_spares(1, options)[0]
end

#claim_spares(count, options = {}) ⇒ Object

Plugin should override so that this returns an array of [count] Jetpants::DB objects, or throws an exception if not enough left. Options hash is plugin-specific. The only assumed option used by the rest of Jetpants is :role of ‘MASTER’ or ‘STANDBY_SLAVE’, for grabbing hardware suited for a particular purpose. This can be ignored if your hardware is entirely uniform and/or a burn-in process is already performed on all new hardware intakes.



79
80
81
# File 'lib/jetpants/topology.rb', line 79

def claim_spares(count, options={})
  raise "Plugin must override Topology#claim_spares"
end

#clearObject

Clears the pool list and nukes cached DB and Host object lookup tables



149
150
151
152
153
# File 'lib/jetpants/topology.rb', line 149

def clear
  @pools = []
  DB.clear
  Host.clear
end

#count_spares(options = {}) ⇒ Object

Plugin should override so that this returns a count of spare machines matching the selected options.



86
87
88
# File 'lib/jetpants/topology.rb', line 86

def count_spares(options={})
  raise "Plugin must override Topology#count_spares"
end

#functional_partitionsObject

Returns array of this topology’s Jetpants::Pool objects that are NOT of type Jetpants::Shard



99
100
101
# File 'lib/jetpants/topology.rb', line 99

def functional_partitions
  @pools.reject {|p| p.is_a? Shard}
end

#load_poolsObject

Plugin should override so that this reads in a configuration and initializes



60
61
62
# File 'lib/jetpants/topology.rb', line 60

def load_pools
  puts "\nNotice: no plugin has overridden Topology#load_pools, so no pools are imported automatically"
end

#pool(target) ⇒ Object

Finds and returns a single Jetpants::Pool. Target may be a name (string) or master (DB object).



104
105
106
107
108
109
110
# File 'lib/jetpants/topology.rb', line 104

def pool(target)
  if target.is_a?(DB)
    @pools.select {|p| p.master == target}.first
  else
    @pools.select {|p| p.name == target}.first
  end
end

#refreshObject

Empties and then reloads the pool list



156
157
158
159
160
# File 'lib/jetpants/topology.rb', line 156

def refresh
  clear
  load_pools
  true
end

#shard(*args) ⇒ Object

Finds and returns a single Jetpants::Shard. Pass in one of these:

  • a min ID and a max ID

  • just a min ID

  • a Range object



116
117
118
119
120
121
122
123
124
125
126
127
128
# File 'lib/jetpants/topology.rb', line 116

def shard(*args)
  if args.count == 2 || args[0].is_a?(Array)
    args.flatten!
    args.map! {|x| x.to_s.upcase == 'INFINITY' ? 'INFINITY' : x.to_i}
    shards.select {|s| s.min_id == args[0] && s.max_id == args[1]}.first
  elsif args[0].is_a?(Range)
    shards.select {|s| s.min_id == args[0].min && s.max_id == args[0].max}.first
  else
    result = shards.select {|s| s.min_id == args[0].to_i}
    raise "Multiple shards found with that min_id!" if result.count > 1
    result.first
  end
end

#shard_db_for_id(id, mode = :read) ⇒ Object

Returns the Jetpants::DB that handles the given ID with the specified mode (either :read or :write)



137
138
139
# File 'lib/jetpants/topology.rb', line 137

def shard_db_for_id(id, mode=:read)
  shard_for_id(id).db(mode)
end

#shard_for_id(id) ⇒ Object

Returns the Jetpants::Shard that handles the given ID.



131
132
133
# File 'lib/jetpants/topology.rb', line 131

def shard_for_id(id)
  @shards.select {|s| s.min_id <= id && (s.max_id == 'INFINITY' || s.max_id >= id)}[0]
end

#shardsObject

Returns array of this topology’s Jetpants::Pool objects of type Jetpants::Shard



94
95
96
# File 'lib/jetpants/topology.rb', line 94

def shards
  @pools.select {|p| p.is_a? Shard}
end

#write_configObject

Plugin should override so that it writes a configuration file or commits a configuration change to a config service.



67
68
69
# File 'lib/jetpants/topology.rb', line 67

def write_config
  puts "\nNotice: no plugin has overridden Topology#write_config, so configuration data is not saved"
end