switchman 0.0.1 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +13 -5
- data/app/models/switchman/shard.rb +64 -19
- data/lib/switchman/action_controller/caching.rb +26 -0
- data/lib/switchman/active_record/abstract_adapter.rb +11 -0
- data/lib/switchman/active_record/association.rb +37 -3
- data/lib/switchman/active_record/attribute_methods.rb +3 -2
- data/lib/switchman/active_record/base.rb +44 -15
- data/lib/switchman/active_record/calculations.rb +145 -3
- data/lib/switchman/active_record/connection_handler.rb +11 -0
- data/lib/switchman/active_record/connection_pool.rb +5 -3
- data/lib/switchman/active_record/finder_methods.rb +25 -0
- data/lib/switchman/active_record/log_subscriber.rb +3 -2
- data/lib/switchman/active_record/query_cache.rb +71 -0
- data/lib/switchman/active_record/query_methods.rb +64 -29
- data/lib/switchman/active_record/relation.rb +44 -15
- data/lib/switchman/active_record/spawn_methods.rb +74 -0
- data/lib/switchman/active_support/cache.rb +17 -0
- data/lib/switchman/connection_pool_proxy.rb +47 -5
- data/lib/switchman/database_server.rb +131 -63
- data/lib/switchman/default_shard.rb +38 -23
- data/lib/switchman/engine.rb +71 -8
- data/lib/switchman/r_spec_helper.rb +41 -34
- data/lib/switchman/rails.rb +21 -0
- data/lib/switchman/shackles.rb +20 -20
- data/lib/switchman/sharded_instrumenter.rb +19 -0
- data/lib/switchman/test_helper.rb +3 -3
- data/lib/switchman/version.rb +1 -1
- data/lib/switchman.rb +1 -1
- data/spec/dummy/app/models/root.rb +5 -0
- data/spec/dummy/app/models/user.rb +6 -0
- data/spec/dummy/db/migrate/20140123154135_add_parent_id_to_users.rb +5 -0
- data/spec/dummy/db/migrate/20140219183820_create_roots.rb +9 -0
- data/spec/dummy/db/schema.rb +8 -1
- data/spec/dummy/log/development.log +135 -0
- data/spec/dummy/log/test.log +86777 -29398
- data/spec/dummy/tmp/cache/{317/9C0/shard%2F43 → 14A/870/key} +1 -1
- data/spec/dummy/tmp/cache/{319/A10/shard%2F72 → 2E9/8A0/shard%2F9} +1 -1
- data/spec/dummy/tmp/cache/317/9E0/shard%2F61 +0 -0
- data/spec/dummy/tmp/cache/318/9F0/shard%2F62 +0 -0
- data/spec/dummy/tmp/cache/{319/9F0/shard%2F54 → 318/A00/shard%2F71} +1 -1
- data/spec/dummy/tmp/cache/31A/A10/shard%2F64 +0 -0
- data/spec/dummy/tmp/cache/31A/A20/shard%2F73 +0 -0
- data/spec/dummy/tmp/cache/31B/A20/shard%2F65 +0 -0
- data/spec/dummy/tmp/cache/31B/A30/shard%2F74 +0 -0
- data/spec/dummy/tmp/cache/{31B/9E0/shard%2F29 → 31C/A40/shard%2F75} +1 -1
- data/spec/dummy/tmp/cache/31D/A30/shard%2F58 +0 -0
- data/spec/dummy/tmp/cache/31D/A40/shard%2F67 +0 -0
- data/spec/dummy/tmp/cache/31E/A40/shard%2F59 +0 -0
- data/spec/dummy/tmp/cache/31E/A50/shard%2F68 +0 -0
- data/spec/dummy/tmp/cache/320/A80/shard%2F79 +0 -0
- data/spec/dummy/tmp/cache/343/D90/shard%2F210 +0 -0
- data/spec/dummy/tmp/cache/344/D70/shard%2F103 +0 -0
- data/spec/dummy/tmp/cache/345/D80/shard%2F104 +0 -0
- data/spec/dummy/tmp/cache/345/DB0/shard%2F212 +0 -0
- data/spec/dummy/tmp/cache/345/DC0/shard%2F140 +0 -0
- data/spec/dummy/tmp/cache/345/DC0/shard%2F302 +0 -0
- data/spec/dummy/tmp/cache/346/D90/shard%2F105 +0 -0
- data/spec/dummy/tmp/cache/346/DD0/shard%2F303 +0 -0
- data/spec/dummy/tmp/cache/346/DF0/shard%2F321 +0 -0
- data/spec/dummy/tmp/cache/347/E00/shard%2F322 +0 -0
- data/spec/dummy/tmp/cache/347/E50/shard%2F610 +0 -0
- data/spec/dummy/tmp/cache/348/DD0/shard%2F206 +0 -0
- data/spec/dummy/tmp/cache/348/DE0/shard%2F215 +0 -0
- data/spec/dummy/tmp/cache/{316/980/shard%2F15 → 348/E10/shard%2F323} +1 -1
- data/spec/dummy/tmp/cache/348/E30/shard%2F422 +0 -0
- data/spec/dummy/tmp/cache/348/E40/shard%2F350 +0 -0
- data/spec/dummy/tmp/cache/348/E50/shard%2F602 +0 -0
- data/spec/dummy/tmp/cache/348/E80/shard%2F710 +0 -0
- data/spec/dummy/tmp/cache/348/E90/shard%2F800 +0 -0
- data/spec/dummy/tmp/cache/349/DE0/shard%2F126 +0 -0
- data/spec/dummy/tmp/cache/349/DF0/shard%2F216 +0 -0
- data/spec/dummy/tmp/cache/349/E00/shard%2F225 +0 -0
- data/spec/dummy/tmp/cache/349/E20/shard%2F243 +0 -0
- data/spec/dummy/tmp/cache/349/E20/shard%2F405 +0 -0
- data/spec/dummy/tmp/cache/349/E30/shard%2F333 +0 -0
- data/spec/dummy/tmp/cache/349/E40/shard%2F423 +0 -0
- data/spec/dummy/tmp/cache/349/E60/shard%2F603 +0 -0
- data/spec/dummy/tmp/cache/34A/DF0/shard%2F127 +0 -0
- data/spec/dummy/tmp/cache/34A/E10/shard%2F226 +0 -0
- data/spec/dummy/tmp/cache/34A/E30/shard%2F244 +0 -0
- data/spec/dummy/tmp/cache/34A/E50/shard%2F505 +0 -0
- data/spec/dummy/tmp/cache/34A/E60/shard%2F433 +0 -0
- data/spec/dummy/tmp/cache/34A/E70/shard%2F523 +0 -0
- data/spec/dummy/tmp/cache/34A/E80/shard%2F613 +0 -0
- data/spec/dummy/tmp/cache/34A/EA0/shard%2F712 +0 -0
- data/spec/dummy/tmp/cache/34A/EC0/shard%2F730 +0 -0
- data/spec/dummy/tmp/cache/34B/E00/shard%2F128 +1 -0
- data/spec/dummy/tmp/cache/34B/E00/shard%2F209 +0 -0
- data/spec/dummy/tmp/cache/34B/E10/shard%2F137 +0 -0
- data/spec/dummy/tmp/cache/34B/E30/shard%2F236 +0 -0
- data/spec/dummy/tmp/cache/34B/E50/shard%2F254 +0 -0
- data/spec/dummy/tmp/cache/34B/E60/shard%2F344 +0 -0
- data/spec/dummy/tmp/cache/34B/E60/shard%2F506 +0 -0
- data/spec/dummy/tmp/cache/34B/E80/shard%2F605 +0 -0
- data/spec/dummy/tmp/cache/34B/E90/shard%2F290 +0 -0
- data/spec/dummy/tmp/cache/34B/EC0/shard%2F560 +0 -0
- data/spec/dummy/tmp/cache/34B/ED0/shard%2F731 +0 -0
- data/spec/dummy/tmp/cache/34B/ED0/shard%2F812 +0 -0
- data/spec/dummy/tmp/cache/34C/E20/shard%2F138 +0 -0
- data/spec/dummy/tmp/cache/34C/E20/shard%2F219 +1 -0
- data/spec/dummy/tmp/cache/34C/E30/shard%2F228 +0 -0
- data/spec/dummy/tmp/cache/34C/E40/shard%2F237 +0 -0
- data/spec/dummy/tmp/cache/34C/E40/shard%2F318 +0 -0
- data/spec/dummy/tmp/cache/34C/E50/shard%2F246 +1 -0
- data/spec/dummy/tmp/cache/34C/E60/shard%2F255 +0 -0
- data/spec/dummy/tmp/cache/34C/E80/shard%2F192 +0 -0
- data/spec/dummy/tmp/cache/34C/EA0/shard%2F372 +0 -0
- data/spec/dummy/tmp/cache/34C/EA0/shard%2F453 +0 -0
- data/spec/dummy/tmp/cache/34C/EB0/shard%2F462 +0 -0
- data/spec/dummy/tmp/cache/34C/ED0/shard%2F480 +0 -0
- data/spec/dummy/tmp/cache/34C/ED0/shard%2F561 +0 -0
- data/spec/dummy/tmp/cache/34C/EF0/shard%2F822 +0 -0
- data/spec/dummy/tmp/cache/34C/EF0/shard%2F903 +0 -0
- data/spec/dummy/tmp/cache/34C/F00/shard%2F912 +0 -0
- data/spec/dummy/tmp/cache/34D/E50/shard%2F319 +0 -0
- data/spec/dummy/tmp/cache/34D/E80/shard%2F508 +0 -0
- data/spec/dummy/tmp/cache/34D/E90/shard%2F355 +0 -0
- data/spec/dummy/tmp/cache/34D/EA0/shard%2F364 +0 -0
- data/spec/dummy/tmp/cache/34D/EB0/shard%2F373 +0 -0
- data/spec/dummy/tmp/cache/34D/EB0/shard%2F454 +0 -0
- data/spec/dummy/tmp/cache/34D/EB0/shard%2F616 +0 -0
- data/spec/dummy/tmp/cache/34D/EC0/shard%2F544 +0 -0
- data/spec/dummy/tmp/cache/34D/ED0/shard%2F391 +0 -0
- data/spec/dummy/tmp/cache/34D/ED0/shard%2F715 +0 -0
- data/spec/dummy/tmp/cache/34D/F00/shard%2F661 +0 -0
- data/spec/dummy/tmp/cache/34D/F10/shard%2F913 +0 -0
- data/spec/dummy/tmp/cache/34E/E80/shard%2F257 +0 -0
- data/spec/dummy/tmp/cache/34E/EA0/shard%2F275 +0 -0
- data/spec/dummy/tmp/cache/34E/EB0/shard%2F365 +0 -0
- data/spec/dummy/tmp/cache/34E/EC0/shard%2F617 +0 -0
- data/spec/dummy/tmp/cache/34E/ED0/shard%2F545 +0 -0
- data/spec/dummy/tmp/cache/34E/EE0/shard%2F635 +0 -0
- data/spec/dummy/tmp/cache/34E/EF0/shard%2F482 +1 -0
- data/spec/dummy/tmp/cache/34E/EF0/shard%2F644 +0 -0
- data/spec/dummy/tmp/cache/34E/F00/shard%2F491 +0 -0
- data/spec/dummy/tmp/cache/34E/F00/shard%2F734 +1 -0
- data/spec/dummy/tmp/cache/34E/F40/shard%2F932 +0 -0
- data/spec/dummy/tmp/cache/34E/F50/shard%2F941 +0 -0
- data/spec/dummy/tmp/cache/34F/E80/shard%2F249 +0 -0
- data/spec/dummy/tmp/cache/34F/EA0/shard%2F267 +0 -0
- data/spec/dummy/tmp/cache/34F/EB0/shard%2F276 +0 -0
- data/spec/dummy/tmp/cache/34F/ED0/shard%2F375 +0 -0
- data/spec/dummy/tmp/cache/34F/ED0/shard%2F456 +0 -0
- data/spec/dummy/tmp/cache/34F/EE0/shard%2F465 +0 -0
- data/spec/dummy/tmp/cache/34F/EF0/shard%2F636 +0 -0
- data/spec/dummy/tmp/cache/34F/F00/shard%2F645 +0 -0
- data/spec/dummy/tmp/cache/34F/F10/shard%2F573 +0 -0
- data/spec/dummy/tmp/cache/34F/F20/shard%2F906 +0 -0
- data/spec/dummy/tmp/cache/34F/F40/shard%2F681 +0 -0
- data/spec/dummy/tmp/cache/34F/F50/shard%2F771 +0 -0
- data/spec/dummy/tmp/cache/34F/F60/shard%2F780 +0 -0
- data/spec/dummy/tmp/cache/34F/F60/shard%2F861 +0 -0
- data/spec/dummy/tmp/cache/34F/F60/shard%2F942 +0 -0
- data/spec/dummy/tmp/cache/350/EC0/shard%2F358 +0 -0
- data/spec/dummy/tmp/cache/350/EE0/shard%2F376 +0 -0
- data/spec/dummy/tmp/cache/350/EE0/shard%2F457 +0 -0
- data/spec/dummy/tmp/cache/350/EE0/shard%2F538 +0 -0
- data/spec/dummy/tmp/cache/350/EE0/shard%2F619 +0 -0
- data/spec/dummy/tmp/cache/350/EF0/shard%2F385 +0 -0
- data/spec/dummy/tmp/cache/350/EF0/shard%2F466 +0 -0
- data/spec/dummy/tmp/cache/350/EF0/shard%2F709 +0 -0
- data/spec/dummy/tmp/cache/350/F00/shard%2F394 +0 -0
- data/spec/dummy/tmp/cache/350/F20/shard%2F574 +0 -0
- data/spec/dummy/tmp/cache/350/F20/shard%2F736 +0 -0
- data/spec/dummy/tmp/cache/350/F30/shard%2F664 +0 -0
- data/spec/dummy/tmp/cache/350/F30/shard%2F745 +0 -0
- data/spec/dummy/tmp/cache/350/F50/shard%2F763 +0 -0
- data/spec/dummy/tmp/cache/350/F60/shard%2F772 +0 -0
- data/spec/dummy/tmp/cache/350/F70/shard%2F781 +0 -0
- data/spec/dummy/tmp/cache/350/F70/shard%2F862 +0 -0
- data/spec/dummy/tmp/cache/351/ED0/shard%2F359 +0 -0
- data/spec/dummy/tmp/cache/351/EF0/shard%2F296 +0 -0
- data/spec/dummy/tmp/cache/351/F00/shard%2F386 +0 -0
- data/spec/dummy/tmp/cache/351/F10/shard%2F476 +0 -0
- data/spec/dummy/tmp/cache/351/F10/shard%2F557 +0 -0
- data/spec/dummy/tmp/cache/351/F20/shard%2F485 +0 -0
- data/spec/dummy/tmp/cache/351/F30/shard%2F494 +0 -0
- data/spec/dummy/tmp/cache/351/F30/shard%2F737 +0 -0
- data/spec/dummy/tmp/cache/351/F40/shard%2F665 +0 -0
- data/spec/dummy/tmp/cache/351/F40/shard%2F746 +0 -0
- data/spec/dummy/tmp/cache/351/F70/shard%2F935 +0 -0
- data/spec/dummy/tmp/cache/352/F00/shard%2F297 +0 -0
- data/spec/dummy/tmp/cache/352/F00/shard%2F378 +0 -0
- data/spec/dummy/tmp/cache/352/F00/shard%2F459 +0 -0
- data/spec/dummy/tmp/cache/352/F10/shard%2F468 +1 -0
- data/spec/dummy/tmp/cache/352/F20/shard%2F639 +1 -0
- data/spec/dummy/tmp/cache/352/F30/shard%2F486 +0 -0
- data/spec/dummy/tmp/cache/352/F50/shard%2F585 +0 -0
- data/spec/dummy/tmp/cache/352/F50/shard%2F909 +0 -0
- data/spec/dummy/tmp/cache/352/F60/shard%2F594 +0 -0
- data/spec/dummy/tmp/cache/352/F70/shard%2F684 +0 -0
- data/spec/dummy/tmp/cache/352/F80/shard%2F774 +0 -0
- data/spec/dummy/tmp/cache/352/F80/shard%2F936 +0 -0
- data/spec/dummy/tmp/cache/352/F90/shard%2F783 +0 -0
- data/spec/dummy/tmp/cache/352/F90/shard%2F864 +0 -0
- data/spec/dummy/tmp/cache/352/F90/shard%2F945 +1 -0
- data/spec/dummy/tmp/cache/352/FA0/shard%2F873 +0 -0
- data/spec/dummy/tmp/cache/352/FC0/shard%2F972 +0 -0
- data/spec/dummy/tmp/cache/353/F50/shard%2F577 +1 -0
- data/spec/dummy/tmp/cache/353/F50/shard%2F739 +0 -0
- data/spec/dummy/tmp/cache/353/F60/shard%2F748 +0 -0
- data/spec/dummy/tmp/cache/353/F70/shard%2F595 +0 -0
- data/spec/dummy/tmp/cache/353/F90/shard%2F775 +0 -0
- data/spec/dummy/tmp/cache/353/FA0/shard%2F784 +0 -0
- data/spec/dummy/tmp/cache/353/FD0/shard%2F892 +0 -0
- data/spec/dummy/tmp/cache/354/000/shard%2F992 +0 -0
- data/spec/dummy/tmp/cache/354/F30/shard%2F389 +1 -0
- data/spec/dummy/tmp/cache/354/F40/shard%2F479 +0 -0
- data/spec/dummy/tmp/cache/354/F50/shard%2F488 +0 -0
- data/spec/dummy/tmp/cache/354/F90/shard%2F929 +0 -0
- data/spec/dummy/tmp/cache/354/FA0/shard%2F938 +0 -0
- data/spec/dummy/tmp/cache/354/FD0/shard%2F965 +0 -0
- data/spec/dummy/tmp/cache/354/FE0/shard%2F893 +0 -0
- data/spec/dummy/tmp/cache/354/FF0/shard%2F983 +0 -0
- data/spec/dummy/tmp/cache/355/010/shard%2F993 +0 -0
- data/spec/dummy/tmp/cache/355/F60/shard%2F489 +0 -0
- data/spec/dummy/tmp/cache/355/F80/shard%2F588 +0 -0
- data/spec/dummy/tmp/cache/355/F90/shard%2F678 +0 -0
- data/spec/dummy/tmp/cache/355/FA0/shard%2F687 +0 -0
- data/spec/dummy/tmp/cache/355/FB0/shard%2F777 +1 -0
- data/spec/dummy/tmp/cache/355/FB0/shard%2F858 +0 -0
- data/spec/dummy/tmp/cache/355/FB0/shard%2F939 +0 -0
- data/spec/dummy/tmp/cache/355/FD0/shard%2F795 +0 -0
- data/spec/dummy/tmp/cache/355/FD0/shard%2F876 +0 -0
- data/spec/dummy/tmp/cache/355/FE0/shard%2F966 +0 -0
- data/spec/dummy/tmp/cache/356/000/shard%2F895 +1 -0
- data/spec/dummy/tmp/cache/356/FA0/shard%2F679 +0 -0
- data/spec/dummy/tmp/cache/356/FB0/shard%2F688 +0 -0
- data/spec/dummy/tmp/cache/356/FC0/shard%2F859 +0 -0
- data/spec/dummy/tmp/cache/356/FE0/shard%2F796 +0 -0
- data/spec/dummy/tmp/cache/356/FE0/shard%2F877 +0 -0
- data/spec/dummy/tmp/cache/357/020/shard%2F986 +0 -0
- data/spec/dummy/tmp/cache/357/FC0/shard%2F689 +1 -0
- data/spec/dummy/tmp/cache/358/000/shard%2F879 +0 -0
- data/spec/dummy/tmp/cache/358/FF0/shard%2F789 +0 -0
- data/spec/dummy/tmp/cache/372/470/shard%2F1010 +0 -0
- data/spec/dummy/tmp/cache/373/4A0/shard%2F1110 +0 -0
- data/spec/dummy/tmp/cache/374/490/shard%2F1012 +1 -0
- data/spec/dummy/tmp/cache/375/4C0/shard%2F2003 +1 -0
- data/spec/dummy/tmp/cache/375/510/shard%2F1400 +0 -0
- data/spec/dummy/tmp/cache/376/4E0/shard%2F1041 +0 -0
- data/spec/dummy/tmp/cache/376/4E0/shard%2F1203 +0 -0
- data/spec/dummy/tmp/cache/376/4F0/shard%2F1212 +0 -0
- data/spec/dummy/tmp/cache/376/500/shard%2F1221 +0 -0
- data/spec/dummy/tmp/cache/377/4C0/shard%2F1015 +0 -0
- data/spec/dummy/tmp/cache/377/500/shard%2F1213 +0 -0
- data/spec/dummy/tmp/cache/377/530/shard%2F1240 +0 -0
- data/spec/dummy/tmp/cache/377/530/shard%2F1321 +0 -0
- data/spec/dummy/tmp/cache/377/530/shard%2F1402 +0 -0
- data/spec/dummy/tmp/cache/378/4E0/shard%2F1106 +0 -0
- data/spec/dummy/tmp/cache/378/510/shard%2F1133 +0 -0
- data/spec/dummy/tmp/cache/378/520/shard%2F1142 +0 -0
- data/spec/dummy/tmp/cache/378/530/shard%2F1313 +0 -0
- data/spec/dummy/tmp/cache/378/540/shard%2F1241 +0 -0
- data/spec/dummy/tmp/cache/378/540/shard%2F1403 +0 -0
- data/spec/dummy/tmp/cache/378/550/shard%2F1331 +0 -0
- data/spec/dummy/tmp/cache/378/560/shard%2F1340 +0 -0
- data/spec/dummy/tmp/cache/379/4F0/shard%2F1026 +0 -0
- data/spec/dummy/tmp/cache/379/500/shard%2F1035 +0 -0
- data/spec/dummy/tmp/cache/379/510/shard%2F1044 +0 -0
- data/spec/dummy/tmp/cache/379/520/shard%2F1134 +0 -0
- data/spec/dummy/tmp/cache/379/530/shard%2F1224 +0 -0
- data/spec/dummy/tmp/cache/379/550/shard%2F1080 +0 -0
- data/spec/dummy/tmp/cache/379/550/shard%2F1161 +0 -0
- data/spec/dummy/tmp/cache/379/550/shard%2F1404 +1 -0
- data/spec/dummy/tmp/cache/379/560/shard%2F1332 +0 -0
- data/spec/dummy/tmp/cache/379/570/shard%2F1260 +0 -0
- data/spec/dummy/tmp/cache/379/570/shard%2F1341 +0 -0
- data/spec/dummy/tmp/cache/379/5A0/shard%2F1611 +1 -0
- data/spec/dummy/tmp/cache/37A/4E0/shard%2F1009 +0 -0
- data/spec/dummy/tmp/cache/37A/4F0/shard%2F1018 +0 -0
- data/spec/dummy/tmp/cache/37A/500/shard%2F1027 +0 -0
- data/spec/dummy/tmp/cache/37A/510/shard%2F1117 +0 -0
- data/spec/dummy/tmp/cache/37A/520/shard%2F1045 +0 -0
- data/spec/dummy/tmp/cache/37A/570/shard%2F1252 +0 -0
- data/spec/dummy/tmp/cache/37A/580/shard%2F1261 +0 -0
- data/spec/dummy/tmp/cache/37A/5C0/shard%2F1702 +0 -0
- data/spec/dummy/tmp/cache/37A/5D0/shard%2F1711 +1 -0
- data/spec/dummy/tmp/cache/37B/500/shard%2F1019 +0 -0
- data/spec/dummy/tmp/cache/37B/510/shard%2F1028 +1 -0
- data/spec/dummy/tmp/cache/37B/510/shard%2F1109 +0 -0
- data/spec/dummy/tmp/cache/37B/540/shard%2F1136 +0 -0
- data/spec/dummy/tmp/cache/37B/580/shard%2F1253 +0 -0
- data/spec/dummy/tmp/cache/37B/590/shard%2F1181 +0 -0
- data/spec/dummy/tmp/cache/37B/5A0/shard%2F1190 +0 -0
- data/spec/dummy/tmp/cache/37B/5B0/shard%2F1523 +0 -0
- data/spec/dummy/tmp/cache/37B/5C0/shard%2F1370 +0 -0
- data/spec/dummy/tmp/cache/37B/600/shard%2F1811 +1 -0
- data/spec/dummy/tmp/cache/37C/530/shard%2F1038 +0 -0
- data/spec/dummy/tmp/cache/37C/550/shard%2F1137 +0 -0
- data/spec/dummy/tmp/cache/37C/560/shard%2F1065 +0 -0
- data/spec/dummy/tmp/cache/37C/580/shard%2F1164 +0 -0
- data/spec/dummy/tmp/cache/37C/590/shard%2F1092 +0 -0
- data/spec/dummy/tmp/cache/37C/590/shard%2F1335 +1 -0
- data/spec/dummy/tmp/cache/37C/5A0/shard%2F1182 +0 -0
- data/spec/dummy/tmp/cache/37C/5A0/shard%2F1263 +0 -0
- data/spec/dummy/tmp/cache/37C/5B0/shard%2F1191 +1 -0
- data/spec/dummy/tmp/cache/37C/5B0/shard%2F1434 +0 -0
- data/spec/dummy/tmp/cache/37C/5C0/shard%2F1605 +1 -0
- data/spec/dummy/tmp/cache/37C/5F0/shard%2F1470 +0 -0
- data/spec/dummy/tmp/cache/37C/620/shard%2F1821 +0 -0
- data/spec/dummy/tmp/cache/37C/620/shard%2F1902 +1 -0
- data/spec/dummy/tmp/cache/37C/640/shard%2F1920 +1 -0
- data/spec/dummy/tmp/cache/37D/540/shard%2F1039 +0 -0
- data/spec/dummy/tmp/cache/37D/560/shard%2F1057 +0 -0
- data/spec/dummy/tmp/cache/37D/590/shard%2F1246 +0 -0
- data/spec/dummy/tmp/cache/37D/590/shard%2F1408 +0 -0
- data/spec/dummy/tmp/cache/37D/5A0/shard%2F1093 +0 -0
- data/spec/dummy/tmp/cache/37D/5E0/shard%2F1372 +0 -0
- data/spec/dummy/tmp/cache/37D/5F0/shard%2F1381 +0 -0
- data/spec/dummy/tmp/cache/37D/610/shard%2F1642 +0 -0
- data/spec/dummy/tmp/cache/37D/610/shard%2F1804 +0 -0
- data/spec/dummy/tmp/cache/37E/570/shard%2F1058 +0 -0
- data/spec/dummy/tmp/cache/37E/570/shard%2F1139 +0 -0
- data/spec/dummy/tmp/cache/37E/580/shard%2F1229 +0 -0
- data/spec/dummy/tmp/cache/37E/5A0/shard%2F1247 +0 -0
- data/spec/dummy/tmp/cache/37E/5A0/shard%2F1409 +0 -0
- data/spec/dummy/tmp/cache/37E/5C0/shard%2F1346 +0 -0
- data/spec/dummy/tmp/cache/37E/5F0/shard%2F1292 +0 -0
- data/spec/dummy/tmp/cache/37E/5F0/shard%2F1373 +0 -0
- data/spec/dummy/tmp/cache/37E/5F0/shard%2F1535 +0 -0
- data/spec/dummy/tmp/cache/37E/600/shard%2F1382 +0 -0
- data/spec/dummy/tmp/cache/37E/620/shard%2F1805 +0 -0
- data/spec/dummy/tmp/cache/37E/640/shard%2F1661 +1 -0
- data/spec/dummy/tmp/cache/37F/5A0/shard%2F1158 +0 -0
- data/spec/dummy/tmp/cache/37F/5B0/shard%2F1167 +0 -0
- data/spec/dummy/tmp/cache/37F/5B0/shard%2F1248 +1 -0
- data/spec/dummy/tmp/cache/37F/5C0/shard%2F1095 +1 -0
- data/spec/dummy/tmp/cache/37F/5E0/shard%2F1275 +0 -0
- data/spec/dummy/tmp/cache/37F/5E0/shard%2F1437 +0 -0
- data/spec/dummy/tmp/cache/37F/600/shard%2F1455 +0 -0
- data/spec/dummy/tmp/cache/37F/600/shard%2F1536 +0 -0
- data/spec/dummy/tmp/cache/37F/610/shard%2F1464 +0 -0
- data/spec/dummy/tmp/cache/37F/620/shard%2F1473 +1 -0
- data/spec/dummy/tmp/cache/37F/630/shard%2F1482 +0 -0
- data/spec/dummy/tmp/cache/37F/640/shard%2F1491 +0 -0
- data/spec/dummy/tmp/cache/37F/640/shard%2F1653 +0 -0
- data/spec/dummy/tmp/cache/380/5C0/shard%2F1168 +0 -0
- data/spec/dummy/tmp/cache/380/5E0/shard%2F1429 +0 -0
- data/spec/dummy/tmp/cache/380/5F0/shard%2F1195 +0 -0
- data/spec/dummy/tmp/cache/380/5F0/shard%2F1276 +0 -0
- data/spec/dummy/tmp/cache/380/610/shard%2F1375 +0 -0
- data/spec/dummy/tmp/cache/380/620/shard%2F1384 +0 -0
- data/spec/dummy/tmp/cache/380/620/shard%2F1465 +0 -0
- data/spec/dummy/tmp/cache/380/640/shard%2F1645 +1 -0
- data/spec/dummy/tmp/cache/380/640/shard%2F1726 +1 -0
- data/spec/dummy/tmp/cache/380/650/shard%2F1492 +0 -0
- data/spec/dummy/tmp/cache/380/650/shard%2F1654 +0 -0
- data/spec/dummy/tmp/cache/380/660/shard%2F1906 +0 -0
- data/spec/dummy/tmp/cache/380/670/shard%2F1591 +0 -0
- data/spec/dummy/tmp/cache/380/670/shard%2F1753 +0 -0
- data/spec/dummy/tmp/cache/381/5F0/shard%2F1349 +0 -0
- data/spec/dummy/tmp/cache/381/600/shard%2F1196 +0 -0
- data/spec/dummy/tmp/cache/381/610/shard%2F1286 +0 -0
- data/spec/dummy/tmp/cache/381/620/shard%2F1295 +0 -0
- data/spec/dummy/tmp/cache/381/630/shard%2F1547 +1 -0
- data/spec/dummy/tmp/cache/381/650/shard%2F1565 +1 -0
- data/spec/dummy/tmp/cache/381/660/shard%2F1493 +1 -0
- data/spec/dummy/tmp/cache/381/670/shard%2F1745 +1 -0
- data/spec/dummy/tmp/cache/381/670/shard%2F1907 +0 -0
- data/spec/dummy/tmp/cache/381/680/shard%2F1592 +0 -0
- data/spec/dummy/tmp/cache/381/680/shard%2F1754 +0 -0
- data/spec/dummy/tmp/cache/381/6C0/shard%2F1790 +1 -0
- data/spec/dummy/tmp/cache/382/5F0/shard%2F1098 +0 -0
- data/spec/dummy/tmp/cache/382/600/shard%2F1269 +0 -0
- data/spec/dummy/tmp/cache/382/610/shard%2F1278 +1 -0
- data/spec/dummy/tmp/cache/382/620/shard%2F1287 +0 -0
- data/spec/dummy/tmp/cache/382/630/shard%2F1296 +0 -0
- data/spec/dummy/tmp/cache/382/640/shard%2F1467 +1 -0
- data/spec/dummy/tmp/cache/382/650/shard%2F1557 +0 -0
- data/spec/dummy/tmp/cache/382/690/shard%2F1674 +1 -0
- data/spec/dummy/tmp/cache/382/6A0/shard%2F1845 +1 -0
- data/spec/dummy/tmp/cache/382/6D0/shard%2F1953 +1 -0
- data/spec/dummy/tmp/cache/382/700/shard%2F1980 +0 -0
- data/spec/dummy/tmp/cache/383/610/shard%2F1189 +0 -0
- data/spec/dummy/tmp/cache/383/630/shard%2F1369 +0 -0
- data/spec/dummy/tmp/cache/383/640/shard%2F1378 +0 -0
- data/spec/dummy/tmp/cache/383/660/shard%2F1639 +1 -0
- data/spec/dummy/tmp/cache/383/680/shard%2F1576 +1 -0
- data/spec/dummy/tmp/cache/383/690/shard%2F1828 +1 -0
- data/spec/dummy/tmp/cache/383/6C0/shard%2F1774 +1 -0
- data/spec/dummy/tmp/cache/383/700/shard%2F1891 +0 -0
- data/spec/dummy/tmp/cache/383/700/shard%2F1972 +1 -0
- data/spec/dummy/tmp/cache/384/6B0/shard%2F1838 +0 -0
- data/spec/dummy/tmp/cache/384/700/shard%2F1883 +1 -0
- data/spec/dummy/tmp/cache/384/710/shard%2F1892 +0 -0
- data/spec/dummy/tmp/cache/386/690/shard%2F1399 +0 -0
- data/spec/dummy/tmp/cache/386/6D0/shard%2F1759 +1 -0
- data/spec/dummy/tmp/cache/386/6F0/shard%2F1858 +1 -0
- data/spec/dummy/tmp/cache/386/750/shard%2F1993 +1 -0
- data/spec/dummy/tmp/cache/388/710/shard%2F1698 +1 -0
- data/spec/dummy/tmp/cache/3A3/EA0/shard%2F10101 +1 -0
- data/spec/dummy/tmp/cache/3A3/EC0/shard%2F11010 +1 -0
- data/spec/dummy/tmp/cache/3A6/EB0/shard%2F10005 +1 -0
- data/spec/dummy/tmp/cache/3A6/ED0/shard%2F10104 +1 -0
- data/spec/dummy/tmp/cache/3A7/EC0/shard%2F10006 +1 -0
- data/spec/dummy/tmp/cache/3A7/F10/shard%2F10051 +1 -0
- data/spec/dummy/tmp/cache/3A8/F50/shard%2F10322 +1 -0
- data/spec/dummy/tmp/cache/3A9/F10/shard%2F10035 +1 -0
- data/spec/dummy/tmp/cache/3A9/F90/shard%2F11403 +1 -0
- data/spec/dummy/tmp/cache/3AA/F40/shard%2F10216 +1 -0
- data/spec/dummy/tmp/cache/3AA/FB0/shard%2F11332 +1 -0
- data/spec/dummy/tmp/cache/3AB/030/shard%2F11720 +1 -0
- data/spec/dummy/tmp/cache/3AB/F10/shard%2F10019 +1 -0
- data/spec/dummy/tmp/cache/3AB/F40/shard%2F10127 +1 -0
- data/spec/dummy/tmp/cache/3AB/F50/shard%2F11027 +1 -0
- data/spec/dummy/tmp/cache/3AB/F80/shard%2F10244 +1 -0
- data/spec/dummy/tmp/cache/3AC/020/shard%2F10731 +1 -0
- data/spec/dummy/tmp/cache/3AC/020/shard%2F11541 +1 -0
- data/spec/dummy/tmp/cache/3AC/020/shard%2F11703 +1 -0
- data/spec/dummy/tmp/cache/3AC/F80/shard%2F10074 +1 -0
- data/spec/dummy/tmp/cache/3AC/F90/shard%2F10083 +1 -0
- data/spec/dummy/tmp/cache/3AC/FA0/shard%2F10173 +1 -0
- data/spec/dummy/tmp/cache/3AC/FF0/shard%2F11190 +1 -0
- data/spec/dummy/tmp/cache/3AD/020/shard%2F10480 +1 -0
- data/spec/dummy/tmp/cache/3AD/F70/shard%2F10138 +1 -0
- data/spec/dummy/tmp/cache/3AE/050/shard%2F11471 +1 -0
- data/spec/dummy/tmp/cache/3AE/080/shard%2F11822 +1 -0
- data/spec/dummy/tmp/cache/3AE/F90/shard%2F10067 +1 -0
- data/spec/dummy/tmp/cache/3AE/FF0/shard%2F11093 +1 -0
- data/spec/dummy/tmp/cache/3AF/070/shard%2F11643 +1 -0
- data/spec/dummy/tmp/cache/3AF/070/shard%2F11805 +1 -0
- data/spec/dummy/tmp/cache/3AF/FA0/shard%2F10068 +1 -0
- data/spec/dummy/tmp/cache/3AF/FF0/shard%2F11247 +1 -0
- data/spec/dummy/tmp/cache/3B0/040/shard%2F10636 +1 -0
- data/spec/dummy/tmp/cache/3B0/060/shard%2F11626 +1 -0
- data/spec/dummy/tmp/cache/3B0/0B0/shard%2F10942 +1 -0
- data/spec/dummy/tmp/cache/3B0/FC0/shard%2F10159 +1 -0
- data/spec/dummy/tmp/cache/3B1/040/shard%2F10466 +1 -0
- data/spec/dummy/tmp/cache/3B1/040/shard%2F11276 +1 -0
- data/spec/dummy/tmp/cache/3B1/050/shard%2F11609 +1 -0
- data/spec/dummy/tmp/cache/3B1/070/shard%2F10574 +1 -0
- data/spec/dummy/tmp/cache/3B1/070/shard%2F11465 +1 -0
- data/spec/dummy/tmp/cache/3B1/0A0/shard%2F11492 +1 -0
- data/spec/dummy/tmp/cache/3B1/0A0/shard%2F11654 +1 -0
- data/spec/dummy/tmp/cache/3B1/0E0/shard%2F11771 +1 -0
- data/spec/dummy/tmp/cache/3B2/050/shard%2F10386 +1 -0
- data/spec/dummy/tmp/cache/3B2/0C0/shard%2F11907 +1 -0
- data/spec/dummy/tmp/cache/3B2/0D0/shard%2F11592 +1 -0
- data/spec/dummy/tmp/cache/3B2/0D0/shard%2F11754 +1 -0
- data/spec/dummy/tmp/cache/3B2/110/shard%2F11952 +1 -0
- data/spec/dummy/tmp/cache/3B3/0C0/shard%2F11575 +1 -0
- data/spec/dummy/tmp/cache/3B3/0C0/shard%2F11737 +1 -0
- data/spec/dummy/tmp/cache/3B4/0B0/shard%2F11558 +1 -0
- data/spec/dummy/tmp/cache/3B4/0E0/shard%2F10775 +1 -0
- data/spec/dummy/tmp/cache/3B4/130/shard%2F11873 +1 -0
- data/spec/dummy/tmp/cache/3B4/160/shard%2F11981 +1 -0
- data/spec/dummy/tmp/cache/3B5/120/shard%2F11856 +1 -0
- data/spec/dummy/tmp/cache/3B5/130/shard%2F10893 +1 -0
- data/spec/dummy/tmp/cache/3B5/150/shard%2F11964 +1 -0
- data/spec/dummy/tmp/cache/3B5/160/shard%2F11892 +1 -0
- data/spec/dummy/tmp/cache/3B6/110/shard%2F11839 +1 -0
- data/spec/dummy/tmp/cache/3B6/120/shard%2F11686 +1 -0
- data/spec/dummy/tmp/cache/3B7/100/shard%2F10688 +1 -0
- data/spec/dummy/tmp/cache/3B7/110/shard%2F11669 +1 -0
- data/spec/dummy/tmp/cache/3B9/170/shard%2F11788 +1 -0
- data/spec/dummy/tmp/cache/3BC/1F0/shard%2F11998 +1 -0
- data/spec/dummy/tmp/cache/4B7/9C0/shard_12%3Akey +1 -0
- data/spec/dummy/tmp/cache/4B8/A30/shard_13%3Akey +1 -0
- data/spec/dummy/tmp/cache/4B9/AA0/shard_14%3Akey +1 -0
- data/spec/dummy/tmp/cache/4BA/B50/shard_51%3Akey +1 -0
- data/spec/dummy/tmp/cache/4BB/B90/shard_25%3Akey +1 -0
- data/spec/dummy/tmp/cache/4BB/BC0/shard_52%3Akey +1 -0
- data/spec/dummy/tmp/cache/4BC/C00/shard_26%3Akey +1 -0
- data/spec/dummy/tmp/cache/4BC/C50/shard_71%3Akey +1 -0
- data/spec/dummy/tmp/cache/4BD/CC0/shard_72%3Akey +1 -0
- data/spec/dummy/tmp/cache/4BD/CE0/shard_90%3Akey +1 -0
- data/spec/dummy/tmp/cache/4BE/D00/shard_46%3Akey +1 -0
- data/spec/dummy/tmp/cache/4BF/D70/shard_47%3Akey +1 -0
- data/spec/dummy/tmp/cache/4C0/DF0/shard_57%3Akey +1 -0
- data/spec/dummy/tmp/cache/4C0/E20/shard_84%3Akey +1 -0
- data/spec/dummy/tmp/cache/4C1/E60/shard_58%3Akey +1 -0
- data/spec/dummy/tmp/cache/4C1/E90/shard_85%3Akey +1 -0
- data/spec/dummy/tmp/cache/4C5/050/shard_89%3Akey +1 -0
- data/spec/dummy/tmp/cache/4E5/B10/shard_100%3Akey +1 -0
- data/spec/dummy/tmp/cache/4E6/B80/shard_101%3Akey +1 -0
- data/spec/dummy/tmp/cache/4E8/CA0/shard_220%3Akey +1 -0
- data/spec/dummy/tmp/cache/4E9/D10/shard_221%3Akey +1 -0
- data/spec/dummy/tmp/cache/4EA/D90/shard_150%3Akey +1 -0
- data/spec/dummy/tmp/cache/4EA/DC0/shard_420%3Akey +1 -0
- data/spec/dummy/tmp/cache/4EB/E00/shard_151%3Akey +1 -0
- data/spec/dummy/tmp/cache/4ED/EE0/shard_153%3Akey +1 -0
- data/spec/dummy/tmp/cache/4EE/F50/shard_154%3Akey +1 -0
- data/spec/dummy/tmp/cache/4EE/F80/shard_181%3Akey +1 -0
- data/spec/dummy/tmp/cache/4EE/F90/shard_352%3Akey +1 -0
- data/spec/dummy/tmp/cache/4EF/000/shard_272%3Akey +1 -0
- data/spec/dummy/tmp/cache/4EF/000/shard_353%3Akey +1 -0
- data/spec/dummy/tmp/cache/4EF/000/shard_515%3Akey +1 -0
- data/spec/dummy/tmp/cache/4EF/030/shard_380%3Akey +1 -0
- data/spec/dummy/tmp/cache/4EF/040/shard_632%3Akey +1 -0
- data/spec/dummy/tmp/cache/4EF/FF0/shard_182%3Akey +1 -0
- data/spec/dummy/tmp/cache/4F0/010/shard_138%3Akey +1 -0
- data/spec/dummy/tmp/cache/4F0/070/shard_273%3Akey +1 -0
- data/spec/dummy/tmp/cache/4F0/070/shard_516%3Akey +1 -0
- data/spec/dummy/tmp/cache/4F0/0A0/shard_381%3Akey +1 -0
- data/spec/dummy/tmp/cache/4F0/0B0/shard_633%3Akey +1 -0
- data/spec/dummy/tmp/cache/4F1/080/shard_139%3Akey +1 -0
- data/spec/dummy/tmp/cache/4F1/140/shard_814%3Akey +1 -0
- data/spec/dummy/tmp/cache/4F2/120/shard_167%3Akey +1 -0
- data/spec/dummy/tmp/cache/4F2/130/shard_419%3Akey +1 -0
- data/spec/dummy/tmp/cache/4F2/1B0/shard_815%3Akey +1 -0
- data/spec/dummy/tmp/cache/4F2/1E0/shard_923%3Akey +1 -0
- data/spec/dummy/tmp/cache/4F3/190/shard_168%3Akey +1 -0
- data/spec/dummy/tmp/cache/4F3/250/shard_924%3Akey +1 -0
- data/spec/dummy/tmp/cache/4F5/320/shard_755%3Akey +1 -0
- data/spec/dummy/tmp/cache/4F6/360/shard_567%3Akey +1 -0
- data/spec/dummy/tmp/cache/4F6/390/shard_756%3Akey +1 -0
- data/spec/dummy/tmp/cache/4F7/3D0/shard_568%3Akey +1 -0
- data/spec/dummy/tmp/cache/4F7/3E0/shard_658%3Akey +1 -0
- data/spec/dummy/tmp/cache/4F8/450/shard_659%3Akey +1 -0
- data/spec/dummy/tmp/cache/4F8/4C0/shard_884%3Akey +1 -0
- data/spec/dummy/tmp/cache/4F9/530/shard_885%3Akey +1 -0
- data/spec/dummy/tmp/cache/4FA/5A0/shard_967%3Akey +1 -0
- data/spec/dummy/tmp/cache/4FB/610/shard_968%3Akey +1 -0
- data/spec/dummy/tmp/cache/518/1C0/shard_1111%3Akey +1 -0
- data/spec/dummy/tmp/cache/519/230/shard_1112%3Akey +1 -0
- data/spec/dummy/tmp/cache/51A/2C0/shard_1050%3Akey +1 -0
- data/spec/dummy/tmp/cache/51B/3A0/shard_1600%3Akey +1 -0
- data/spec/dummy/tmp/cache/51C/410/shard_1601%3Akey +1 -0
- data/spec/dummy/tmp/cache/51D/4B0/shard_1710%3Akey +1 -0
- data/spec/dummy/tmp/cache/51E/4E0/shard_1351%3Akey +1 -0
- data/spec/dummy/tmp/cache/51F/550/shard_1352%3Akey +1 -0
- data/spec/dummy/tmp/cache/51F/570/shard_1532%3Akey +1 -0
- data/spec/dummy/tmp/cache/520/580/shard_1155%3Akey +1 -0
- data/spec/dummy/tmp/cache/520/5A0/shard_1416%3Akey +1 -0
- data/spec/dummy/tmp/cache/520/5D0/shard_1443%3Akey +1 -0
- data/spec/dummy/tmp/cache/520/5E0/shard_1452%3Akey +1 -0
- data/spec/dummy/tmp/cache/520/5E0/shard_1533%3Akey +1 -0
- data/spec/dummy/tmp/cache/520/5F0/shard_1461%3Akey +1 -0
- data/spec/dummy/tmp/cache/520/600/shard_1551%3Akey +1 -0
- data/spec/dummy/tmp/cache/521/5F0/shard_1156%3Akey +1 -0
- data/spec/dummy/tmp/cache/521/610/shard_1417%3Akey +1 -0
- data/spec/dummy/tmp/cache/521/620/shard_1507%3Akey +1 -0
- data/spec/dummy/tmp/cache/521/630/shard_1516%3Akey +1 -0
- data/spec/dummy/tmp/cache/521/640/shard_1444%3Akey +1 -0
- data/spec/dummy/tmp/cache/521/650/shard_1453%3Akey +1 -0
- data/spec/dummy/tmp/cache/521/660/shard_1462%3Akey +1 -0
- data/spec/dummy/tmp/cache/521/670/shard_1552%3Akey +1 -0
- data/spec/dummy/tmp/cache/521/680/shard_1480%3Akey +1 -0
- data/spec/dummy/tmp/cache/521/690/shard_1813%3Akey +1 -0
- data/spec/dummy/tmp/cache/522/630/shard_1049%3Akey +1 -0
- data/spec/dummy/tmp/cache/522/690/shard_1508%3Akey +1 -0
- data/spec/dummy/tmp/cache/522/6A0/shard_1517%3Akey +1 -0
- data/spec/dummy/tmp/cache/522/700/shard_1571%3Akey +1 -0
- data/spec/dummy/tmp/cache/522/700/shard_1733%3Akey +1 -0
- data/spec/dummy/tmp/cache/522/700/shard_1814%3Akey +1 -0
- data/spec/dummy/tmp/cache/522/740/shard_1850%3Akey +1 -0
- data/spec/dummy/tmp/cache/523/6F0/shard_1257%3Akey +1 -0
- data/spec/dummy/tmp/cache/523/730/shard_1617%3Akey +1 -0
- data/spec/dummy/tmp/cache/523/770/shard_1572%3Akey +1 -0
- data/spec/dummy/tmp/cache/523/770/shard_1734%3Akey +1 -0
- data/spec/dummy/tmp/cache/523/7B0/shard_1851%3Akey +1 -0
- data/spec/dummy/tmp/cache/524/760/shard_1258%3Akey +1 -0
- data/spec/dummy/tmp/cache/524/7A0/shard_1537%3Akey +1 -0
- data/spec/dummy/tmp/cache/524/7A0/shard_1618%3Akey +1 -0
- data/spec/dummy/tmp/cache/524/7C0/shard_1636%3Akey +1 -0
- data/spec/dummy/tmp/cache/524/820/shard_1690%3Akey +1 -0
- data/spec/dummy/tmp/cache/525/810/shard_1538%3Akey +1 -0
- data/spec/dummy/tmp/cache/525/820/shard_1709%3Akey +1 -0
- data/spec/dummy/tmp/cache/525/830/shard_1637%3Akey +1 -0
- data/spec/dummy/tmp/cache/525/870/shard_1835%3Akey +1 -0
- data/spec/dummy/tmp/cache/525/8A0/shard_1862%3Akey +1 -0
- data/spec/dummy/tmp/cache/526/8D0/shard_1665%3Akey +1 -0
- data/spec/dummy/tmp/cache/526/8E0/shard_1755%3Akey +1 -0
- data/spec/dummy/tmp/cache/526/8E0/shard_1836%3Akey +1 -0
- data/spec/dummy/tmp/cache/526/910/shard_1863%3Akey +1 -0
- data/spec/dummy/tmp/cache/527/8F0/shard_1297%3Akey +1 -0
- data/spec/dummy/tmp/cache/527/920/shard_1486%3Akey +1 -0
- data/spec/dummy/tmp/cache/527/930/shard_1738%3Akey +1 -0
- data/spec/dummy/tmp/cache/527/940/shard_1585%3Akey +1 -0
- data/spec/dummy/tmp/cache/527/940/shard_1666%3Akey +1 -0
- data/spec/dummy/tmp/cache/527/950/shard_1756%3Akey +1 -0
- data/spec/dummy/tmp/cache/527/990/shard_1792%3Akey +1 -0
- data/spec/dummy/tmp/cache/528/960/shard_1298%3Akey +1 -0
- data/spec/dummy/tmp/cache/528/990/shard_1487%3Akey +1 -0
- data/spec/dummy/tmp/cache/528/9A0/shard_1739%3Akey +1 -0
- data/spec/dummy/tmp/cache/528/9B0/shard_1586%3Akey +1 -0
- data/spec/dummy/tmp/cache/528/9E0/shard_1775%3Akey +1 -0
- data/spec/dummy/tmp/cache/528/A00/shard_1793%3Akey +1 -0
- data/spec/dummy/tmp/cache/529/9F0/shard_1479%3Akey +1 -0
- data/spec/dummy/tmp/cache/529/A30/shard_1677%3Akey +1 -0
- data/spec/dummy/tmp/cache/529/A50/shard_1776%3Akey +1 -0
- data/spec/dummy/tmp/cache/529/A80/shard_1884%3Akey +1 -0
- data/spec/dummy/tmp/cache/52A/A80/shard_1498%3Akey +1 -0
- data/spec/dummy/tmp/cache/52A/AA0/shard_1678%3Akey +1 -0
- data/spec/dummy/tmp/cache/52A/AF0/shard_1885%3Akey +1 -0
- data/spec/dummy/tmp/cache/52B/AF0/shard_1499%3Akey +1 -0
- data/spec/dummy/tmp/cache/52C/B90/shard_1689%3Akey +1 -0
- data/spec/dummy/tmp/cache/52E/CC0/shard_1898%3Akey +1 -0
- data/spec/dummy/tmp/cache/52F/D30/shard_1899%3Akey +1 -0
- data/spec/lib/action_controller/caching_spec.rb +49 -0
- data/spec/lib/active_record/association_spec.rb +41 -0
- data/spec/lib/active_record/attribute_methods_spec.rb +6 -0
- data/spec/lib/active_record/base_spec.rb +20 -4
- data/spec/lib/active_record/calculations_spec.rb +117 -0
- data/spec/lib/active_record/finder_methods_spec.rb +22 -0
- data/spec/lib/active_record/query_cache_spec.rb +288 -0
- data/spec/lib/active_record/query_methods_spec.rb +33 -0
- data/spec/lib/active_record/relation_spec.rb +9 -0
- data/spec/lib/active_record/spawn_methods_spec.rb +43 -0
- data/spec/lib/database_server_spec.rb +73 -14
- data/spec/lib/default_shard_spec.rb +24 -0
- data/spec/lib/r_spec_helper_spec.rb +20 -0
- data/spec/lib/rails_spec.rb +31 -0
- data/spec/lib/shackles_spec.rb +68 -14
- data/spec/models/shard_spec.rb +30 -9
- metadata +1132 -94
- data/lib/switchman/cache_extensions.rb +0 -12
- data/spec/dummy/tmp/cache/2E2/830/shard%2F2 +0 -0
- data/spec/dummy/tmp/cache/2E3/840/shard%2F3 +0 -0
- data/spec/dummy/tmp/cache/313/970/shard%2F30 +0 -0
- data/spec/dummy/tmp/cache/314/980/shard%2F31 +0 -0
- data/spec/dummy/tmp/cache/316/9D0/shard%2F60 +0 -0
- data/spec/dummy/tmp/cache/317/990/shard%2F16 +0 -0
- data/spec/dummy/tmp/cache/318/9A0/shard%2F17 +0 -0
- data/spec/dummy/tmp/cache/318/9D0/shard%2F44 +0 -0
- data/spec/dummy/tmp/cache/319/9E0/shard%2F45 +0 -0
- data/spec/dummy/tmp/cache/319/A30/shard%2F90 +0 -0
- data/spec/dummy/tmp/cache/321/AA0/shard%2F89 +0 -0
- data/spec/dummy/tmp/cache/322/AC0/shard%2F99 +0 -1
- data/spec/dummy/tmp/cache/345/DB0/shard%2F131 +0 -1
- data/spec/dummy/tmp/cache/346/DB0/shard%2F123 +0 -0
- data/spec/dummy/tmp/cache/346/DD0/shard%2F222 +0 -1
- data/spec/dummy/tmp/cache/346/DE0/shard%2F150 +0 -0
- data/spec/dummy/tmp/cache/346/DF0/shard%2F240 +0 -1
- data/spec/dummy/tmp/cache/347/DA0/shard%2F106 +0 -1
- data/spec/dummy/tmp/cache/347/DC0/shard%2F124 +0 -0
- data/spec/dummy/tmp/cache/347/DC0/shard%2F205 +0 -1
- data/spec/dummy/tmp/cache/347/E10/shard%2F250 +0 -1
- data/spec/dummy/tmp/cache/348/DF0/shard%2F143 +0 -1
- data/spec/dummy/tmp/cache/348/DF0/shard%2F224 +0 -1
- data/spec/dummy/tmp/cache/348/E10/shard%2F161 +0 -1
- data/spec/dummy/tmp/cache/349/DD0/shard%2F117 +0 -1
- data/spec/dummy/tmp/cache/349/E40/shard%2F180 +0 -1
- data/spec/dummy/tmp/cache/34A/DF0/shard%2F208 +0 -1
- data/spec/dummy/tmp/cache/34A/E10/shard%2F145 +0 -1
- data/spec/dummy/tmp/cache/34A/E60/shard%2F190 +0 -1
- data/spec/dummy/tmp/cache/34B/E30/shard%2F155 +0 -1
- data/spec/dummy/tmp/cache/34D/E30/shard%2F139 +0 -0
- data/spec/dummy/tmp/cache/34E/E50/shard%2F149 +0 -0
- data/spec/dummy/tmp/cache/353/EF0/shard%2F199 +0 -1
- data/spec/lib/cache_extensions_spec.rb +0 -27
@@ -20,6 +20,31 @@ module Switchman
|
|
20
20
|
super
|
21
21
|
end
|
22
22
|
end
|
23
|
+
|
24
|
+
def find_or_instantiator_by_attributes(match, attributes, *args)
|
25
|
+
primary_shard.activate { super }
|
26
|
+
end
|
27
|
+
|
28
|
+
def exists?(id = false)
|
29
|
+
id = id.id if ActiveRecord::Base === id
|
30
|
+
return false if id.nil?
|
31
|
+
|
32
|
+
join_dependency = construct_join_dependency_for_association_find
|
33
|
+
relation = construct_relation_for_association_find(join_dependency)
|
34
|
+
relation = relation.except(:select, :order).select("1 AS one").limit(1)
|
35
|
+
|
36
|
+
case id
|
37
|
+
when Array, Hash
|
38
|
+
relation = relation.where(id)
|
39
|
+
else
|
40
|
+
relation = relation.where(table[primary_key].eq(id)) if id
|
41
|
+
end
|
42
|
+
|
43
|
+
activate { return true if connection.select_value(relation, "#{name} Exists") }
|
44
|
+
false
|
45
|
+
rescue ThrowResult
|
46
|
+
false
|
47
|
+
end
|
23
48
|
end
|
24
49
|
end
|
25
50
|
end
|
@@ -17,7 +17,8 @@ module Switchman
|
|
17
17
|
name = '%s (%.1fms)' % [payload[:name], event.duration]
|
18
18
|
sql = payload[:sql].squeeze(' ')
|
19
19
|
binds = nil
|
20
|
-
|
20
|
+
shard = payload[:shard]
|
21
|
+
shard = " [shard #{shard[:id]} #{shard[:env]}]" if shard
|
21
22
|
|
22
23
|
unless (payload[:binds] || []).empty?
|
23
24
|
binds = " " + payload[:binds].map { |col,v|
|
@@ -36,7 +37,7 @@ module Switchman
|
|
36
37
|
name = color(name, self.class::MAGENTA, true)
|
37
38
|
end
|
38
39
|
|
39
|
-
debug " #{name} #{sql}#{binds}
|
40
|
+
debug " #{name} #{sql}#{binds}#{shard}"
|
40
41
|
end
|
41
42
|
end
|
42
43
|
end
|
@@ -3,10 +3,81 @@ module Switchman
|
|
3
3
|
# needs to be included in the same class as ::ActiveRecord::ConnectionAdapters::QueryCache
|
4
4
|
# *after* that module is included
|
5
5
|
module QueryCache
|
6
|
+
# thread local accessors to replace @query_cache_enabled
|
7
|
+
def query_cache_enabled
|
8
|
+
Thread.current[:query_cache_enabled]
|
9
|
+
end
|
10
|
+
|
11
|
+
def query_cache_enabled=(value)
|
12
|
+
Thread.current[:query_cache_enabled] = value
|
13
|
+
end
|
14
|
+
|
15
|
+
# basically wholesale repeat of the methods from the original (see
|
16
|
+
# https://github.com/rails/rails/blob/master/activerecord/lib/active_record/connection_adapters/abstract/query_cache.rb),
|
17
|
+
# but with self.query_cache_enabled and self.query_cache_enabled= instead
|
18
|
+
# of @query_cache_enabled.
|
19
|
+
|
20
|
+
def enable_query_cache!
|
21
|
+
self.query_cache_enabled = true
|
22
|
+
end
|
23
|
+
|
24
|
+
def disable_query_cache!
|
25
|
+
self.query_cache_enabled = false
|
26
|
+
end
|
27
|
+
|
28
|
+
def cache
|
29
|
+
old, self.query_cache_enabled = query_cache_enabled, true
|
30
|
+
yield
|
31
|
+
ensure
|
32
|
+
self.query_cache_enabled = old
|
33
|
+
clear_query_cache unless self.query_cache_enabled
|
34
|
+
end
|
35
|
+
|
36
|
+
def uncached
|
37
|
+
old, self.query_cache_enabled = query_cache_enabled, false
|
38
|
+
yield
|
39
|
+
ensure
|
40
|
+
self.query_cache_enabled = old
|
41
|
+
end
|
42
|
+
|
43
|
+
def select_all(arel, name = nil, binds = [])
|
44
|
+
if self.query_cache_enabled && !locked?(arel)
|
45
|
+
sql = to_sql(arel, binds)
|
46
|
+
cache_sql(sql, binds) { super(sql, name, binds) }
|
47
|
+
else
|
48
|
+
super
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
# no reason to define these on the including class directly. the super
|
53
|
+
# works just as well from a method on the included module
|
54
|
+
[:insert, :update, :delete].each do |method_name|
|
55
|
+
class_eval <<-end_code, __FILE__, __LINE__ + 1
|
56
|
+
def #{method_name}(*args)
|
57
|
+
clear_query_cache if self.query_cache_enabled
|
58
|
+
super
|
59
|
+
end
|
60
|
+
end_code
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
6
64
|
def cache_sql(sql, *args, &block)
|
7
65
|
# have to include the shard id in the cache key because of switching dbs on the same connection
|
8
66
|
super("#{self.shard.id}::#{sql}", *args, &block)
|
9
67
|
end
|
68
|
+
|
69
|
+
def self.included(base)
|
70
|
+
base.class_eval do
|
71
|
+
# when we call insert, update, and delete, we want it to find the
|
72
|
+
# definitions from this module (which will then find the definitions
|
73
|
+
# from ActiveRecord::ConnectionAdapters::DatabaseStatements as
|
74
|
+
# 'super'), not the ones defined on base by
|
75
|
+
# ActiveRecord::ConnectionAdapters::QueryCache.
|
76
|
+
remove_method :insert
|
77
|
+
remove_method :update
|
78
|
+
remove_method :delete
|
79
|
+
end
|
80
|
+
end
|
10
81
|
end
|
11
82
|
end
|
12
83
|
end
|
@@ -6,10 +6,12 @@ module Switchman
|
|
6
6
|
# An array or relation of shards
|
7
7
|
# An AR object (query runs against that object's associated_shards)
|
8
8
|
# shard_source_value is one of:
|
9
|
-
# :implicit
|
10
|
-
# :explicit
|
11
|
-
# :
|
12
|
-
#
|
9
|
+
# :implicit - inferred from current shard when relation was created, or primary key where clause
|
10
|
+
# :explicit - explicit set on the relation
|
11
|
+
# :association - a special value that scopes from associations use to use slightly different logic
|
12
|
+
# for foreign key transposition
|
13
|
+
# :to_a - a special value that Relation#to_a uses when querying multiple shards to
|
14
|
+
# remove primary keys from conditions that aren't applicable to the current shard
|
13
15
|
attr_accessor :shard_value, :shard_source_value
|
14
16
|
|
15
17
|
def shard(value, source = :explicit)
|
@@ -43,12 +45,11 @@ module Switchman
|
|
43
45
|
end
|
44
46
|
|
45
47
|
def build_where(opts, other = [])
|
46
|
-
source_shard = Shard.current(klass.shard_category)
|
47
48
|
case opts
|
48
49
|
when Hash, Arel::Nodes::Node
|
49
50
|
predicates = super
|
50
51
|
infer_shards_from_primary_key(predicates) if shard_source_value == :implicit && shard_value.is_a?(Shard)
|
51
|
-
predicates = transpose_predicates(predicates,
|
52
|
+
predicates = transpose_predicates(predicates, nil, primary_shard) if shard_source_value != :explicit
|
52
53
|
predicates
|
53
54
|
else
|
54
55
|
super
|
@@ -73,11 +74,24 @@ module Switchman
|
|
73
74
|
end
|
74
75
|
end
|
75
76
|
|
77
|
+
# the shard value as an array or a relation
|
78
|
+
def all_shards
|
79
|
+
case shard_value
|
80
|
+
when Shard, DefaultShard
|
81
|
+
[shard_value]
|
82
|
+
when ::ActiveRecord::Base
|
83
|
+
shard_value.respond_to?(:associated_shards) ? shard_value.associated_shards : [shard_value.shard]
|
84
|
+
else
|
85
|
+
shard_value
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
76
89
|
private
|
77
90
|
def infer_shards_from_primary_key(predicates)
|
78
91
|
primary_key = predicates.detect do |predicate|
|
79
92
|
predicate.is_a?(Arel::Nodes::Binary) && predicate.left.is_a?(Arel::Attributes::Attribute) &&
|
80
|
-
|
93
|
+
predicate.left.relation.is_a?(Arel::Table) && predicate.left.relation.engine == klass &&
|
94
|
+
klass.primary_key == predicate.left.name
|
81
95
|
end
|
82
96
|
if primary_key
|
83
97
|
case primary_key.right
|
@@ -115,45 +129,66 @@ module Switchman
|
|
115
129
|
end
|
116
130
|
end
|
117
131
|
|
118
|
-
def transposable_attribute_type(
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
return :foreign
|
132
|
+
def transposable_attribute_type(relation, column)
|
133
|
+
if sharded_primary_key?(relation, column)
|
134
|
+
:primary
|
135
|
+
elsif sharded_foreign_key?(relation, column)
|
136
|
+
:foreign
|
124
137
|
end
|
125
138
|
end
|
126
139
|
|
127
|
-
def
|
128
|
-
@@
|
129
|
-
@@
|
130
|
-
|
131
|
-
@@foreign_keys[attribute.relation.table_name][attribute.name]
|
132
|
-
else
|
133
|
-
models = attribute.relation.engine.descendants.select{|d| d.table_name == attribute.relation.table_name}
|
134
|
-
models << attribute.relation.engine unless attribute.relation.engine == ::ActiveRecord::Base
|
140
|
+
def models_for_table(table_name)
|
141
|
+
@@models_for_table ||= {}
|
142
|
+
@@models_for_table[table_name] ||= ::ActiveRecord::Base.descendants.select { |d| d.table_name == table_name }
|
143
|
+
end
|
135
144
|
|
136
|
-
|
137
|
-
|
145
|
+
def sharded_foreign_key?(relation, column)
|
146
|
+
models_for_table(relation.table_name).any? { |m| m.sharded_column?(column) }
|
138
147
|
end
|
139
148
|
|
140
|
-
def sharded_primary_key?(
|
141
|
-
|
149
|
+
def sharded_primary_key?(relation, column)
|
150
|
+
relation.engine.primary_key == column
|
142
151
|
end
|
143
152
|
|
153
|
+
def source_shard_for_foreign_key(relation, column)
|
154
|
+
reflection = nil
|
155
|
+
models_for_table(relation.table_name).each do |model|
|
156
|
+
reflection = model.send(:reflection_for_integer_attribute, column)
|
157
|
+
break if reflection
|
158
|
+
end
|
159
|
+
return Shard.current(klass.shard_category) if reflection.options[:polymorphic]
|
160
|
+
Shard.current(reflection.klass.shard_category)
|
161
|
+
end
|
162
|
+
|
163
|
+
def relation_and_column(attribute)
|
164
|
+
column = attribute.name
|
165
|
+
attribute = attribute.relation if attribute.relation.is_a?(Arel::Nodes::TableAlias)
|
166
|
+
[attribute.relation, column]
|
167
|
+
end
|
144
168
|
# semi-private
|
145
169
|
public
|
146
170
|
def transpose_predicates(predicates, source_shard, target_shard, remove_nonlocal_primary_keys = false)
|
147
171
|
predicates.map do |predicate|
|
148
|
-
next predicate unless predicate.is_a?(Arel::Nodes::Binary)
|
172
|
+
next predicate unless predicate.is_a?(Arel::Nodes::Binary)
|
173
|
+
next predicate unless predicate.left.is_a?(Arel::Attributes::Attribute)
|
174
|
+
relation, column = relation_and_column(predicate.left)
|
175
|
+
next predicate unless (type = transposable_attribute_type(relation, column))
|
149
176
|
|
150
177
|
remove = true if type == :primary && remove_nonlocal_primary_keys && predicate.left.relation.engine == klass
|
178
|
+
current_source_shard =
|
179
|
+
if source_shard
|
180
|
+
source_shard
|
181
|
+
elsif type == :primary
|
182
|
+
Shard.current(klass.shard_category)
|
183
|
+
elsif type == :foreign
|
184
|
+
source_shard_for_foreign_key(relation, column)
|
185
|
+
end
|
151
186
|
|
152
187
|
new_right_value = case predicate.right
|
153
188
|
when Array
|
154
189
|
local_ids = []
|
155
190
|
predicate.right.each do |value|
|
156
|
-
local_id = Shard.relative_id_for(value,
|
191
|
+
local_id = Shard.relative_id_for(value, current_source_shard, target_shard)
|
157
192
|
local_ids << local_id unless remove && local_id > Shard::IDS_PER_SHARD
|
158
193
|
end
|
159
194
|
local_ids
|
@@ -161,13 +196,13 @@ module Switchman
|
|
161
196
|
# look for a bind param with a matching column name
|
162
197
|
if @bind_params && idx = @bind_params.find_index{|b| b.is_a?(Array) && b.first.try(:name) == predicate.left}
|
163
198
|
column, value = @bind_params[idx]
|
164
|
-
local_id = Shard.relative_id_for(value,
|
199
|
+
local_id = Shard.relative_id_for(value, current_source_shard, target_shard)
|
165
200
|
local_id = [] if remove && local_id > Shard::IDS_PER_SHARD
|
166
201
|
@bind_params[idx] = [column, local_id]
|
167
202
|
end
|
168
203
|
predicate.right
|
169
204
|
else
|
170
|
-
local_id = Shard.relative_id_for(predicate.right,
|
205
|
+
local_id = Shard.relative_id_for(predicate.right, current_source_shard, target_shard)
|
171
206
|
local_id = [] if remove && local_id > Shard::IDS_PER_SHARD
|
172
207
|
local_id
|
173
208
|
end
|
@@ -3,7 +3,12 @@ module Switchman
|
|
3
3
|
module Relation
|
4
4
|
def self.included(klass)
|
5
5
|
klass::SINGLE_VALUE_METHODS.concat [ :shard, :shard_source ]
|
6
|
-
|
6
|
+
|
7
|
+
%w{exec_queries update_all delete_all}.each do |method|
|
8
|
+
klass.alias_method_chain(method, :deshackles)
|
9
|
+
end
|
10
|
+
|
11
|
+
%w{initialize exec_queries update_all delete_all new create create!}.each do |method|
|
7
12
|
klass.alias_method_chain(method, :sharding)
|
8
13
|
end
|
9
14
|
end
|
@@ -23,6 +28,28 @@ module Switchman
|
|
23
28
|
relation
|
24
29
|
end
|
25
30
|
|
31
|
+
def new_with_sharding(*args, &block)
|
32
|
+
primary_shard.activate(klass.shard_category) { new_without_sharding(*args, &block) }
|
33
|
+
end
|
34
|
+
|
35
|
+
def create_with_sharding(*args, &block)
|
36
|
+
primary_shard.activate(klass.shard_category) { create_without_sharding(*args, &block) }
|
37
|
+
end
|
38
|
+
|
39
|
+
def create_with_sharding!(*args, &block)
|
40
|
+
primary_shard.activate(klass.shard_category) { create_without_sharding!(*args, &block) }
|
41
|
+
end
|
42
|
+
|
43
|
+
def exec_queries_with_deshackles(*args)
|
44
|
+
if self.lock_value
|
45
|
+
db = Shard.current(shard_category).database_server
|
46
|
+
if ::Shackles.environment != db.shackles_environment
|
47
|
+
return db.unshackle { exec_queries_without_deshackles(*args) }
|
48
|
+
end
|
49
|
+
end
|
50
|
+
exec_queries_without_deshackles(*args)
|
51
|
+
end
|
52
|
+
|
26
53
|
def exec_queries_with_sharding
|
27
54
|
return @records if loaded?
|
28
55
|
results = self.activate{|relation| relation.send(:exec_queries_without_sharding) }
|
@@ -36,6 +63,15 @@ module Switchman
|
|
36
63
|
|
37
64
|
%w{update_all delete_all}.each do |method|
|
38
65
|
class_eval <<-RUBY
|
66
|
+
def #{method}_with_deshackles(*args)
|
67
|
+
db = Shard.current(shard_category).database_server
|
68
|
+
if ::Shackles.environment != db.shackles_environment
|
69
|
+
db.unshackle { #{method}_without_deshackles(*args) }
|
70
|
+
else
|
71
|
+
#{method}_without_deshackles(*args)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
39
75
|
def #{method}_with_sharding(*args)
|
40
76
|
self.activate{|relation| relation.#{method}_without_sharding(*args)}
|
41
77
|
end
|
@@ -43,22 +79,15 @@ module Switchman
|
|
43
79
|
end
|
44
80
|
|
45
81
|
def activate(&block)
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
shard_value.activate(klass.shard_category) { yield(self, shard_value) }
|
51
|
-
when Array, ::ActiveRecord::Relation, ::ActiveRecord::Base
|
52
|
-
# TODO: implement local limit to avoid querying extra shards
|
53
|
-
if shard_value.is_a?(::ActiveRecord::Base)
|
54
|
-
if shard_value.respond_to?(:associated_shards)
|
55
|
-
shards = shard_value.associated_shards
|
56
|
-
else
|
57
|
-
shards = [shard_value.shard]
|
58
|
-
end
|
82
|
+
shards = all_shards
|
83
|
+
if (Array === shards && shards.length == 1)
|
84
|
+
if shards.first == DefaultShard || shards.first == Shard.current(klass.shard_category)
|
85
|
+
yield(self, shards.first)
|
59
86
|
else
|
60
|
-
shards
|
87
|
+
shards.first.activate(klass.shard_category) { yield(self, shard_value) }
|
61
88
|
end
|
89
|
+
else
|
90
|
+
# TODO: implement local limit to avoid querying extra shards
|
62
91
|
Shard.with_each_shard(shards, [klass.shard_category]) do
|
63
92
|
shard(Shard.current(klass.shard_category), :to_a).activate(&block)
|
64
93
|
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module Switchman
|
2
|
+
module ActiveRecord
|
3
|
+
module SpawnMethods
|
4
|
+
def merge(r)
|
5
|
+
return self unless r
|
6
|
+
return to_a & r if r.is_a?(Array)
|
7
|
+
|
8
|
+
# have to figure out shard stuff *before* conditions are merged
|
9
|
+
if shard_value != r.shard_value
|
10
|
+
if (r.shard_source_value == :implicit)
|
11
|
+
final_shard_value = shard_value
|
12
|
+
final_primary_shard = primary_shard
|
13
|
+
final_shard_source_value = shard_source_value
|
14
|
+
elsif (shard_source_value == :implicit)
|
15
|
+
final_shard_value = r.shard_value
|
16
|
+
final_primary_shard = r.primary_shard
|
17
|
+
final_shard_source_value = r.shard_source_value
|
18
|
+
else
|
19
|
+
final_shard_source_value = [:explicit, :association].detect do |source_value|
|
20
|
+
shard_source_value == source_value || r.shard_source_value == source_value
|
21
|
+
end
|
22
|
+
raise "unknown shard_source_value" unless final_shard_source_value
|
23
|
+
|
24
|
+
# have to merge shard_value
|
25
|
+
lhs_shard_value = all_shards
|
26
|
+
rhs_shard_value = r.all_shards
|
27
|
+
if (::ActiveRecord::Relation === lhs_shard_value &&
|
28
|
+
::ActiveRecord::Relation === rhs_shard_value)
|
29
|
+
final_shard_value = lhs_shard_value.merge(rhs_shard_value)
|
30
|
+
final_primary_shard = Shard.default
|
31
|
+
else
|
32
|
+
final_shard_value = lhs_shard_value.to_a & rhs_shard_value.to_a
|
33
|
+
return none if final_shard_value.length == 0
|
34
|
+
final_primary_shard = final_shard_value.first
|
35
|
+
final_shard_value = final_shard_value.first if final_shard_value.length == 1
|
36
|
+
end
|
37
|
+
end
|
38
|
+
elsif shard_source_value != r.shard_source_value
|
39
|
+
final_shard_source_value = [:explicit, :association, :implicit].detect do |source_value|
|
40
|
+
shard_source_value == source_value || r.shard_source_value == source_value
|
41
|
+
end
|
42
|
+
raise "unknown shard_source_value" unless final_shard_source_value
|
43
|
+
|
44
|
+
result = super
|
45
|
+
result.shard_source_value = final_shard_source_value
|
46
|
+
return result
|
47
|
+
else
|
48
|
+
# nothing fancy
|
49
|
+
return super
|
50
|
+
end
|
51
|
+
|
52
|
+
# change the primary shard if necessary before merging
|
53
|
+
result = if primary_shard != final_primary_shard && r.primary_shard != final_primary_shard
|
54
|
+
lhs = shard(final_primary_shard)
|
55
|
+
r = r.shard(final_primary_shard)
|
56
|
+
lhs.merge(r)
|
57
|
+
elsif primary_shard != final_primary_shard
|
58
|
+
lhs = shard(final_primary_shard)
|
59
|
+
lhs.merge(r)
|
60
|
+
elsif r.primary_shard != final_primary_shard
|
61
|
+
r = r.shard(final_primary_shard)
|
62
|
+
super(r)
|
63
|
+
else
|
64
|
+
super
|
65
|
+
end
|
66
|
+
|
67
|
+
result.shard_value = final_shard_value
|
68
|
+
result.shard_source_value = final_shard_source_value
|
69
|
+
|
70
|
+
result
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Switchman
|
2
|
+
module ActiveSupport
|
3
|
+
module Cache
|
4
|
+
module Store
|
5
|
+
def initialize_with_sharding(options = nil)
|
6
|
+
options ||= {}
|
7
|
+
options[:namespace] ||= lambda { Shard.current.default? ? nil : "shard_#{Shard.current.id}" }
|
8
|
+
initialize_without_sharding(options)
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.included(klass)
|
12
|
+
klass.alias_method_chain(:initialize, :sharding)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -1,4 +1,11 @@
|
|
1
1
|
module Switchman
|
2
|
+
module ConnectionError
|
3
|
+
def self.===(other)
|
4
|
+
return true if defined?(PG::Error) && PG::Error === other
|
5
|
+
false
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
2
9
|
class ConnectionPoolProxy
|
3
10
|
delegate :spec, :connected?, :default_schema, :with_connection,
|
4
11
|
:to => :current_pool
|
@@ -19,8 +26,12 @@ module Switchman
|
|
19
26
|
Shard.current(@category)
|
20
27
|
end
|
21
28
|
|
29
|
+
def active_shackles_environment
|
30
|
+
::Rails.env.test? ? :master : active_shard.database_server.shackles_environment
|
31
|
+
end
|
32
|
+
|
22
33
|
def current_pool
|
23
|
-
pool = self.default_pool if active_shard.default?
|
34
|
+
pool = self.default_pool if active_shard.database_server == Shard.default.database_server && active_shackles_environment == :master && active_shard.database_server.shareable?
|
24
35
|
pool = @connection_pools[pool_key] ||= create_pool unless pool
|
25
36
|
pool.shard = active_shard
|
26
37
|
pool
|
@@ -28,7 +39,24 @@ module Switchman
|
|
28
39
|
|
29
40
|
def connection
|
30
41
|
pool = current_pool
|
31
|
-
|
42
|
+
begin
|
43
|
+
pool.connection
|
44
|
+
rescue ConnectionError
|
45
|
+
raise if active_shard.database_server == Shard.default.database_server && active_shackles_environment == :master
|
46
|
+
configs = active_shard.database_server.config(active_shackles_environment)
|
47
|
+
raise unless configs.is_a?(Array)
|
48
|
+
configs.each_with_index do |config, idx|
|
49
|
+
pool = create_pool(config.dup)
|
50
|
+
begin
|
51
|
+
connection = pool.connection
|
52
|
+
rescue ConnectionError
|
53
|
+
raise if idx == configs.length - 1
|
54
|
+
next
|
55
|
+
end
|
56
|
+
@connection_pools[pool_key] = pool
|
57
|
+
break connection
|
58
|
+
end
|
59
|
+
end
|
32
60
|
end
|
33
61
|
|
34
62
|
%w{release_connection disconnect! clear_reloadable_connections! verify_active_connections! clear_stale_cached_connections!}.each do |method|
|
@@ -42,12 +70,26 @@ module Switchman
|
|
42
70
|
protected
|
43
71
|
|
44
72
|
def pool_key
|
45
|
-
|
73
|
+
[active_shackles_environment,
|
74
|
+
active_shard.database_server.shareable? ? active_shard.database_server.pool_key : active_shard]
|
46
75
|
end
|
47
76
|
|
48
|
-
def create_pool
|
77
|
+
def create_pool(config = nil)
|
49
78
|
shard = active_shard
|
50
|
-
|
79
|
+
unless config
|
80
|
+
if shard != Shard.default
|
81
|
+
config = shard.database_server.config(active_shackles_environment)
|
82
|
+
config = config.first if config.is_a?(Array)
|
83
|
+
config = config.dup
|
84
|
+
else
|
85
|
+
config = default_pool.spec.config
|
86
|
+
if config[active_shackles_environment].is_a?(Hash)
|
87
|
+
config = config.merge(config[active_shackles_environment])
|
88
|
+
else
|
89
|
+
config = config.dup
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
51
93
|
spec = ::ActiveRecord::Base::ConnectionSpecification.new(config, "#{config[:adapter]}_connection")
|
52
94
|
# unfortunately the AR code that does this require logic can't really be
|
53
95
|
# called in isolation
|