Class: SwitchPoint::Proxy

Inherits:
Object
  • Object
show all
Defined in:
lib/switch_point/proxy.rb

Constant Summary collapse

AVAILABLE_MODES =
%i[writable readonly].freeze
DEFAULT_MODE =
:readonly

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name) ⇒ Proxy

Returns a new instance of Proxy.



12
13
14
15
16
17
18
19
20
# File 'lib/switch_point/proxy.rb', line 12

def initialize(name)
  @initial_name = name
  @current_name = name
  AVAILABLE_MODES.each do |mode|
    model = define_model(name, mode)
    memorize_switch_point(name, mode, model.connection_pool)
  end
  @global_mode = DEFAULT_MODE
end

Instance Attribute Details

#initial_nameObject (readonly)

Returns the value of attribute initial_name.



7
8
9
# File 'lib/switch_point/proxy.rb', line 7

def initial_name
  @initial_name
end

Instance Method Details

#cache(&block) ⇒ Object



152
153
154
155
156
# File 'lib/switch_point/proxy.rb', line 152

def cache(&block)
  r = with_readonly { model_for_connection }
  w = with_writable { model_for_connection }
  r.cache { w.cache(&block) }
end

#connected?Boolean

Returns:

  • (Boolean)


148
149
150
# File 'lib/switch_point/proxy.rb', line 148

def connected?
  model_for_connection.connected?
end

#connectionObject



144
145
146
# File 'lib/switch_point/proxy.rb', line 144

def connection
  model_for_connection.connection
end

#define_model(name, mode) ⇒ Object



22
23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/switch_point/proxy.rb', line 22

def define_model(name, mode)
  model_name = SwitchPoint.config.model_name(name, mode)
  if model_name
    model = Class.new(ActiveRecord::Base)
    Proxy.const_set(model_name, model)
    model.establish_connection(SwitchPoint.config.database_name(name, mode))
    model
  elsif mode == :readonly
    # Re-use writable connection
    Proxy.const_get(SwitchPoint.config.model_name(name, :writable))
  else
    ActiveRecord::Base
  end
end

#memorize_switch_point(name, mode, pool) ⇒ Object



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/switch_point/proxy.rb', line 37

def memorize_switch_point(name, mode, pool)
  switch_point = { name: name, mode: mode }
  if pool.equal?(ActiveRecord::Base.connection_pool)
    if mode != :writable
      raise Error.new("ActiveRecord::Base's switch_points must be writable, but #{name} is #{mode}")
    end

    switch_points = pool.spec.config[:switch_points] || []
    switch_points << switch_point
    pool.spec.config[:switch_points] = switch_points
  elsif pool.spec.config.key?(:switch_point)
    # Only :writable is specified
  else
    pool.spec.config[:switch_point] = switch_point
  end
end

#modeObject



63
64
65
# File 'lib/switch_point/proxy.rb', line 63

def mode
  thread_local_mode || @global_mode
end

#model_for_connectionObject



129
130
131
132
133
134
135
136
137
138
139
140
141
142
# File 'lib/switch_point/proxy.rb', line 129

def model_for_connection
  ProxyRepository.checkout(@current_name) # Ensure the target proxy is created
  model_name = SwitchPoint.config.model_name(@current_name, mode)
  if model_name
    Proxy.const_get(model_name)
  elsif mode == :readonly
    # When only writable is specified, re-use writable connection.
    with_writable do
      model_for_connection
    end
  else
    ActiveRecord::Base
  end
end

#readonly!Object



67
68
69
70
71
72
73
# File 'lib/switch_point/proxy.rb', line 67

def readonly!
  if thread_local_mode
    self.thread_local_mode = :readonly
  else
    @global_mode = :readonly
  end
end

#readonly?Boolean

Returns:

  • (Boolean)


75
76
77
# File 'lib/switch_point/proxy.rb', line 75

def readonly?
  mode == :readonly
end

#reset_name!Object



125
126
127
# File 'lib/switch_point/proxy.rb', line 125

def reset_name!
  @current_name = @initial_name
end

#switch_name(new_name, &block) ⇒ Object



111
112
113
114
115
116
117
118
119
120
121
122
123
# File 'lib/switch_point/proxy.rb', line 111

def switch_name(new_name, &block)
  if block
    begin
      old_name = @current_name
      @current_name = new_name
      block.call
    ensure
      @current_name = old_name
    end
  else
    @current_name = new_name
  end
end

#thread_local_modeObject



54
55
56
# File 'lib/switch_point/proxy.rb', line 54

def thread_local_mode
  Thread.current[:"switch_point_#{@current_name}_mode"]
end

#uncached(&block) ⇒ Object



158
159
160
161
162
# File 'lib/switch_point/proxy.rb', line 158

def uncached(&block)
  r = with_readonly { model_for_connection }
  w = with_writable { model_for_connection }
  r.uncached { w.uncached(&block) }
end

#with_mode(new_mode, &block) ⇒ Object



99
100
101
102
103
104
105
106
107
108
109
# File 'lib/switch_point/proxy.rb', line 99

def with_mode(new_mode, &block)
  unless AVAILABLE_MODES.include?(new_mode)
    raise ArgumentError.new("Unknown mode: #{new_mode}")
  end

  saved_mode = thread_local_mode
  self.thread_local_mode = new_mode
  block.call
ensure
  self.thread_local_mode = saved_mode
end

#with_readonly(&block) ⇒ Object



91
92
93
# File 'lib/switch_point/proxy.rb', line 91

def with_readonly(&block)
  with_mode(:readonly, &block)
end

#with_writable(&block) ⇒ Object



95
96
97
# File 'lib/switch_point/proxy.rb', line 95

def with_writable(&block)
  with_mode(:writable, &block)
end

#writable!Object



79
80
81
82
83
84
85
# File 'lib/switch_point/proxy.rb', line 79

def writable!
  if thread_local_mode
    self.thread_local_mode = :writable
  else
    @global_mode = :writable
  end
end

#writable?Boolean

Returns:

  • (Boolean)


87
88
89
# File 'lib/switch_point/proxy.rb', line 87

def writable?
  mode == :writable
end