switch_connection 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +26 -0
- data/.hound.yml +3 -0
- data/.rspec +2 -0
- data/.rubocop.yml +63 -0
- data/.rubocop_todo.yml +2 -0
- data/.ruby-version +1 -0
- data/.travis.yml +22 -0
- data/Appraisals +66 -0
- data/CHANGELOG.md +73 -0
- data/Gemfile +7 -0
- data/LICENSE.txt +22 -0
- data/README.md +143 -0
- data/Rakefile +16 -0
- data/assets/switch_point.svg +2 -0
- data/benchmark/proxy.rb +71 -0
- data/gemfiles/rails_3.2.gemfile +8 -0
- data/gemfiles/rails_4.0.gemfile +8 -0
- data/gemfiles/rails_4.1.gemfile +8 -0
- data/gemfiles/rails_4.2.gemfile +9 -0
- data/gemfiles/rails_5.0.gemfile +9 -0
- data/gemfiles/rails_5.1.gemfile +8 -0
- data/gemfiles/rails_5.2.gemfile +9 -0
- data/gemfiles/rails_edge.gemfile +9 -0
- data/lib/switch_connection.rb +66 -0
- data/lib/switch_connection/config.rb +94 -0
- data/lib/switch_connection/error.rb +12 -0
- data/lib/switch_connection/model.rb +144 -0
- data/lib/switch_connection/proxy.rb +165 -0
- data/lib/switch_connection/proxy_repository.rb +30 -0
- data/lib/switch_connection/version.rb +5 -0
- data/spec/models.rb +141 -0
- data/spec/spec_helper.rb +91 -0
- data/spec/switch_connection/model_spec.rb +402 -0
- data/spec/switch_connection_spec.rb +108 -0
- data/switch_connection.gemspec +36 -0
- metadata +265 -0
data/Rakefile
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bundler/gem_tasks'
|
4
|
+
|
5
|
+
task :default => %i[spec rubocop]
|
6
|
+
|
7
|
+
require 'rspec/core/rake_task'
|
8
|
+
RSpec::Core::RakeTask.new(:spec)
|
9
|
+
|
10
|
+
require 'rubocop/rake_task'
|
11
|
+
RuboCop::RakeTask.new(:rubocop)
|
12
|
+
|
13
|
+
desc 'Run benchmark'
|
14
|
+
task :benchmark do
|
15
|
+
sh 'ruby', 'benchmark/proxy.rb'
|
16
|
+
end
|
@@ -0,0 +1,2 @@
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
2
|
+
<svg contentScriptType="text/ecmascript" xmlns:xlink="http://www.w3.org/1999/xlink" zoomAndPan="magnify" contentStyleType="text/css" viewBox="74.0 85.0 534.0 434.1035" xmlns:cacoo="http://cacoo.com/" preserveAspectRatio="xMidYMin meet" xmlns="http://www.w3.org/2000/svg" version="1.1"><defs><marker refX="14.0" refY="7.0" markerUnits="userSpaceOnUse" orient="auto" id="id4" markerHeight="14.0" viewBox="0 0 14.0 14.0" preserveAspectRatio="xMidYMid meet" markerWidth="14.0" overflow="visible"><path fill="none" d="M0 0 L14.0 7.0 L0 14.0" stroke-width="2.0" stroke-linejoin="round" stroke-linecap="round" stroke="#e33933"/></marker><marker refX="14.0" refY="7.0" markerUnits="userSpaceOnUse" orient="auto" id="id5" markerHeight="14.0" viewBox="0 0 14.0 14.0" preserveAspectRatio="xMidYMid meet" markerWidth="14.0" overflow="visible"><path fill="none" d="M0 0 L14.0 7.0 L0 14.0" stroke-width="2.0" stroke-linejoin="round" stroke-linecap="round" stroke="#e33933"/></marker><marker refX="14.0" refY="7.0" markerUnits="userSpaceOnUse" orient="auto" id="id6" markerHeight="14.0" viewBox="0 0 14.0 14.0" preserveAspectRatio="xMidYMid meet" markerWidth="14.0" overflow="visible"><path fill="none" d="M0 0 L14.0 7.0 L0 14.0" stroke-width="2.0" stroke-linejoin="round" stroke-linecap="round" stroke="#97d077"/></marker><marker refX="14.0" refY="7.0" markerUnits="userSpaceOnUse" orient="auto" id="id7" markerHeight="14.0" viewBox="0 0 14.0 14.0" preserveAspectRatio="xMidYMid meet" markerWidth="14.0" overflow="visible"><path fill="none" d="M0 0 L14.0 7.0 L0 14.0" stroke-width="2.0" stroke-linejoin="round" stroke-linecap="round" stroke="#97d077"/></marker><marker refX="14.0" refY="7.0" markerUnits="userSpaceOnUse" orient="auto" id="id15" markerHeight="14.0" viewBox="0 0 14.0 14.0" preserveAspectRatio="xMidYMid meet" markerWidth="14.0" overflow="visible"><path fill="none" d="M0 0 L14.0 7.0 L0 14.0" stroke-width="2.0" stroke-linejoin="round" stroke-linecap="round" stroke="#000000"/></marker><marker refX="14.0" refY="7.0" markerUnits="userSpaceOnUse" orient="auto" id="id16" markerHeight="14.0" viewBox="0 0 14.0 14.0" preserveAspectRatio="xMidYMid meet" markerWidth="14.0" overflow="visible"><path fill="none" d="M0 0 L14.0 7.0 L0 14.0" stroke-width="2.0" stroke-linejoin="round" stroke-linecap="round" stroke="#000000"/></marker><marker refX="14.0" refY="7.0" markerUnits="userSpaceOnUse" orient="auto" id="id17" markerHeight="14.0" viewBox="0 0 14.0 14.0" preserveAspectRatio="xMidYMid meet" markerWidth="14.0" overflow="visible"><path fill="none" d="M0 0 L14.0 7.0 L0 14.0" stroke-width="2.0" stroke-linejoin="round" stroke-linecap="round" stroke="#000000"/></marker><marker refX="14.0" refY="7.0" markerUnits="userSpaceOnUse" orient="auto" id="id26" markerHeight="14.0" viewBox="0 0 14.0 14.0" preserveAspectRatio="xMidYMid meet" markerWidth="14.0" overflow="visible"><path fill="none" d="M0 0 L14.0 7.0 L0 14.0" stroke-width="2.0" stroke-linejoin="round" stroke-linecap="round" stroke="#000000"/></marker><marker refX="14.0" refY="7.0" markerUnits="userSpaceOnUse" orient="auto" id="id27" markerHeight="14.0" viewBox="0 0 14.0 14.0" preserveAspectRatio="xMidYMid meet" markerWidth="14.0" overflow="visible"><path fill="none" d="M0 0 L14.0 7.0 L0 14.0" stroke-width="2.0" stroke-linejoin="round" stroke-linecap="round" stroke="#e33933"/></marker><marker refX="14.0" refY="7.0" markerUnits="userSpaceOnUse" orient="auto" id="id28" markerHeight="14.0" viewBox="0 0 14.0 14.0" preserveAspectRatio="xMidYMid meet" markerWidth="14.0" overflow="visible"><path fill="none" d="M0 0 L14.0 7.0 L0 14.0" stroke-width="2.0" stroke-linejoin="round" stroke-linecap="round" stroke="#74c14a"/></marker></defs><g><g transform="translate(529.0 140.8965)"><path fill="#ffffff" fill-opacity="1.0" d="M0.0 6.0 L64.00000000000006 6.0 L64.00000000000006 52.5 Q64.00000000000006 54.98528137423857 54.62741699796954 56.742640687119284 Q45.25483399593911 58.5 32.00000000000002 58.5 Q18.745166004060973 58.5 9.372583002030485 56.742640687119284 Q0.0 54.98528137423857 0.0 52.5 L0.0 6.0z" stroke-width="1.0" stroke-linejoin="round" stroke="#000000"/><path fill="#ffffff" fill-opacity="1.0" d="M64.00000000000006 6.0 Q64.00000000000006 8.485281374238571 54.62741699796954 10.242640687119284 Q45.25483399593911 11.999999999999998 32.00000000000003 12.0 Q18.745166004060973 12.0 9.372583002030488 10.242640687119286 Q0.0 8.485281374238571 0.0 6.000000000000001 Q0.0 3.5147186257614313 9.372583002030485 1.7573593128807152 Q18.745166004060973 8.881784197001252E-16 32.00000000000002 0.0 Q45.25483399593911 -8.881784197001252E-16 54.62741699796954 1.7573593128807143 Q64.00000000000006 3.5147186257614287 64.00000000000006 6.0z" stroke-width="1.0" stroke-linejoin="round" stroke="#000000"/><g transform="translate(0.0 12.0)"><clipPath id="id0"><path d="M0 0 L64.0 0 L64.0 46.5 L0 46.5z"/></clipPath><text font-size="12" clip-path="url(#id0)" text-decoration="none" fill="#000000" font-family="Arial,Arial" font-style="normal" font-weight="normal"><tspan x="18.0" xml:space="preserve" y="19.25" textLength="28.0">main</tspan><tspan x="11.0" xml:space="preserve" y="36.25" textLength="41.0">master</tspan></text></g></g><g transform="translate(529.0 376.8965)"><path fill="#ffffff" fill-opacity="1.0" d="M0.0 6.0 L63.99999999999992 6.0 L63.99999999999992 52.5 Q63.99999999999992 54.98528137423857 54.62741699796942 56.742640687119284 Q45.25483399593904 58.5 31.999999999999932 58.5 Q18.745166004060934 58.5 9.372583002030463 56.742640687119284 Q0.0 54.98528137423857 0.0 52.5 L0.0 6.0z" stroke-width="1.0" stroke-linejoin="round" stroke="#000000"/><path fill="#ffffff" fill-opacity="1.0" d="M63.99999999999992 6.0 Q63.99999999999992 8.485281374238571 54.62741699796942 10.242640687119284 Q45.25483399593904 11.999999999999998 31.99999999999996 12.0 Q18.74516600406094 12.0 9.37258300203047 10.242640687119286 Q0.0 8.485281374238571 0.0 6.000000000000001 Q0.0 3.5147186257614313 9.372583002030463 1.7573593128807152 Q18.745166004060934 8.881784197001252E-16 31.999999999999932 0.0 Q45.25483399593904 -8.881784197001252E-16 54.62741699796942 1.7573593128807143 Q63.99999999999992 3.5147186257614287 63.99999999999992 6.0z" stroke-width="1.0" stroke-linejoin="round" stroke="#000000"/><g transform="translate(0.0 12.0)"><clipPath id="id1"><path d="M0 0 L64.0 0 L64.0 46.5 L0 46.5z"/></clipPath><text font-size="12" clip-path="url(#id1)" text-decoration="none" fill="#000000" font-family="Arial,Arial" font-style="normal" font-weight="normal"><tspan x="5.0" xml:space="preserve" y="19.25" textLength="46.0">comment</tspan><tspan x="11.0" xml:space="preserve" y="36.25" textLength="41.0">master</tspan></text></g></g><g transform="translate(293.5289580126552 170.1465)"><path fill="#ffffff" fill-opacity="1.0" d="M51.74956447969533 68.4248898947933 L0.424969148024419 34.35350099488455 L51.74956447969533 0.28211209497580036 L103.07415981136624 34.35350099488455 L51.74956447969533 68.4248898947933 L51.74956447969533 68.4248898947933z" stroke-width="1.0" stroke-linejoin="round" stroke="#000000"/><g transform="translate(20.199307221852635 21.163783014064215)"><clipPath id="id2"><path d="M0 0 L62.58726465655704 0 L62.58726465655704 26.463928188151897 L0 26.463928188151897z"/></clipPath><text font-size="12" clip-path="url(#id2)" text-decoration="none" fill="#000000" font-family="Arial,Arial" font-style="normal" font-weight="normal"><tspan x="17.0" xml:space="preserve" y="17.73196409407595" textLength="28.0">main</tspan></text></g></g><g transform="translate(293.5289580126552 406.1465)"><path fill="#ffffff" fill-opacity="1.0" d="M51.381583974689526 68.70699999999998 L7.148564543362447E-16 34.35349999999998 L51.381583974689526 -5.911707234851347E-15 L102.76316794937905 34.35349999999998 L51.381583974689526 68.70699999999998 L51.381583974689526 68.70699999999998z" stroke-width="1.0" stroke-linejoin="round" stroke="#000000"/><g transform="translate(19.79629465597243 21.054571154298447)"><clipPath id="id3"><path d="M0 0 L62.65675888753867 0 L62.65675888753867 26.683049513549793 L0 26.683049513549793z"/></clipPath><text font-size="12" clip-path="url(#id3)" text-decoration="none" fill="#000000" font-family="Arial,Arial" font-style="normal" font-weight="normal"><tspan x="5.0" xml:space="preserve" y="17.841524756774895" textLength="53.0">comment</tspan></text></g></g><path fill="none" marker-end="url(#id4)" d="M370.94082015818594 187.46430654493017 L529.0 170.1465" stroke-width="2.0" stroke-linejoin="round" stroke="#e33933"/><path fill="none" marker-end="url(#id5)" d="M370.6013339746895 423.32325 L529.0 406.1465" stroke-width="2.0" stroke-linejoin="round" stroke="#e33933"/><path fill="none" marker-end="url(#id6)" d="M370.6013339746895 457.67674999999997 L529.0 474.8535" stroke-width="2.0" stroke-linejoin="round" stroke="#97d077"/><path fill="none" marker-end="url(#id7)" d="M370.94082015818594 221.53569544483895 L529.0 233.75752170027454" stroke-width="2.0" stroke-linejoin="round" stroke="#97d077"/><g transform="translate(389.0 160.1465)"><clipPath id="id8"><path d="M0 0 L58.0 0 L58.0 20.0 L0 20.0z"/></clipPath><text font-size="12" clip-path="url(#id8)" text-decoration="none" fill="#000000" font-family="Arial,Arial" font-style="normal" font-weight="normal"><tspan x="2.0" xml:space="preserve" y="15.0" textLength="50.0">writable</tspan></text></g><g transform="translate(389.0 225.3535)"><clipPath id="id9"><path d="M0 0 L58.0 0 L58.0 27.0 L0 27.0z"/></clipPath><text font-size="12" clip-path="url(#id9)" text-decoration="none" fill="#000000" font-family="Arial,Arial" font-style="normal" font-weight="normal"><tspan x="2.0" xml:space="preserve" y="15.0" textLength="51.0">readonly</tspan></text></g><g transform="translate(389.0 396.1465)"><clipPath id="id10"><path d="M0 0 L58.0 0 L58.0 20.0 L0 20.0z"/></clipPath><text font-size="12" clip-path="url(#id10)" text-decoration="none" fill="#000000" font-family="Arial,Arial" font-style="normal" font-weight="normal"><tspan x="2.0" xml:space="preserve" y="15.0" textLength="50.0">writable</tspan></text></g><g transform="translate(389.0 461.3535)"><clipPath id="id11"><path d="M0 0 L58.0 0 L58.0 27.0 L0 27.0z"/></clipPath><text font-size="12" clip-path="url(#id11)" text-decoration="none" fill="#000000" font-family="Arial,Arial" font-style="normal" font-weight="normal"><tspan x="2.0" xml:space="preserve" y="15.0" textLength="51.0">readonly</tspan></text></g><g transform="translate(116.5 213.8535)"><path fill="#ffffff" fill-opacity="1.0" d="M115.00000000000001 25.0 Q115.00000000000001 35.354843 98.15939999999996 42.67725 Q81.31799499999998 50.0 57.50000000000001 50.0 Q33.68292499999999 50.0 16.841465489999997 42.677624 Q0.0 35.35525 0.0 25.0 Q0.0 14.64475 16.841463189999995 7.3223763 Q33.68292499999999 0.0 57.50000000000001 0.0 Q81.31840209999994 0.0 98.15939999999996 7.3223753 Q115.00000000000001 14.644578 115.00000000000001 25.0 L115.00000000000001 25.0z" stroke-width="1.0" stroke-linejoin="round" stroke="#000000"/><g transform="translate(15.920599842071528 7.961000442504883)"><clipPath id="id12"><path d="M0 0 L83.16799964904784 0 L83.16799964904784 33.847999572753906 L0 33.847999572753906z"/></clipPath><text font-size="12" clip-path="url(#id12)" text-decoration="none" fill="#000000" font-family="Arial,Arial" font-style="normal" font-weight="normal"><tspan x="14.0" xml:space="preserve" y="21.423999786376953" textLength="54.0">Publisher</tspan></text></g></g><g transform="translate(116.5 145.1465)"><path fill="#ffffff" fill-opacity="1.0" d="M115.00000000000001 25.0 Q115.00000000000001 35.354843 98.15939999999996 42.67725 Q81.31799499999998 50.0 57.50000000000001 50.0 Q33.68292499999999 50.0 16.841465489999997 42.677624 Q0.0 35.35525 0.0 25.0 Q0.0 14.64475 16.841463189999995 7.3223763 Q33.68292499999999 0.0 57.50000000000001 0.0 Q81.31840209999994 0.0 98.15939999999996 7.3223753 Q115.00000000000001 14.644578 115.00000000000001 25.0 L115.00000000000001 25.0z" stroke-width="1.0" stroke-linejoin="round" stroke="#000000"/><g transform="translate(15.920599842071528 7.961000442504883)"><clipPath id="id13"><path d="M0 0 L83.16799964904784 0 L83.16799964904784 33.847999572753906 L0 33.847999572753906z"/></clipPath><text font-size="12" clip-path="url(#id13)" text-decoration="none" fill="#000000" font-family="Arial,Arial" font-style="normal" font-weight="normal"><tspan x="27.0" xml:space="preserve" y="21.423999786376953" textLength="28.0">Book</tspan></text></g></g><g transform="translate(116.5 415.5)"><path fill="#ffffff" fill-opacity="1.0" d="M115.00000000000001 25.0 Q115.00000000000001 35.354843 98.15939999999996 42.67725 Q81.31799499999998 50.0 57.50000000000001 50.0 Q33.68292499999999 50.0 16.841465489999997 42.677624 Q0.0 35.35525 0.0 25.0 Q0.0 14.64475 16.841463189999995 7.3223763 Q33.68292499999999 0.0 57.50000000000001 0.0 Q81.31840209999994 0.0 98.15939999999996 7.3223753 Q115.00000000000001 14.644578 115.00000000000001 25.0 L115.00000000000001 25.0z" stroke-width="1.0" stroke-linejoin="round" stroke="#000000"/><g transform="translate(14.920599842071528 7.961000442504883)"><clipPath id="id14"><path d="M0 0 L83.16799964904784 0 L83.16799964904784 33.847999572753906 L0 33.847999572753906z"/></clipPath><text font-size="12" clip-path="url(#id14)" text-decoration="none" fill="#000000" font-family="Arial,Arial" font-style="normal" font-weight="normal"><tspan x="14.0" xml:space="preserve" y="21.423999786376953" textLength="55.0">Comment</tspan></text></g></g><path fill="none" stroke-linejoin="round" stroke-dasharray="6.0 2.0" d="M231.5 170.1465 L319.61622482651507 187.46430654493017" stroke="#000000" stroke-width="2.0" marker-end="url(#id15)"/><path fill="none" stroke-linejoin="round" stroke-dasharray="6.0 2.0" d="M231.5 238.8535 L319.61622482651507 221.53569544483895" stroke="#000000" stroke-width="2.0" marker-end="url(#id16)"/><path fill="none" stroke-linejoin="round" stroke-dasharray="6.0 2.0" d="M231.5 440.5 L293.5289580126552 440.5" stroke="#000000" stroke-width="2.0" marker-end="url(#id17)"/><g transform="translate(89.0 100.0)"><clipPath id="id18"><path d="M0 0 L176.0 0 L176.0 20.0 L0 20.0z"/></clipPath><text font-size="12" clip-path="url(#id18)" text-decoration="none" fill="#000000" font-family="Arial,Arial" font-style="normal" font-weight="bold"><tspan x="2.0" xml:space="preserve" y="15.0" textLength="169.0">Model < ActiveRecord::Base</tspan></text></g><g transform="translate(322.91054198734474 100.0)"><clipPath id="id19"><path d="M0 0 L44.0 0 L44.0 20.0 L0 20.0z"/></clipPath><text font-size="12" clip-path="url(#id19)" text-decoration="none" fill="#000000" font-family="Arial,Arial" font-style="normal" font-weight="bold"><tspan x="2.0" xml:space="preserve" y="15.0" textLength="35.0">Proxy</tspan></text></g><g transform="translate(116.5 299.1465)"><path fill="#ffffff" fill-opacity="1.0" d="M115.00000000000001 25.0 Q115.00000000000001 35.354843 98.15940000000002 42.67725 Q81.31799500000004 50.0 57.50000000000001 50.0 Q33.68292500000001 50.0 16.84146549 42.677624 Q0.0 35.35525 0.0 25.0 Q0.0 14.64475 16.84146319000001 7.3223763 Q33.68292500000001 0.0 57.50000000000001 0.0 Q81.31840210000003 0.0 98.15940000000002 7.3223753 Q115.00000000000001 14.644578 115.00000000000001 25.0 L115.00000000000001 25.0z" stroke-width="1.0" stroke-linejoin="round" stroke="#000000"/><g transform="translate(14.92059984207154 7.961000442504883)"><clipPath id="id20"><path d="M0 0 L83.16799964904786 0 L83.16799964904786 33.847999572753906 L0 33.847999572753906z"/></clipPath><text font-size="12" clip-path="url(#id20)" text-decoration="none" fill="#000000" font-family="Arial,Arial" font-style="normal" font-weight="normal"><tspan x="18.0" xml:space="preserve" y="21.423999786376953" textLength="46.0">BigData</tspan></text></g></g><g transform="translate(293.95090530472953 290.0751120949758)"><path fill="#ffffff" fill-opacity="1.0" d="M50.95963817063662 68.14277779981754 L-1.5432100042289676E-14 34.071388899908776 L50.95963817063662 1.3489209749195652E-14 L101.91927634127326 34.071388899908776 L50.95963817063662 68.14277779981754 L50.95963817063662 68.14277779981754z" stroke-width="1.0" stroke-linejoin="round" stroke="#000000"/><g transform="translate(19.633727393157077 20.881670919088414)"><clipPath id="id21"><path d="M0 0 L62.14222129521437 0 L62.14222129521437 26.463928188151918 L0 26.463928188151918z"/></clipPath><text font-size="12" clip-path="url(#id21)" text-decoration="none" fill="#000000" font-family="Arial,Arial" font-style="normal" font-weight="normal"><tspan x="10.0" xml:space="preserve" y="17.73196409407596" textLength="41.0">special</tspan></text></g></g><g transform="translate(529.0 294.89650099488455)"><path fill="#ffffff" fill-opacity="1.0" d="M0.0 6.0 L63.99999999999999 6.0 L63.99999999999999 52.5 Q63.99999999999999 54.98528137423857 54.6274169979695 56.742640687119284 Q45.254833995939045 58.5 31.999999999999975 58.5 Q18.74516600406095 58.5 9.37258300203047 56.742640687119284 Q0.0 54.98528137423857 0.0 52.5 L0.0 6.0z" stroke-width="1.0" stroke-linejoin="round" stroke="#000000"/><path fill="#ffffff" fill-opacity="1.0" d="M63.99999999999999 6.0 Q63.99999999999999 8.485281374238571 54.6274169979695 10.242640687119284 Q45.254833995939045 11.999999999999998 31.999999999999996 12.0 Q18.745166004060952 12.0 9.37258300203048 10.242640687119286 Q0.0 8.485281374238571 0.0 6.000000000000001 Q0.0 3.5147186257614313 9.37258300203047 1.7573593128807152 Q18.74516600406095 8.881784197001252E-16 31.999999999999975 0.0 Q45.254833995939045 -8.881784197001252E-16 54.6274169979695 1.7573593128807143 Q63.99999999999999 3.5147186257614287 63.99999999999999 6.0z" stroke-width="1.0" stroke-linejoin="round" stroke="#000000"/><g transform="translate(0.0 12.0)"><clipPath id="id22"><path d="M0 0 L64.0 0 L64.0 46.5 L0 46.5z"/></clipPath><text font-size="12" clip-path="url(#id22)" text-decoration="none" fill="#000000" font-family="Arial,Arial" font-style="normal" font-weight="normal"><tspan x="18.0" xml:space="preserve" y="10.75" textLength="28.0">main</tspan><tspan x="11.0" xml:space="preserve" y="27.75" textLength="41.0">special</tspan><tspan x="16.0" xml:space="preserve" y="44.75" textLength="31.0">slave</tspan></text></g></g><g transform="translate(529.0 209.6035)"><path fill="#ffffff" fill-opacity="1.0" d="M0.0 6.0 L64.00000000000006 6.0 L64.00000000000006 52.5 Q64.00000000000006 54.98528137423857 54.62741699796954 56.742640687119284 Q45.25483399593911 58.5 32.00000000000002 58.5 Q18.745166004060973 58.5 9.372583002030485 56.742640687119284 Q0.0 54.98528137423857 0.0 52.5 L0.0 6.0z" stroke-width="1.0" stroke-linejoin="round" stroke="#000000"/><path fill="#ffffff" fill-opacity="1.0" d="M64.00000000000006 6.0 Q64.00000000000006 8.485281374238571 54.62741699796954 10.242640687119284 Q45.25483399593911 11.999999999999998 32.00000000000003 12.0 Q18.745166004060973 12.0 9.372583002030488 10.242640687119286 Q0.0 8.485281374238571 0.0 6.000000000000001 Q0.0 3.5147186257614313 9.372583002030485 1.7573593128807152 Q18.745166004060973 8.881784197001252E-16 32.00000000000002 0.0 Q45.25483399593911 -8.881784197001252E-16 54.62741699796954 1.7573593128807143 Q64.00000000000006 3.5147186257614287 64.00000000000006 6.0z" stroke-width="1.0" stroke-linejoin="round" stroke="#000000"/><g transform="translate(0.0 12.0)"><clipPath id="id23"><path d="M0 0 L64.0 0 L64.0 46.5 L0 46.5z"/></clipPath><text font-size="12" clip-path="url(#id23)" text-decoration="none" fill="#000000" font-family="Arial,Arial" font-style="normal" font-weight="normal"><tspan x="18.0" xml:space="preserve" y="19.25" textLength="28.0">main</tspan><tspan x="16.0" xml:space="preserve" y="36.25" textLength="31.0">slave</tspan></text></g></g><g transform="translate(529.0 445.6035)"><path fill="#ffffff" fill-opacity="1.0" d="M0.0 6.0 L64.00000000000006 6.0 L64.00000000000006 52.5 Q64.00000000000006 54.98528137423857 54.62741699796954 56.742640687119284 Q45.25483399593911 58.5 32.00000000000002 58.5 Q18.745166004060973 58.5 9.372583002030485 56.742640687119284 Q0.0 54.98528137423857 0.0 52.5 L0.0 6.0z" stroke-width="1.0" stroke-linejoin="round" stroke="#000000"/><path fill="#ffffff" fill-opacity="1.0" d="M64.00000000000006 6.0 Q64.00000000000006 8.485281374238571 54.62741699796954 10.242640687119284 Q45.25483399593911 11.999999999999998 32.00000000000003 12.0 Q18.745166004060973 12.0 9.372583002030488 10.242640687119286 Q0.0 8.485281374238571 0.0 6.000000000000001 Q0.0 3.5147186257614313 9.372583002030485 1.7573593128807152 Q18.745166004060973 8.881784197001252E-16 32.00000000000002 0.0 Q45.25483399593911 -8.881784197001252E-16 54.62741699796954 1.7573593128807143 Q64.00000000000006 3.5147186257614287 64.00000000000006 6.0z" stroke-width="1.0" stroke-linejoin="round" stroke="#000000"/><g transform="translate(0.0 12.0)"><clipPath id="id24"><path d="M0 0 L64.0 0 L64.0 46.5 L0 46.5z"/></clipPath><text font-size="12" clip-path="url(#id24)" text-decoration="none" fill="#000000" font-family="Arial,Arial" font-style="normal" font-weight="normal"><tspan x="5.0" xml:space="preserve" y="19.25" textLength="53.0">comment</tspan><tspan x="16.0" xml:space="preserve" y="36.25" textLength="31.0">slave</tspan></text></g></g><g transform="translate(529.0 100.0)"><clipPath id="id25"><path d="M0 0 L64.0 0 L64.0 20.0 L0 20.0z"/></clipPath><text font-size="12" clip-path="url(#id25)" text-decoration="none" fill="#000000" font-family="Arial,Arial" font-style="normal" font-weight="bold"><tspan x="2.0" xml:space="preserve" y="15.0" textLength="55.0">Database</tspan></text></g><path fill="none" stroke-linejoin="round" stroke-dasharray="6.0 2.0" d="M231.5 324.1465 L293.95090530472953 324.14650099488455" stroke="#000000" stroke-width="2.0" marker-end="url(#id26)"/><path fill="none" marker-end="url(#id27)" d="M370.3903625606845 307.1108065449302 L529.0 184.77149999999997" stroke-width="2.0" stroke-linejoin="round" stroke="#e33933"/><path fill="none" marker-end="url(#id28)" d="M370.3903625606845 341.18219544483895 L529.0 324.14650099488455" stroke-width="2.0" stroke-linejoin="round" stroke="#74c14a"/><g transform="translate(389.0 344.7178898947933)"><clipPath id="id29"><path d="M0 0 L58.0 0 L58.0 27.0 L0 27.0z"/></clipPath><text font-size="12" clip-path="url(#id29)" text-decoration="none" fill="#000000" font-family="Arial,Arial" font-style="normal" font-weight="normal"><tspan x="2.0" xml:space="preserve" y="15.0" textLength="51.0">readonly</tspan></text></g><g transform="translate(395.87018164600283 280.0751120949758)"><clipPath id="id30"><path d="M0 0 L58.0 0 L58.0 20.0 L0 20.0z"/></clipPath><text font-size="12" clip-path="url(#id30)" text-decoration="none" fill="#000000" font-family="Arial,Arial" font-style="normal" font-weight="normal"><tspan x="2.0" xml:space="preserve" y="15.0" textLength="50.0">writable</tspan></text></g></g></svg>
|
data/benchmark/proxy.rb
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'benchmark/ips'
|
4
|
+
require 'switch_connection'
|
5
|
+
require 'active_record'
|
6
|
+
SwitchConnection.configure do |config|
|
7
|
+
config.define_switch_point :proxy,
|
8
|
+
slaves: [:proxy_slave],
|
9
|
+
master: :proxy_master
|
10
|
+
end
|
11
|
+
ENV['RAILS_ENV'] ||= 'test'
|
12
|
+
class Plain < ActiveRecord::Base
|
13
|
+
end
|
14
|
+
|
15
|
+
class Proxy1 < ActiveRecord::Base
|
16
|
+
use_switch_point :proxy
|
17
|
+
end
|
18
|
+
|
19
|
+
class ProxyBase < ActiveRecord::Base
|
20
|
+
self.abstract_class = true
|
21
|
+
use_switch_point :proxy
|
22
|
+
end
|
23
|
+
|
24
|
+
class Proxy2 < ProxyBase
|
25
|
+
end
|
26
|
+
|
27
|
+
database_config = { adapter: 'sqlite3', database: ':memory:' }
|
28
|
+
databases = {
|
29
|
+
test: {
|
30
|
+
'default' => database_config.dup,
|
31
|
+
'proxy_slave' => database_config.dup,
|
32
|
+
'proxy_master' => database_config.dup
|
33
|
+
}
|
34
|
+
}
|
35
|
+
|
36
|
+
ActiveRecord::Base.configurations =
|
37
|
+
# ActiveRecord.gem_version was introduced in ActiveRecord 4.0
|
38
|
+
if ActiveRecord.respond_to?(:gem_version) && ActiveRecord.gem_version >= Gem::Version.new('5.1.0')
|
39
|
+
{ 'test' => databases }
|
40
|
+
else
|
41
|
+
databases
|
42
|
+
end
|
43
|
+
ActiveRecord::Base.establish_connection(ActiveRecord::Base.configurations[SwitchConnection.config.env]['default'])
|
44
|
+
|
45
|
+
Plain.connection.execute('CREATE TABLE plains (id integer primary key autoincrement)')
|
46
|
+
%i[slave master].each do |mode|
|
47
|
+
ProxyBase.public_send("with_#{mode}") do
|
48
|
+
%w[proxy1s proxy2s].each do |table|
|
49
|
+
ProxyBase.connection.execute("CREATE TABLE #{table} (id integer primary key autoincrement)")
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
Benchmark.ips do |x|
|
55
|
+
x.report('plain') do
|
56
|
+
Plain.create
|
57
|
+
Plain.first
|
58
|
+
end
|
59
|
+
|
60
|
+
x.report('proxy1') do
|
61
|
+
Proxy1.with_master { Proxy1.create }
|
62
|
+
Proxy1.first
|
63
|
+
end
|
64
|
+
|
65
|
+
x.report('proxy2') do
|
66
|
+
Proxy2.with_master { Proxy2.create }
|
67
|
+
Proxy2.first
|
68
|
+
end
|
69
|
+
|
70
|
+
x.compare!
|
71
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'active_support/lazy_load_hooks'
|
4
|
+
require 'switch_connection/config'
|
5
|
+
require 'switch_connection/version'
|
6
|
+
require 'log_connection_name'
|
7
|
+
module SwitchConnection
|
8
|
+
module ClassMethods
|
9
|
+
def configure(&block)
|
10
|
+
block.call(config)
|
11
|
+
end
|
12
|
+
|
13
|
+
def config
|
14
|
+
@config ||= Config.new
|
15
|
+
end
|
16
|
+
|
17
|
+
def slave_all!
|
18
|
+
config.each_key do |name|
|
19
|
+
slave!(name)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def slave!(name)
|
24
|
+
ProxyRepository.checkout(name).slave!
|
25
|
+
end
|
26
|
+
|
27
|
+
def master_all!
|
28
|
+
config.each_key do |name|
|
29
|
+
master!(name)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def master!(name)
|
34
|
+
ProxyRepository.checkout(name).master!
|
35
|
+
end
|
36
|
+
|
37
|
+
def with_slave(*names, &block)
|
38
|
+
with_mode(:slave, *names, &block)
|
39
|
+
end
|
40
|
+
|
41
|
+
def with_slave_all(&block)
|
42
|
+
with_slave(*config.keys, &block)
|
43
|
+
end
|
44
|
+
|
45
|
+
def with_master(*names, &block)
|
46
|
+
with_mode(:master, *names, &block)
|
47
|
+
end
|
48
|
+
|
49
|
+
def with_master_all(&block)
|
50
|
+
with_master(*config.keys, &block)
|
51
|
+
end
|
52
|
+
|
53
|
+
def with_mode(mode, *names, &block)
|
54
|
+
names.reverse.inject(block) do |func, name|
|
55
|
+
lambda do
|
56
|
+
ProxyRepository.checkout(name).with_mode(mode, &func)
|
57
|
+
end
|
58
|
+
end.call
|
59
|
+
end
|
60
|
+
end
|
61
|
+
extend ClassMethods
|
62
|
+
end
|
63
|
+
ActiveSupport.on_load(:active_record) do
|
64
|
+
require 'switch_connection/model'
|
65
|
+
ActiveRecord::Base.include(SwitchConnection::Model)
|
66
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SwitchConnection
|
4
|
+
class Config
|
5
|
+
attr_accessor :auto_master, :env
|
6
|
+
alias_method :auto_master?, :auto_master
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
self.auto_master = false
|
10
|
+
self.env = :test
|
11
|
+
end
|
12
|
+
|
13
|
+
def define_switch_point(name, config)
|
14
|
+
assert_valid_config!(config)
|
15
|
+
switch_points[name] = config
|
16
|
+
end
|
17
|
+
|
18
|
+
def switch_points
|
19
|
+
@switch_points ||= {}
|
20
|
+
end
|
21
|
+
|
22
|
+
def master_database_name(name)
|
23
|
+
fetch(name)[:master]
|
24
|
+
end
|
25
|
+
|
26
|
+
def slave_database_name(name, index)
|
27
|
+
fetch(name)[:slaves][index]
|
28
|
+
end
|
29
|
+
|
30
|
+
def model_name(name, mode)
|
31
|
+
if mode == :master
|
32
|
+
master_model_name(name)
|
33
|
+
else
|
34
|
+
return unless slave_exist?(name)
|
35
|
+
|
36
|
+
slave_mode_name(name, rand(slave_count(name)))
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def master_model_name(name)
|
41
|
+
"#{name.to_s.gsub(/\W+/, '_').camelize}_master".camelize if fetch(name)[:master]
|
42
|
+
end
|
43
|
+
|
44
|
+
def slave_mode_name(name, index)
|
45
|
+
"#{name.to_s.gsub(/\W+/, '_').camelize}_slave_index_#{index}".camelize
|
46
|
+
end
|
47
|
+
|
48
|
+
def slave_exist?(name)
|
49
|
+
fetch(name).key?(:slaves)
|
50
|
+
end
|
51
|
+
|
52
|
+
def slave_count(name)
|
53
|
+
return 0 unless slave_exist?(name)
|
54
|
+
|
55
|
+
fetch(name)[:slaves].count
|
56
|
+
end
|
57
|
+
|
58
|
+
def slave_mode_names(name)
|
59
|
+
(0..(fetch(name)[:slaves].count - 1)).map { |i| slave_mode_name(name, i) }
|
60
|
+
end
|
61
|
+
|
62
|
+
def fetch(name)
|
63
|
+
switch_points.fetch(name)
|
64
|
+
end
|
65
|
+
|
66
|
+
def keys
|
67
|
+
switch_points.keys
|
68
|
+
end
|
69
|
+
|
70
|
+
def each_key(&block)
|
71
|
+
switch_points.each_key(&block)
|
72
|
+
end
|
73
|
+
|
74
|
+
private
|
75
|
+
|
76
|
+
def assert_valid_config!(config)
|
77
|
+
unless config.key?(:master) || config.key?(:slaves)
|
78
|
+
raise ArgumentError.new(':master or :slaves must be specified')
|
79
|
+
end
|
80
|
+
|
81
|
+
if config.key?(:slaves)
|
82
|
+
unless config[:slaves].is_a?(Array)
|
83
|
+
raise TypeError.new(":slaves's value must be Array")
|
84
|
+
end
|
85
|
+
end
|
86
|
+
if config.key?(:master)
|
87
|
+
unless config[:master].is_a?(Symbol)
|
88
|
+
raise TypeError.new(":master's value must be ")
|
89
|
+
end
|
90
|
+
end
|
91
|
+
nil
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,144 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'switch_connection/error'
|
4
|
+
require 'switch_connection/proxy_repository'
|
5
|
+
|
6
|
+
module SwitchConnection
|
7
|
+
module Model
|
8
|
+
def self.included(model)
|
9
|
+
super
|
10
|
+
model.singleton_class.class_eval do
|
11
|
+
include ClassMethods
|
12
|
+
prepend MonkeyPatch
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def with_slave(&block)
|
17
|
+
self.class.with_slave(&block)
|
18
|
+
end
|
19
|
+
|
20
|
+
def with_master(&block)
|
21
|
+
self.class.with_master(&block)
|
22
|
+
end
|
23
|
+
|
24
|
+
def with_switch_point(new_switch_point_name, &block)
|
25
|
+
self.class.with_switch_point(new_switch_point_name, &block)
|
26
|
+
end
|
27
|
+
|
28
|
+
def transaction_with(*models, &block)
|
29
|
+
self.class.transaction_with(*models, &block)
|
30
|
+
end
|
31
|
+
|
32
|
+
module ClassMethods
|
33
|
+
def with_slave(&block)
|
34
|
+
if switch_point_proxy
|
35
|
+
switch_point_proxy.with_slave(&block)
|
36
|
+
else
|
37
|
+
raise UnconfiguredError.new("#{name} isn't configured to use switch_point")
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def with_master(&block)
|
42
|
+
if switch_point_proxy
|
43
|
+
switch_point_proxy.with_master(&block)
|
44
|
+
else
|
45
|
+
raise UnconfiguredError.new("#{name} isn't configured to use switch_point")
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def use_switch_point(name)
|
50
|
+
assert_existing_switch_point!(name)
|
51
|
+
@global_switch_point_name = name
|
52
|
+
end
|
53
|
+
|
54
|
+
def with_switch_point(new_switch_point_name)
|
55
|
+
saved_switch_point_name = thread_local_switch_point_name
|
56
|
+
self.thread_local_switch_point_name = new_switch_point_name
|
57
|
+
yield
|
58
|
+
ensure
|
59
|
+
self.thread_local_switch_point_name = saved_switch_point_name
|
60
|
+
end
|
61
|
+
|
62
|
+
def switch_point_name
|
63
|
+
thread_local_switch_point_name || @global_switch_point_name
|
64
|
+
end
|
65
|
+
|
66
|
+
def thread_local_switch_point_name
|
67
|
+
Thread.current[:"thread_local_#{name}_switch_point_name"]
|
68
|
+
end
|
69
|
+
|
70
|
+
def thread_local_switch_point_name=(name)
|
71
|
+
Thread.current[:"thread_local_#{self.name}_switch_point_name"] = name
|
72
|
+
end
|
73
|
+
|
74
|
+
private :thread_local_switch_point_name=
|
75
|
+
|
76
|
+
def switch_point_proxy
|
77
|
+
if switch_point_name
|
78
|
+
ProxyRepository.checkout(switch_point_name)
|
79
|
+
elsif self == ActiveRecord::Base
|
80
|
+
nil
|
81
|
+
else
|
82
|
+
superclass.switch_point_proxy
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def transaction_with(*models, &block)
|
87
|
+
unless can_transaction_with?(*models)
|
88
|
+
raise Error.new("switch_point's model names must be consistent")
|
89
|
+
end
|
90
|
+
|
91
|
+
with_master do
|
92
|
+
transaction(&block)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
private
|
97
|
+
|
98
|
+
def assert_existing_switch_point!(name)
|
99
|
+
SwitchConnection.config.fetch(name)
|
100
|
+
end
|
101
|
+
|
102
|
+
def can_transaction_with?(*models)
|
103
|
+
master_switch_points = [self, *models].map do |model|
|
104
|
+
next unless model.switch_point_name
|
105
|
+
|
106
|
+
SwitchConnection.config.model_name(
|
107
|
+
model.switch_point_name,
|
108
|
+
:master
|
109
|
+
)
|
110
|
+
end
|
111
|
+
|
112
|
+
master_switch_points.uniq.size == 1
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
module MonkeyPatch
|
117
|
+
def connection
|
118
|
+
if switch_point_proxy
|
119
|
+
connection = switch_point_proxy.connection
|
120
|
+
connection.connection_name = switch_point_name
|
121
|
+
connection
|
122
|
+
else
|
123
|
+
super
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
def cache(&block)
|
128
|
+
if switch_point_proxy
|
129
|
+
switch_point_proxy.cache(&block)
|
130
|
+
else
|
131
|
+
super
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
def uncached(&block)
|
136
|
+
if switch_point_proxy
|
137
|
+
switch_point_proxy.uncached(&block)
|
138
|
+
else
|
139
|
+
super
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|