switchman 0.0.1 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (642) hide show
  1. checksums.yaml +13 -5
  2. data/app/models/switchman/shard.rb +64 -19
  3. data/lib/switchman/action_controller/caching.rb +26 -0
  4. data/lib/switchman/active_record/abstract_adapter.rb +11 -0
  5. data/lib/switchman/active_record/association.rb +37 -3
  6. data/lib/switchman/active_record/attribute_methods.rb +3 -2
  7. data/lib/switchman/active_record/base.rb +44 -15
  8. data/lib/switchman/active_record/calculations.rb +145 -3
  9. data/lib/switchman/active_record/connection_handler.rb +11 -0
  10. data/lib/switchman/active_record/connection_pool.rb +5 -3
  11. data/lib/switchman/active_record/finder_methods.rb +25 -0
  12. data/lib/switchman/active_record/log_subscriber.rb +3 -2
  13. data/lib/switchman/active_record/query_cache.rb +71 -0
  14. data/lib/switchman/active_record/query_methods.rb +64 -29
  15. data/lib/switchman/active_record/relation.rb +44 -15
  16. data/lib/switchman/active_record/spawn_methods.rb +74 -0
  17. data/lib/switchman/active_support/cache.rb +17 -0
  18. data/lib/switchman/connection_pool_proxy.rb +47 -5
  19. data/lib/switchman/database_server.rb +131 -63
  20. data/lib/switchman/default_shard.rb +38 -23
  21. data/lib/switchman/engine.rb +71 -8
  22. data/lib/switchman/r_spec_helper.rb +41 -34
  23. data/lib/switchman/rails.rb +21 -0
  24. data/lib/switchman/shackles.rb +20 -20
  25. data/lib/switchman/sharded_instrumenter.rb +19 -0
  26. data/lib/switchman/test_helper.rb +3 -3
  27. data/lib/switchman/version.rb +1 -1
  28. data/lib/switchman.rb +1 -1
  29. data/spec/dummy/app/models/root.rb +5 -0
  30. data/spec/dummy/app/models/user.rb +6 -0
  31. data/spec/dummy/db/migrate/20140123154135_add_parent_id_to_users.rb +5 -0
  32. data/spec/dummy/db/migrate/20140219183820_create_roots.rb +9 -0
  33. data/spec/dummy/db/schema.rb +8 -1
  34. data/spec/dummy/log/development.log +135 -0
  35. data/spec/dummy/log/test.log +86777 -29398
  36. data/spec/dummy/tmp/cache/{317/9C0/shard%2F43 → 14A/870/key} +1 -1
  37. data/spec/dummy/tmp/cache/{319/A10/shard%2F72 → 2E9/8A0/shard%2F9} +1 -1
  38. data/spec/dummy/tmp/cache/317/9E0/shard%2F61 +0 -0
  39. data/spec/dummy/tmp/cache/318/9F0/shard%2F62 +0 -0
  40. data/spec/dummy/tmp/cache/{319/9F0/shard%2F54 → 318/A00/shard%2F71} +1 -1
  41. data/spec/dummy/tmp/cache/31A/A10/shard%2F64 +0 -0
  42. data/spec/dummy/tmp/cache/31A/A20/shard%2F73 +0 -0
  43. data/spec/dummy/tmp/cache/31B/A20/shard%2F65 +0 -0
  44. data/spec/dummy/tmp/cache/31B/A30/shard%2F74 +0 -0
  45. data/spec/dummy/tmp/cache/{31B/9E0/shard%2F29 → 31C/A40/shard%2F75} +1 -1
  46. data/spec/dummy/tmp/cache/31D/A30/shard%2F58 +0 -0
  47. data/spec/dummy/tmp/cache/31D/A40/shard%2F67 +0 -0
  48. data/spec/dummy/tmp/cache/31E/A40/shard%2F59 +0 -0
  49. data/spec/dummy/tmp/cache/31E/A50/shard%2F68 +0 -0
  50. data/spec/dummy/tmp/cache/320/A80/shard%2F79 +0 -0
  51. data/spec/dummy/tmp/cache/343/D90/shard%2F210 +0 -0
  52. data/spec/dummy/tmp/cache/344/D70/shard%2F103 +0 -0
  53. data/spec/dummy/tmp/cache/345/D80/shard%2F104 +0 -0
  54. data/spec/dummy/tmp/cache/345/DB0/shard%2F212 +0 -0
  55. data/spec/dummy/tmp/cache/345/DC0/shard%2F140 +0 -0
  56. data/spec/dummy/tmp/cache/345/DC0/shard%2F302 +0 -0
  57. data/spec/dummy/tmp/cache/346/D90/shard%2F105 +0 -0
  58. data/spec/dummy/tmp/cache/346/DD0/shard%2F303 +0 -0
  59. data/spec/dummy/tmp/cache/346/DF0/shard%2F321 +0 -0
  60. data/spec/dummy/tmp/cache/347/E00/shard%2F322 +0 -0
  61. data/spec/dummy/tmp/cache/347/E50/shard%2F610 +0 -0
  62. data/spec/dummy/tmp/cache/348/DD0/shard%2F206 +0 -0
  63. data/spec/dummy/tmp/cache/348/DE0/shard%2F215 +0 -0
  64. data/spec/dummy/tmp/cache/{316/980/shard%2F15 → 348/E10/shard%2F323} +1 -1
  65. data/spec/dummy/tmp/cache/348/E30/shard%2F422 +0 -0
  66. data/spec/dummy/tmp/cache/348/E40/shard%2F350 +0 -0
  67. data/spec/dummy/tmp/cache/348/E50/shard%2F602 +0 -0
  68. data/spec/dummy/tmp/cache/348/E80/shard%2F710 +0 -0
  69. data/spec/dummy/tmp/cache/348/E90/shard%2F800 +0 -0
  70. data/spec/dummy/tmp/cache/349/DE0/shard%2F126 +0 -0
  71. data/spec/dummy/tmp/cache/349/DF0/shard%2F216 +0 -0
  72. data/spec/dummy/tmp/cache/349/E00/shard%2F225 +0 -0
  73. data/spec/dummy/tmp/cache/349/E20/shard%2F243 +0 -0
  74. data/spec/dummy/tmp/cache/349/E20/shard%2F405 +0 -0
  75. data/spec/dummy/tmp/cache/349/E30/shard%2F333 +0 -0
  76. data/spec/dummy/tmp/cache/349/E40/shard%2F423 +0 -0
  77. data/spec/dummy/tmp/cache/349/E60/shard%2F603 +0 -0
  78. data/spec/dummy/tmp/cache/34A/DF0/shard%2F127 +0 -0
  79. data/spec/dummy/tmp/cache/34A/E10/shard%2F226 +0 -0
  80. data/spec/dummy/tmp/cache/34A/E30/shard%2F244 +0 -0
  81. data/spec/dummy/tmp/cache/34A/E50/shard%2F505 +0 -0
  82. data/spec/dummy/tmp/cache/34A/E60/shard%2F433 +0 -0
  83. data/spec/dummy/tmp/cache/34A/E70/shard%2F523 +0 -0
  84. data/spec/dummy/tmp/cache/34A/E80/shard%2F613 +0 -0
  85. data/spec/dummy/tmp/cache/34A/EA0/shard%2F712 +0 -0
  86. data/spec/dummy/tmp/cache/34A/EC0/shard%2F730 +0 -0
  87. data/spec/dummy/tmp/cache/34B/E00/shard%2F128 +1 -0
  88. data/spec/dummy/tmp/cache/34B/E00/shard%2F209 +0 -0
  89. data/spec/dummy/tmp/cache/34B/E10/shard%2F137 +0 -0
  90. data/spec/dummy/tmp/cache/34B/E30/shard%2F236 +0 -0
  91. data/spec/dummy/tmp/cache/34B/E50/shard%2F254 +0 -0
  92. data/spec/dummy/tmp/cache/34B/E60/shard%2F344 +0 -0
  93. data/spec/dummy/tmp/cache/34B/E60/shard%2F506 +0 -0
  94. data/spec/dummy/tmp/cache/34B/E80/shard%2F605 +0 -0
  95. data/spec/dummy/tmp/cache/34B/E90/shard%2F290 +0 -0
  96. data/spec/dummy/tmp/cache/34B/EC0/shard%2F560 +0 -0
  97. data/spec/dummy/tmp/cache/34B/ED0/shard%2F731 +0 -0
  98. data/spec/dummy/tmp/cache/34B/ED0/shard%2F812 +0 -0
  99. data/spec/dummy/tmp/cache/34C/E20/shard%2F138 +0 -0
  100. data/spec/dummy/tmp/cache/34C/E20/shard%2F219 +1 -0
  101. data/spec/dummy/tmp/cache/34C/E30/shard%2F228 +0 -0
  102. data/spec/dummy/tmp/cache/34C/E40/shard%2F237 +0 -0
  103. data/spec/dummy/tmp/cache/34C/E40/shard%2F318 +0 -0
  104. data/spec/dummy/tmp/cache/34C/E50/shard%2F246 +1 -0
  105. data/spec/dummy/tmp/cache/34C/E60/shard%2F255 +0 -0
  106. data/spec/dummy/tmp/cache/34C/E80/shard%2F192 +0 -0
  107. data/spec/dummy/tmp/cache/34C/EA0/shard%2F372 +0 -0
  108. data/spec/dummy/tmp/cache/34C/EA0/shard%2F453 +0 -0
  109. data/spec/dummy/tmp/cache/34C/EB0/shard%2F462 +0 -0
  110. data/spec/dummy/tmp/cache/34C/ED0/shard%2F480 +0 -0
  111. data/spec/dummy/tmp/cache/34C/ED0/shard%2F561 +0 -0
  112. data/spec/dummy/tmp/cache/34C/EF0/shard%2F822 +0 -0
  113. data/spec/dummy/tmp/cache/34C/EF0/shard%2F903 +0 -0
  114. data/spec/dummy/tmp/cache/34C/F00/shard%2F912 +0 -0
  115. data/spec/dummy/tmp/cache/34D/E50/shard%2F319 +0 -0
  116. data/spec/dummy/tmp/cache/34D/E80/shard%2F508 +0 -0
  117. data/spec/dummy/tmp/cache/34D/E90/shard%2F355 +0 -0
  118. data/spec/dummy/tmp/cache/34D/EA0/shard%2F364 +0 -0
  119. data/spec/dummy/tmp/cache/34D/EB0/shard%2F373 +0 -0
  120. data/spec/dummy/tmp/cache/34D/EB0/shard%2F454 +0 -0
  121. data/spec/dummy/tmp/cache/34D/EB0/shard%2F616 +0 -0
  122. data/spec/dummy/tmp/cache/34D/EC0/shard%2F544 +0 -0
  123. data/spec/dummy/tmp/cache/34D/ED0/shard%2F391 +0 -0
  124. data/spec/dummy/tmp/cache/34D/ED0/shard%2F715 +0 -0
  125. data/spec/dummy/tmp/cache/34D/F00/shard%2F661 +0 -0
  126. data/spec/dummy/tmp/cache/34D/F10/shard%2F913 +0 -0
  127. data/spec/dummy/tmp/cache/34E/E80/shard%2F257 +0 -0
  128. data/spec/dummy/tmp/cache/34E/EA0/shard%2F275 +0 -0
  129. data/spec/dummy/tmp/cache/34E/EB0/shard%2F365 +0 -0
  130. data/spec/dummy/tmp/cache/34E/EC0/shard%2F617 +0 -0
  131. data/spec/dummy/tmp/cache/34E/ED0/shard%2F545 +0 -0
  132. data/spec/dummy/tmp/cache/34E/EE0/shard%2F635 +0 -0
  133. data/spec/dummy/tmp/cache/34E/EF0/shard%2F482 +1 -0
  134. data/spec/dummy/tmp/cache/34E/EF0/shard%2F644 +0 -0
  135. data/spec/dummy/tmp/cache/34E/F00/shard%2F491 +0 -0
  136. data/spec/dummy/tmp/cache/34E/F00/shard%2F734 +1 -0
  137. data/spec/dummy/tmp/cache/34E/F40/shard%2F932 +0 -0
  138. data/spec/dummy/tmp/cache/34E/F50/shard%2F941 +0 -0
  139. data/spec/dummy/tmp/cache/34F/E80/shard%2F249 +0 -0
  140. data/spec/dummy/tmp/cache/34F/EA0/shard%2F267 +0 -0
  141. data/spec/dummy/tmp/cache/34F/EB0/shard%2F276 +0 -0
  142. data/spec/dummy/tmp/cache/34F/ED0/shard%2F375 +0 -0
  143. data/spec/dummy/tmp/cache/34F/ED0/shard%2F456 +0 -0
  144. data/spec/dummy/tmp/cache/34F/EE0/shard%2F465 +0 -0
  145. data/spec/dummy/tmp/cache/34F/EF0/shard%2F636 +0 -0
  146. data/spec/dummy/tmp/cache/34F/F00/shard%2F645 +0 -0
  147. data/spec/dummy/tmp/cache/34F/F10/shard%2F573 +0 -0
  148. data/spec/dummy/tmp/cache/34F/F20/shard%2F906 +0 -0
  149. data/spec/dummy/tmp/cache/34F/F40/shard%2F681 +0 -0
  150. data/spec/dummy/tmp/cache/34F/F50/shard%2F771 +0 -0
  151. data/spec/dummy/tmp/cache/34F/F60/shard%2F780 +0 -0
  152. data/spec/dummy/tmp/cache/34F/F60/shard%2F861 +0 -0
  153. data/spec/dummy/tmp/cache/34F/F60/shard%2F942 +0 -0
  154. data/spec/dummy/tmp/cache/350/EC0/shard%2F358 +0 -0
  155. data/spec/dummy/tmp/cache/350/EE0/shard%2F376 +0 -0
  156. data/spec/dummy/tmp/cache/350/EE0/shard%2F457 +0 -0
  157. data/spec/dummy/tmp/cache/350/EE0/shard%2F538 +0 -0
  158. data/spec/dummy/tmp/cache/350/EE0/shard%2F619 +0 -0
  159. data/spec/dummy/tmp/cache/350/EF0/shard%2F385 +0 -0
  160. data/spec/dummy/tmp/cache/350/EF0/shard%2F466 +0 -0
  161. data/spec/dummy/tmp/cache/350/EF0/shard%2F709 +0 -0
  162. data/spec/dummy/tmp/cache/350/F00/shard%2F394 +0 -0
  163. data/spec/dummy/tmp/cache/350/F20/shard%2F574 +0 -0
  164. data/spec/dummy/tmp/cache/350/F20/shard%2F736 +0 -0
  165. data/spec/dummy/tmp/cache/350/F30/shard%2F664 +0 -0
  166. data/spec/dummy/tmp/cache/350/F30/shard%2F745 +0 -0
  167. data/spec/dummy/tmp/cache/350/F50/shard%2F763 +0 -0
  168. data/spec/dummy/tmp/cache/350/F60/shard%2F772 +0 -0
  169. data/spec/dummy/tmp/cache/350/F70/shard%2F781 +0 -0
  170. data/spec/dummy/tmp/cache/350/F70/shard%2F862 +0 -0
  171. data/spec/dummy/tmp/cache/351/ED0/shard%2F359 +0 -0
  172. data/spec/dummy/tmp/cache/351/EF0/shard%2F296 +0 -0
  173. data/spec/dummy/tmp/cache/351/F00/shard%2F386 +0 -0
  174. data/spec/dummy/tmp/cache/351/F10/shard%2F476 +0 -0
  175. data/spec/dummy/tmp/cache/351/F10/shard%2F557 +0 -0
  176. data/spec/dummy/tmp/cache/351/F20/shard%2F485 +0 -0
  177. data/spec/dummy/tmp/cache/351/F30/shard%2F494 +0 -0
  178. data/spec/dummy/tmp/cache/351/F30/shard%2F737 +0 -0
  179. data/spec/dummy/tmp/cache/351/F40/shard%2F665 +0 -0
  180. data/spec/dummy/tmp/cache/351/F40/shard%2F746 +0 -0
  181. data/spec/dummy/tmp/cache/351/F70/shard%2F935 +0 -0
  182. data/spec/dummy/tmp/cache/352/F00/shard%2F297 +0 -0
  183. data/spec/dummy/tmp/cache/352/F00/shard%2F378 +0 -0
  184. data/spec/dummy/tmp/cache/352/F00/shard%2F459 +0 -0
  185. data/spec/dummy/tmp/cache/352/F10/shard%2F468 +1 -0
  186. data/spec/dummy/tmp/cache/352/F20/shard%2F639 +1 -0
  187. data/spec/dummy/tmp/cache/352/F30/shard%2F486 +0 -0
  188. data/spec/dummy/tmp/cache/352/F50/shard%2F585 +0 -0
  189. data/spec/dummy/tmp/cache/352/F50/shard%2F909 +0 -0
  190. data/spec/dummy/tmp/cache/352/F60/shard%2F594 +0 -0
  191. data/spec/dummy/tmp/cache/352/F70/shard%2F684 +0 -0
  192. data/spec/dummy/tmp/cache/352/F80/shard%2F774 +0 -0
  193. data/spec/dummy/tmp/cache/352/F80/shard%2F936 +0 -0
  194. data/spec/dummy/tmp/cache/352/F90/shard%2F783 +0 -0
  195. data/spec/dummy/tmp/cache/352/F90/shard%2F864 +0 -0
  196. data/spec/dummy/tmp/cache/352/F90/shard%2F945 +1 -0
  197. data/spec/dummy/tmp/cache/352/FA0/shard%2F873 +0 -0
  198. data/spec/dummy/tmp/cache/352/FC0/shard%2F972 +0 -0
  199. data/spec/dummy/tmp/cache/353/F50/shard%2F577 +1 -0
  200. data/spec/dummy/tmp/cache/353/F50/shard%2F739 +0 -0
  201. data/spec/dummy/tmp/cache/353/F60/shard%2F748 +0 -0
  202. data/spec/dummy/tmp/cache/353/F70/shard%2F595 +0 -0
  203. data/spec/dummy/tmp/cache/353/F90/shard%2F775 +0 -0
  204. data/spec/dummy/tmp/cache/353/FA0/shard%2F784 +0 -0
  205. data/spec/dummy/tmp/cache/353/FD0/shard%2F892 +0 -0
  206. data/spec/dummy/tmp/cache/354/000/shard%2F992 +0 -0
  207. data/spec/dummy/tmp/cache/354/F30/shard%2F389 +1 -0
  208. data/spec/dummy/tmp/cache/354/F40/shard%2F479 +0 -0
  209. data/spec/dummy/tmp/cache/354/F50/shard%2F488 +0 -0
  210. data/spec/dummy/tmp/cache/354/F90/shard%2F929 +0 -0
  211. data/spec/dummy/tmp/cache/354/FA0/shard%2F938 +0 -0
  212. data/spec/dummy/tmp/cache/354/FD0/shard%2F965 +0 -0
  213. data/spec/dummy/tmp/cache/354/FE0/shard%2F893 +0 -0
  214. data/spec/dummy/tmp/cache/354/FF0/shard%2F983 +0 -0
  215. data/spec/dummy/tmp/cache/355/010/shard%2F993 +0 -0
  216. data/spec/dummy/tmp/cache/355/F60/shard%2F489 +0 -0
  217. data/spec/dummy/tmp/cache/355/F80/shard%2F588 +0 -0
  218. data/spec/dummy/tmp/cache/355/F90/shard%2F678 +0 -0
  219. data/spec/dummy/tmp/cache/355/FA0/shard%2F687 +0 -0
  220. data/spec/dummy/tmp/cache/355/FB0/shard%2F777 +1 -0
  221. data/spec/dummy/tmp/cache/355/FB0/shard%2F858 +0 -0
  222. data/spec/dummy/tmp/cache/355/FB0/shard%2F939 +0 -0
  223. data/spec/dummy/tmp/cache/355/FD0/shard%2F795 +0 -0
  224. data/spec/dummy/tmp/cache/355/FD0/shard%2F876 +0 -0
  225. data/spec/dummy/tmp/cache/355/FE0/shard%2F966 +0 -0
  226. data/spec/dummy/tmp/cache/356/000/shard%2F895 +1 -0
  227. data/spec/dummy/tmp/cache/356/FA0/shard%2F679 +0 -0
  228. data/spec/dummy/tmp/cache/356/FB0/shard%2F688 +0 -0
  229. data/spec/dummy/tmp/cache/356/FC0/shard%2F859 +0 -0
  230. data/spec/dummy/tmp/cache/356/FE0/shard%2F796 +0 -0
  231. data/spec/dummy/tmp/cache/356/FE0/shard%2F877 +0 -0
  232. data/spec/dummy/tmp/cache/357/020/shard%2F986 +0 -0
  233. data/spec/dummy/tmp/cache/357/FC0/shard%2F689 +1 -0
  234. data/spec/dummy/tmp/cache/358/000/shard%2F879 +0 -0
  235. data/spec/dummy/tmp/cache/358/FF0/shard%2F789 +0 -0
  236. data/spec/dummy/tmp/cache/372/470/shard%2F1010 +0 -0
  237. data/spec/dummy/tmp/cache/373/4A0/shard%2F1110 +0 -0
  238. data/spec/dummy/tmp/cache/374/490/shard%2F1012 +1 -0
  239. data/spec/dummy/tmp/cache/375/4C0/shard%2F2003 +1 -0
  240. data/spec/dummy/tmp/cache/375/510/shard%2F1400 +0 -0
  241. data/spec/dummy/tmp/cache/376/4E0/shard%2F1041 +0 -0
  242. data/spec/dummy/tmp/cache/376/4E0/shard%2F1203 +0 -0
  243. data/spec/dummy/tmp/cache/376/4F0/shard%2F1212 +0 -0
  244. data/spec/dummy/tmp/cache/376/500/shard%2F1221 +0 -0
  245. data/spec/dummy/tmp/cache/377/4C0/shard%2F1015 +0 -0
  246. data/spec/dummy/tmp/cache/377/500/shard%2F1213 +0 -0
  247. data/spec/dummy/tmp/cache/377/530/shard%2F1240 +0 -0
  248. data/spec/dummy/tmp/cache/377/530/shard%2F1321 +0 -0
  249. data/spec/dummy/tmp/cache/377/530/shard%2F1402 +0 -0
  250. data/spec/dummy/tmp/cache/378/4E0/shard%2F1106 +0 -0
  251. data/spec/dummy/tmp/cache/378/510/shard%2F1133 +0 -0
  252. data/spec/dummy/tmp/cache/378/520/shard%2F1142 +0 -0
  253. data/spec/dummy/tmp/cache/378/530/shard%2F1313 +0 -0
  254. data/spec/dummy/tmp/cache/378/540/shard%2F1241 +0 -0
  255. data/spec/dummy/tmp/cache/378/540/shard%2F1403 +0 -0
  256. data/spec/dummy/tmp/cache/378/550/shard%2F1331 +0 -0
  257. data/spec/dummy/tmp/cache/378/560/shard%2F1340 +0 -0
  258. data/spec/dummy/tmp/cache/379/4F0/shard%2F1026 +0 -0
  259. data/spec/dummy/tmp/cache/379/500/shard%2F1035 +0 -0
  260. data/spec/dummy/tmp/cache/379/510/shard%2F1044 +0 -0
  261. data/spec/dummy/tmp/cache/379/520/shard%2F1134 +0 -0
  262. data/spec/dummy/tmp/cache/379/530/shard%2F1224 +0 -0
  263. data/spec/dummy/tmp/cache/379/550/shard%2F1080 +0 -0
  264. data/spec/dummy/tmp/cache/379/550/shard%2F1161 +0 -0
  265. data/spec/dummy/tmp/cache/379/550/shard%2F1404 +1 -0
  266. data/spec/dummy/tmp/cache/379/560/shard%2F1332 +0 -0
  267. data/spec/dummy/tmp/cache/379/570/shard%2F1260 +0 -0
  268. data/spec/dummy/tmp/cache/379/570/shard%2F1341 +0 -0
  269. data/spec/dummy/tmp/cache/379/5A0/shard%2F1611 +1 -0
  270. data/spec/dummy/tmp/cache/37A/4E0/shard%2F1009 +0 -0
  271. data/spec/dummy/tmp/cache/37A/4F0/shard%2F1018 +0 -0
  272. data/spec/dummy/tmp/cache/37A/500/shard%2F1027 +0 -0
  273. data/spec/dummy/tmp/cache/37A/510/shard%2F1117 +0 -0
  274. data/spec/dummy/tmp/cache/37A/520/shard%2F1045 +0 -0
  275. data/spec/dummy/tmp/cache/37A/570/shard%2F1252 +0 -0
  276. data/spec/dummy/tmp/cache/37A/580/shard%2F1261 +0 -0
  277. data/spec/dummy/tmp/cache/37A/5C0/shard%2F1702 +0 -0
  278. data/spec/dummy/tmp/cache/37A/5D0/shard%2F1711 +1 -0
  279. data/spec/dummy/tmp/cache/37B/500/shard%2F1019 +0 -0
  280. data/spec/dummy/tmp/cache/37B/510/shard%2F1028 +1 -0
  281. data/spec/dummy/tmp/cache/37B/510/shard%2F1109 +0 -0
  282. data/spec/dummy/tmp/cache/37B/540/shard%2F1136 +0 -0
  283. data/spec/dummy/tmp/cache/37B/580/shard%2F1253 +0 -0
  284. data/spec/dummy/tmp/cache/37B/590/shard%2F1181 +0 -0
  285. data/spec/dummy/tmp/cache/37B/5A0/shard%2F1190 +0 -0
  286. data/spec/dummy/tmp/cache/37B/5B0/shard%2F1523 +0 -0
  287. data/spec/dummy/tmp/cache/37B/5C0/shard%2F1370 +0 -0
  288. data/spec/dummy/tmp/cache/37B/600/shard%2F1811 +1 -0
  289. data/spec/dummy/tmp/cache/37C/530/shard%2F1038 +0 -0
  290. data/spec/dummy/tmp/cache/37C/550/shard%2F1137 +0 -0
  291. data/spec/dummy/tmp/cache/37C/560/shard%2F1065 +0 -0
  292. data/spec/dummy/tmp/cache/37C/580/shard%2F1164 +0 -0
  293. data/spec/dummy/tmp/cache/37C/590/shard%2F1092 +0 -0
  294. data/spec/dummy/tmp/cache/37C/590/shard%2F1335 +1 -0
  295. data/spec/dummy/tmp/cache/37C/5A0/shard%2F1182 +0 -0
  296. data/spec/dummy/tmp/cache/37C/5A0/shard%2F1263 +0 -0
  297. data/spec/dummy/tmp/cache/37C/5B0/shard%2F1191 +1 -0
  298. data/spec/dummy/tmp/cache/37C/5B0/shard%2F1434 +0 -0
  299. data/spec/dummy/tmp/cache/37C/5C0/shard%2F1605 +1 -0
  300. data/spec/dummy/tmp/cache/37C/5F0/shard%2F1470 +0 -0
  301. data/spec/dummy/tmp/cache/37C/620/shard%2F1821 +0 -0
  302. data/spec/dummy/tmp/cache/37C/620/shard%2F1902 +1 -0
  303. data/spec/dummy/tmp/cache/37C/640/shard%2F1920 +1 -0
  304. data/spec/dummy/tmp/cache/37D/540/shard%2F1039 +0 -0
  305. data/spec/dummy/tmp/cache/37D/560/shard%2F1057 +0 -0
  306. data/spec/dummy/tmp/cache/37D/590/shard%2F1246 +0 -0
  307. data/spec/dummy/tmp/cache/37D/590/shard%2F1408 +0 -0
  308. data/spec/dummy/tmp/cache/37D/5A0/shard%2F1093 +0 -0
  309. data/spec/dummy/tmp/cache/37D/5E0/shard%2F1372 +0 -0
  310. data/spec/dummy/tmp/cache/37D/5F0/shard%2F1381 +0 -0
  311. data/spec/dummy/tmp/cache/37D/610/shard%2F1642 +0 -0
  312. data/spec/dummy/tmp/cache/37D/610/shard%2F1804 +0 -0
  313. data/spec/dummy/tmp/cache/37E/570/shard%2F1058 +0 -0
  314. data/spec/dummy/tmp/cache/37E/570/shard%2F1139 +0 -0
  315. data/spec/dummy/tmp/cache/37E/580/shard%2F1229 +0 -0
  316. data/spec/dummy/tmp/cache/37E/5A0/shard%2F1247 +0 -0
  317. data/spec/dummy/tmp/cache/37E/5A0/shard%2F1409 +0 -0
  318. data/spec/dummy/tmp/cache/37E/5C0/shard%2F1346 +0 -0
  319. data/spec/dummy/tmp/cache/37E/5F0/shard%2F1292 +0 -0
  320. data/spec/dummy/tmp/cache/37E/5F0/shard%2F1373 +0 -0
  321. data/spec/dummy/tmp/cache/37E/5F0/shard%2F1535 +0 -0
  322. data/spec/dummy/tmp/cache/37E/600/shard%2F1382 +0 -0
  323. data/spec/dummy/tmp/cache/37E/620/shard%2F1805 +0 -0
  324. data/spec/dummy/tmp/cache/37E/640/shard%2F1661 +1 -0
  325. data/spec/dummy/tmp/cache/37F/5A0/shard%2F1158 +0 -0
  326. data/spec/dummy/tmp/cache/37F/5B0/shard%2F1167 +0 -0
  327. data/spec/dummy/tmp/cache/37F/5B0/shard%2F1248 +1 -0
  328. data/spec/dummy/tmp/cache/37F/5C0/shard%2F1095 +1 -0
  329. data/spec/dummy/tmp/cache/37F/5E0/shard%2F1275 +0 -0
  330. data/spec/dummy/tmp/cache/37F/5E0/shard%2F1437 +0 -0
  331. data/spec/dummy/tmp/cache/37F/600/shard%2F1455 +0 -0
  332. data/spec/dummy/tmp/cache/37F/600/shard%2F1536 +0 -0
  333. data/spec/dummy/tmp/cache/37F/610/shard%2F1464 +0 -0
  334. data/spec/dummy/tmp/cache/37F/620/shard%2F1473 +1 -0
  335. data/spec/dummy/tmp/cache/37F/630/shard%2F1482 +0 -0
  336. data/spec/dummy/tmp/cache/37F/640/shard%2F1491 +0 -0
  337. data/spec/dummy/tmp/cache/37F/640/shard%2F1653 +0 -0
  338. data/spec/dummy/tmp/cache/380/5C0/shard%2F1168 +0 -0
  339. data/spec/dummy/tmp/cache/380/5E0/shard%2F1429 +0 -0
  340. data/spec/dummy/tmp/cache/380/5F0/shard%2F1195 +0 -0
  341. data/spec/dummy/tmp/cache/380/5F0/shard%2F1276 +0 -0
  342. data/spec/dummy/tmp/cache/380/610/shard%2F1375 +0 -0
  343. data/spec/dummy/tmp/cache/380/620/shard%2F1384 +0 -0
  344. data/spec/dummy/tmp/cache/380/620/shard%2F1465 +0 -0
  345. data/spec/dummy/tmp/cache/380/640/shard%2F1645 +1 -0
  346. data/spec/dummy/tmp/cache/380/640/shard%2F1726 +1 -0
  347. data/spec/dummy/tmp/cache/380/650/shard%2F1492 +0 -0
  348. data/spec/dummy/tmp/cache/380/650/shard%2F1654 +0 -0
  349. data/spec/dummy/tmp/cache/380/660/shard%2F1906 +0 -0
  350. data/spec/dummy/tmp/cache/380/670/shard%2F1591 +0 -0
  351. data/spec/dummy/tmp/cache/380/670/shard%2F1753 +0 -0
  352. data/spec/dummy/tmp/cache/381/5F0/shard%2F1349 +0 -0
  353. data/spec/dummy/tmp/cache/381/600/shard%2F1196 +0 -0
  354. data/spec/dummy/tmp/cache/381/610/shard%2F1286 +0 -0
  355. data/spec/dummy/tmp/cache/381/620/shard%2F1295 +0 -0
  356. data/spec/dummy/tmp/cache/381/630/shard%2F1547 +1 -0
  357. data/spec/dummy/tmp/cache/381/650/shard%2F1565 +1 -0
  358. data/spec/dummy/tmp/cache/381/660/shard%2F1493 +1 -0
  359. data/spec/dummy/tmp/cache/381/670/shard%2F1745 +1 -0
  360. data/spec/dummy/tmp/cache/381/670/shard%2F1907 +0 -0
  361. data/spec/dummy/tmp/cache/381/680/shard%2F1592 +0 -0
  362. data/spec/dummy/tmp/cache/381/680/shard%2F1754 +0 -0
  363. data/spec/dummy/tmp/cache/381/6C0/shard%2F1790 +1 -0
  364. data/spec/dummy/tmp/cache/382/5F0/shard%2F1098 +0 -0
  365. data/spec/dummy/tmp/cache/382/600/shard%2F1269 +0 -0
  366. data/spec/dummy/tmp/cache/382/610/shard%2F1278 +1 -0
  367. data/spec/dummy/tmp/cache/382/620/shard%2F1287 +0 -0
  368. data/spec/dummy/tmp/cache/382/630/shard%2F1296 +0 -0
  369. data/spec/dummy/tmp/cache/382/640/shard%2F1467 +1 -0
  370. data/spec/dummy/tmp/cache/382/650/shard%2F1557 +0 -0
  371. data/spec/dummy/tmp/cache/382/690/shard%2F1674 +1 -0
  372. data/spec/dummy/tmp/cache/382/6A0/shard%2F1845 +1 -0
  373. data/spec/dummy/tmp/cache/382/6D0/shard%2F1953 +1 -0
  374. data/spec/dummy/tmp/cache/382/700/shard%2F1980 +0 -0
  375. data/spec/dummy/tmp/cache/383/610/shard%2F1189 +0 -0
  376. data/spec/dummy/tmp/cache/383/630/shard%2F1369 +0 -0
  377. data/spec/dummy/tmp/cache/383/640/shard%2F1378 +0 -0
  378. data/spec/dummy/tmp/cache/383/660/shard%2F1639 +1 -0
  379. data/spec/dummy/tmp/cache/383/680/shard%2F1576 +1 -0
  380. data/spec/dummy/tmp/cache/383/690/shard%2F1828 +1 -0
  381. data/spec/dummy/tmp/cache/383/6C0/shard%2F1774 +1 -0
  382. data/spec/dummy/tmp/cache/383/700/shard%2F1891 +0 -0
  383. data/spec/dummy/tmp/cache/383/700/shard%2F1972 +1 -0
  384. data/spec/dummy/tmp/cache/384/6B0/shard%2F1838 +0 -0
  385. data/spec/dummy/tmp/cache/384/700/shard%2F1883 +1 -0
  386. data/spec/dummy/tmp/cache/384/710/shard%2F1892 +0 -0
  387. data/spec/dummy/tmp/cache/386/690/shard%2F1399 +0 -0
  388. data/spec/dummy/tmp/cache/386/6D0/shard%2F1759 +1 -0
  389. data/spec/dummy/tmp/cache/386/6F0/shard%2F1858 +1 -0
  390. data/spec/dummy/tmp/cache/386/750/shard%2F1993 +1 -0
  391. data/spec/dummy/tmp/cache/388/710/shard%2F1698 +1 -0
  392. data/spec/dummy/tmp/cache/3A3/EA0/shard%2F10101 +1 -0
  393. data/spec/dummy/tmp/cache/3A3/EC0/shard%2F11010 +1 -0
  394. data/spec/dummy/tmp/cache/3A6/EB0/shard%2F10005 +1 -0
  395. data/spec/dummy/tmp/cache/3A6/ED0/shard%2F10104 +1 -0
  396. data/spec/dummy/tmp/cache/3A7/EC0/shard%2F10006 +1 -0
  397. data/spec/dummy/tmp/cache/3A7/F10/shard%2F10051 +1 -0
  398. data/spec/dummy/tmp/cache/3A8/F50/shard%2F10322 +1 -0
  399. data/spec/dummy/tmp/cache/3A9/F10/shard%2F10035 +1 -0
  400. data/spec/dummy/tmp/cache/3A9/F90/shard%2F11403 +1 -0
  401. data/spec/dummy/tmp/cache/3AA/F40/shard%2F10216 +1 -0
  402. data/spec/dummy/tmp/cache/3AA/FB0/shard%2F11332 +1 -0
  403. data/spec/dummy/tmp/cache/3AB/030/shard%2F11720 +1 -0
  404. data/spec/dummy/tmp/cache/3AB/F10/shard%2F10019 +1 -0
  405. data/spec/dummy/tmp/cache/3AB/F40/shard%2F10127 +1 -0
  406. data/spec/dummy/tmp/cache/3AB/F50/shard%2F11027 +1 -0
  407. data/spec/dummy/tmp/cache/3AB/F80/shard%2F10244 +1 -0
  408. data/spec/dummy/tmp/cache/3AC/020/shard%2F10731 +1 -0
  409. data/spec/dummy/tmp/cache/3AC/020/shard%2F11541 +1 -0
  410. data/spec/dummy/tmp/cache/3AC/020/shard%2F11703 +1 -0
  411. data/spec/dummy/tmp/cache/3AC/F80/shard%2F10074 +1 -0
  412. data/spec/dummy/tmp/cache/3AC/F90/shard%2F10083 +1 -0
  413. data/spec/dummy/tmp/cache/3AC/FA0/shard%2F10173 +1 -0
  414. data/spec/dummy/tmp/cache/3AC/FF0/shard%2F11190 +1 -0
  415. data/spec/dummy/tmp/cache/3AD/020/shard%2F10480 +1 -0
  416. data/spec/dummy/tmp/cache/3AD/F70/shard%2F10138 +1 -0
  417. data/spec/dummy/tmp/cache/3AE/050/shard%2F11471 +1 -0
  418. data/spec/dummy/tmp/cache/3AE/080/shard%2F11822 +1 -0
  419. data/spec/dummy/tmp/cache/3AE/F90/shard%2F10067 +1 -0
  420. data/spec/dummy/tmp/cache/3AE/FF0/shard%2F11093 +1 -0
  421. data/spec/dummy/tmp/cache/3AF/070/shard%2F11643 +1 -0
  422. data/spec/dummy/tmp/cache/3AF/070/shard%2F11805 +1 -0
  423. data/spec/dummy/tmp/cache/3AF/FA0/shard%2F10068 +1 -0
  424. data/spec/dummy/tmp/cache/3AF/FF0/shard%2F11247 +1 -0
  425. data/spec/dummy/tmp/cache/3B0/040/shard%2F10636 +1 -0
  426. data/spec/dummy/tmp/cache/3B0/060/shard%2F11626 +1 -0
  427. data/spec/dummy/tmp/cache/3B0/0B0/shard%2F10942 +1 -0
  428. data/spec/dummy/tmp/cache/3B0/FC0/shard%2F10159 +1 -0
  429. data/spec/dummy/tmp/cache/3B1/040/shard%2F10466 +1 -0
  430. data/spec/dummy/tmp/cache/3B1/040/shard%2F11276 +1 -0
  431. data/spec/dummy/tmp/cache/3B1/050/shard%2F11609 +1 -0
  432. data/spec/dummy/tmp/cache/3B1/070/shard%2F10574 +1 -0
  433. data/spec/dummy/tmp/cache/3B1/070/shard%2F11465 +1 -0
  434. data/spec/dummy/tmp/cache/3B1/0A0/shard%2F11492 +1 -0
  435. data/spec/dummy/tmp/cache/3B1/0A0/shard%2F11654 +1 -0
  436. data/spec/dummy/tmp/cache/3B1/0E0/shard%2F11771 +1 -0
  437. data/spec/dummy/tmp/cache/3B2/050/shard%2F10386 +1 -0
  438. data/spec/dummy/tmp/cache/3B2/0C0/shard%2F11907 +1 -0
  439. data/spec/dummy/tmp/cache/3B2/0D0/shard%2F11592 +1 -0
  440. data/spec/dummy/tmp/cache/3B2/0D0/shard%2F11754 +1 -0
  441. data/spec/dummy/tmp/cache/3B2/110/shard%2F11952 +1 -0
  442. data/spec/dummy/tmp/cache/3B3/0C0/shard%2F11575 +1 -0
  443. data/spec/dummy/tmp/cache/3B3/0C0/shard%2F11737 +1 -0
  444. data/spec/dummy/tmp/cache/3B4/0B0/shard%2F11558 +1 -0
  445. data/spec/dummy/tmp/cache/3B4/0E0/shard%2F10775 +1 -0
  446. data/spec/dummy/tmp/cache/3B4/130/shard%2F11873 +1 -0
  447. data/spec/dummy/tmp/cache/3B4/160/shard%2F11981 +1 -0
  448. data/spec/dummy/tmp/cache/3B5/120/shard%2F11856 +1 -0
  449. data/spec/dummy/tmp/cache/3B5/130/shard%2F10893 +1 -0
  450. data/spec/dummy/tmp/cache/3B5/150/shard%2F11964 +1 -0
  451. data/spec/dummy/tmp/cache/3B5/160/shard%2F11892 +1 -0
  452. data/spec/dummy/tmp/cache/3B6/110/shard%2F11839 +1 -0
  453. data/spec/dummy/tmp/cache/3B6/120/shard%2F11686 +1 -0
  454. data/spec/dummy/tmp/cache/3B7/100/shard%2F10688 +1 -0
  455. data/spec/dummy/tmp/cache/3B7/110/shard%2F11669 +1 -0
  456. data/spec/dummy/tmp/cache/3B9/170/shard%2F11788 +1 -0
  457. data/spec/dummy/tmp/cache/3BC/1F0/shard%2F11998 +1 -0
  458. data/spec/dummy/tmp/cache/4B7/9C0/shard_12%3Akey +1 -0
  459. data/spec/dummy/tmp/cache/4B8/A30/shard_13%3Akey +1 -0
  460. data/spec/dummy/tmp/cache/4B9/AA0/shard_14%3Akey +1 -0
  461. data/spec/dummy/tmp/cache/4BA/B50/shard_51%3Akey +1 -0
  462. data/spec/dummy/tmp/cache/4BB/B90/shard_25%3Akey +1 -0
  463. data/spec/dummy/tmp/cache/4BB/BC0/shard_52%3Akey +1 -0
  464. data/spec/dummy/tmp/cache/4BC/C00/shard_26%3Akey +1 -0
  465. data/spec/dummy/tmp/cache/4BC/C50/shard_71%3Akey +1 -0
  466. data/spec/dummy/tmp/cache/4BD/CC0/shard_72%3Akey +1 -0
  467. data/spec/dummy/tmp/cache/4BD/CE0/shard_90%3Akey +1 -0
  468. data/spec/dummy/tmp/cache/4BE/D00/shard_46%3Akey +1 -0
  469. data/spec/dummy/tmp/cache/4BF/D70/shard_47%3Akey +1 -0
  470. data/spec/dummy/tmp/cache/4C0/DF0/shard_57%3Akey +1 -0
  471. data/spec/dummy/tmp/cache/4C0/E20/shard_84%3Akey +1 -0
  472. data/spec/dummy/tmp/cache/4C1/E60/shard_58%3Akey +1 -0
  473. data/spec/dummy/tmp/cache/4C1/E90/shard_85%3Akey +1 -0
  474. data/spec/dummy/tmp/cache/4C5/050/shard_89%3Akey +1 -0
  475. data/spec/dummy/tmp/cache/4E5/B10/shard_100%3Akey +1 -0
  476. data/spec/dummy/tmp/cache/4E6/B80/shard_101%3Akey +1 -0
  477. data/spec/dummy/tmp/cache/4E8/CA0/shard_220%3Akey +1 -0
  478. data/spec/dummy/tmp/cache/4E9/D10/shard_221%3Akey +1 -0
  479. data/spec/dummy/tmp/cache/4EA/D90/shard_150%3Akey +1 -0
  480. data/spec/dummy/tmp/cache/4EA/DC0/shard_420%3Akey +1 -0
  481. data/spec/dummy/tmp/cache/4EB/E00/shard_151%3Akey +1 -0
  482. data/spec/dummy/tmp/cache/4ED/EE0/shard_153%3Akey +1 -0
  483. data/spec/dummy/tmp/cache/4EE/F50/shard_154%3Akey +1 -0
  484. data/spec/dummy/tmp/cache/4EE/F80/shard_181%3Akey +1 -0
  485. data/spec/dummy/tmp/cache/4EE/F90/shard_352%3Akey +1 -0
  486. data/spec/dummy/tmp/cache/4EF/000/shard_272%3Akey +1 -0
  487. data/spec/dummy/tmp/cache/4EF/000/shard_353%3Akey +1 -0
  488. data/spec/dummy/tmp/cache/4EF/000/shard_515%3Akey +1 -0
  489. data/spec/dummy/tmp/cache/4EF/030/shard_380%3Akey +1 -0
  490. data/spec/dummy/tmp/cache/4EF/040/shard_632%3Akey +1 -0
  491. data/spec/dummy/tmp/cache/4EF/FF0/shard_182%3Akey +1 -0
  492. data/spec/dummy/tmp/cache/4F0/010/shard_138%3Akey +1 -0
  493. data/spec/dummy/tmp/cache/4F0/070/shard_273%3Akey +1 -0
  494. data/spec/dummy/tmp/cache/4F0/070/shard_516%3Akey +1 -0
  495. data/spec/dummy/tmp/cache/4F0/0A0/shard_381%3Akey +1 -0
  496. data/spec/dummy/tmp/cache/4F0/0B0/shard_633%3Akey +1 -0
  497. data/spec/dummy/tmp/cache/4F1/080/shard_139%3Akey +1 -0
  498. data/spec/dummy/tmp/cache/4F1/140/shard_814%3Akey +1 -0
  499. data/spec/dummy/tmp/cache/4F2/120/shard_167%3Akey +1 -0
  500. data/spec/dummy/tmp/cache/4F2/130/shard_419%3Akey +1 -0
  501. data/spec/dummy/tmp/cache/4F2/1B0/shard_815%3Akey +1 -0
  502. data/spec/dummy/tmp/cache/4F2/1E0/shard_923%3Akey +1 -0
  503. data/spec/dummy/tmp/cache/4F3/190/shard_168%3Akey +1 -0
  504. data/spec/dummy/tmp/cache/4F3/250/shard_924%3Akey +1 -0
  505. data/spec/dummy/tmp/cache/4F5/320/shard_755%3Akey +1 -0
  506. data/spec/dummy/tmp/cache/4F6/360/shard_567%3Akey +1 -0
  507. data/spec/dummy/tmp/cache/4F6/390/shard_756%3Akey +1 -0
  508. data/spec/dummy/tmp/cache/4F7/3D0/shard_568%3Akey +1 -0
  509. data/spec/dummy/tmp/cache/4F7/3E0/shard_658%3Akey +1 -0
  510. data/spec/dummy/tmp/cache/4F8/450/shard_659%3Akey +1 -0
  511. data/spec/dummy/tmp/cache/4F8/4C0/shard_884%3Akey +1 -0
  512. data/spec/dummy/tmp/cache/4F9/530/shard_885%3Akey +1 -0
  513. data/spec/dummy/tmp/cache/4FA/5A0/shard_967%3Akey +1 -0
  514. data/spec/dummy/tmp/cache/4FB/610/shard_968%3Akey +1 -0
  515. data/spec/dummy/tmp/cache/518/1C0/shard_1111%3Akey +1 -0
  516. data/spec/dummy/tmp/cache/519/230/shard_1112%3Akey +1 -0
  517. data/spec/dummy/tmp/cache/51A/2C0/shard_1050%3Akey +1 -0
  518. data/spec/dummy/tmp/cache/51B/3A0/shard_1600%3Akey +1 -0
  519. data/spec/dummy/tmp/cache/51C/410/shard_1601%3Akey +1 -0
  520. data/spec/dummy/tmp/cache/51D/4B0/shard_1710%3Akey +1 -0
  521. data/spec/dummy/tmp/cache/51E/4E0/shard_1351%3Akey +1 -0
  522. data/spec/dummy/tmp/cache/51F/550/shard_1352%3Akey +1 -0
  523. data/spec/dummy/tmp/cache/51F/570/shard_1532%3Akey +1 -0
  524. data/spec/dummy/tmp/cache/520/580/shard_1155%3Akey +1 -0
  525. data/spec/dummy/tmp/cache/520/5A0/shard_1416%3Akey +1 -0
  526. data/spec/dummy/tmp/cache/520/5D0/shard_1443%3Akey +1 -0
  527. data/spec/dummy/tmp/cache/520/5E0/shard_1452%3Akey +1 -0
  528. data/spec/dummy/tmp/cache/520/5E0/shard_1533%3Akey +1 -0
  529. data/spec/dummy/tmp/cache/520/5F0/shard_1461%3Akey +1 -0
  530. data/spec/dummy/tmp/cache/520/600/shard_1551%3Akey +1 -0
  531. data/spec/dummy/tmp/cache/521/5F0/shard_1156%3Akey +1 -0
  532. data/spec/dummy/tmp/cache/521/610/shard_1417%3Akey +1 -0
  533. data/spec/dummy/tmp/cache/521/620/shard_1507%3Akey +1 -0
  534. data/spec/dummy/tmp/cache/521/630/shard_1516%3Akey +1 -0
  535. data/spec/dummy/tmp/cache/521/640/shard_1444%3Akey +1 -0
  536. data/spec/dummy/tmp/cache/521/650/shard_1453%3Akey +1 -0
  537. data/spec/dummy/tmp/cache/521/660/shard_1462%3Akey +1 -0
  538. data/spec/dummy/tmp/cache/521/670/shard_1552%3Akey +1 -0
  539. data/spec/dummy/tmp/cache/521/680/shard_1480%3Akey +1 -0
  540. data/spec/dummy/tmp/cache/521/690/shard_1813%3Akey +1 -0
  541. data/spec/dummy/tmp/cache/522/630/shard_1049%3Akey +1 -0
  542. data/spec/dummy/tmp/cache/522/690/shard_1508%3Akey +1 -0
  543. data/spec/dummy/tmp/cache/522/6A0/shard_1517%3Akey +1 -0
  544. data/spec/dummy/tmp/cache/522/700/shard_1571%3Akey +1 -0
  545. data/spec/dummy/tmp/cache/522/700/shard_1733%3Akey +1 -0
  546. data/spec/dummy/tmp/cache/522/700/shard_1814%3Akey +1 -0
  547. data/spec/dummy/tmp/cache/522/740/shard_1850%3Akey +1 -0
  548. data/spec/dummy/tmp/cache/523/6F0/shard_1257%3Akey +1 -0
  549. data/spec/dummy/tmp/cache/523/730/shard_1617%3Akey +1 -0
  550. data/spec/dummy/tmp/cache/523/770/shard_1572%3Akey +1 -0
  551. data/spec/dummy/tmp/cache/523/770/shard_1734%3Akey +1 -0
  552. data/spec/dummy/tmp/cache/523/7B0/shard_1851%3Akey +1 -0
  553. data/spec/dummy/tmp/cache/524/760/shard_1258%3Akey +1 -0
  554. data/spec/dummy/tmp/cache/524/7A0/shard_1537%3Akey +1 -0
  555. data/spec/dummy/tmp/cache/524/7A0/shard_1618%3Akey +1 -0
  556. data/spec/dummy/tmp/cache/524/7C0/shard_1636%3Akey +1 -0
  557. data/spec/dummy/tmp/cache/524/820/shard_1690%3Akey +1 -0
  558. data/spec/dummy/tmp/cache/525/810/shard_1538%3Akey +1 -0
  559. data/spec/dummy/tmp/cache/525/820/shard_1709%3Akey +1 -0
  560. data/spec/dummy/tmp/cache/525/830/shard_1637%3Akey +1 -0
  561. data/spec/dummy/tmp/cache/525/870/shard_1835%3Akey +1 -0
  562. data/spec/dummy/tmp/cache/525/8A0/shard_1862%3Akey +1 -0
  563. data/spec/dummy/tmp/cache/526/8D0/shard_1665%3Akey +1 -0
  564. data/spec/dummy/tmp/cache/526/8E0/shard_1755%3Akey +1 -0
  565. data/spec/dummy/tmp/cache/526/8E0/shard_1836%3Akey +1 -0
  566. data/spec/dummy/tmp/cache/526/910/shard_1863%3Akey +1 -0
  567. data/spec/dummy/tmp/cache/527/8F0/shard_1297%3Akey +1 -0
  568. data/spec/dummy/tmp/cache/527/920/shard_1486%3Akey +1 -0
  569. data/spec/dummy/tmp/cache/527/930/shard_1738%3Akey +1 -0
  570. data/spec/dummy/tmp/cache/527/940/shard_1585%3Akey +1 -0
  571. data/spec/dummy/tmp/cache/527/940/shard_1666%3Akey +1 -0
  572. data/spec/dummy/tmp/cache/527/950/shard_1756%3Akey +1 -0
  573. data/spec/dummy/tmp/cache/527/990/shard_1792%3Akey +1 -0
  574. data/spec/dummy/tmp/cache/528/960/shard_1298%3Akey +1 -0
  575. data/spec/dummy/tmp/cache/528/990/shard_1487%3Akey +1 -0
  576. data/spec/dummy/tmp/cache/528/9A0/shard_1739%3Akey +1 -0
  577. data/spec/dummy/tmp/cache/528/9B0/shard_1586%3Akey +1 -0
  578. data/spec/dummy/tmp/cache/528/9E0/shard_1775%3Akey +1 -0
  579. data/spec/dummy/tmp/cache/528/A00/shard_1793%3Akey +1 -0
  580. data/spec/dummy/tmp/cache/529/9F0/shard_1479%3Akey +1 -0
  581. data/spec/dummy/tmp/cache/529/A30/shard_1677%3Akey +1 -0
  582. data/spec/dummy/tmp/cache/529/A50/shard_1776%3Akey +1 -0
  583. data/spec/dummy/tmp/cache/529/A80/shard_1884%3Akey +1 -0
  584. data/spec/dummy/tmp/cache/52A/A80/shard_1498%3Akey +1 -0
  585. data/spec/dummy/tmp/cache/52A/AA0/shard_1678%3Akey +1 -0
  586. data/spec/dummy/tmp/cache/52A/AF0/shard_1885%3Akey +1 -0
  587. data/spec/dummy/tmp/cache/52B/AF0/shard_1499%3Akey +1 -0
  588. data/spec/dummy/tmp/cache/52C/B90/shard_1689%3Akey +1 -0
  589. data/spec/dummy/tmp/cache/52E/CC0/shard_1898%3Akey +1 -0
  590. data/spec/dummy/tmp/cache/52F/D30/shard_1899%3Akey +1 -0
  591. data/spec/lib/action_controller/caching_spec.rb +49 -0
  592. data/spec/lib/active_record/association_spec.rb +41 -0
  593. data/spec/lib/active_record/attribute_methods_spec.rb +6 -0
  594. data/spec/lib/active_record/base_spec.rb +20 -4
  595. data/spec/lib/active_record/calculations_spec.rb +117 -0
  596. data/spec/lib/active_record/finder_methods_spec.rb +22 -0
  597. data/spec/lib/active_record/query_cache_spec.rb +288 -0
  598. data/spec/lib/active_record/query_methods_spec.rb +33 -0
  599. data/spec/lib/active_record/relation_spec.rb +9 -0
  600. data/spec/lib/active_record/spawn_methods_spec.rb +43 -0
  601. data/spec/lib/database_server_spec.rb +73 -14
  602. data/spec/lib/default_shard_spec.rb +24 -0
  603. data/spec/lib/r_spec_helper_spec.rb +20 -0
  604. data/spec/lib/rails_spec.rb +31 -0
  605. data/spec/lib/shackles_spec.rb +68 -14
  606. data/spec/models/shard_spec.rb +30 -9
  607. metadata +1132 -94
  608. data/lib/switchman/cache_extensions.rb +0 -12
  609. data/spec/dummy/tmp/cache/2E2/830/shard%2F2 +0 -0
  610. data/spec/dummy/tmp/cache/2E3/840/shard%2F3 +0 -0
  611. data/spec/dummy/tmp/cache/313/970/shard%2F30 +0 -0
  612. data/spec/dummy/tmp/cache/314/980/shard%2F31 +0 -0
  613. data/spec/dummy/tmp/cache/316/9D0/shard%2F60 +0 -0
  614. data/spec/dummy/tmp/cache/317/990/shard%2F16 +0 -0
  615. data/spec/dummy/tmp/cache/318/9A0/shard%2F17 +0 -0
  616. data/spec/dummy/tmp/cache/318/9D0/shard%2F44 +0 -0
  617. data/spec/dummy/tmp/cache/319/9E0/shard%2F45 +0 -0
  618. data/spec/dummy/tmp/cache/319/A30/shard%2F90 +0 -0
  619. data/spec/dummy/tmp/cache/321/AA0/shard%2F89 +0 -0
  620. data/spec/dummy/tmp/cache/322/AC0/shard%2F99 +0 -1
  621. data/spec/dummy/tmp/cache/345/DB0/shard%2F131 +0 -1
  622. data/spec/dummy/tmp/cache/346/DB0/shard%2F123 +0 -0
  623. data/spec/dummy/tmp/cache/346/DD0/shard%2F222 +0 -1
  624. data/spec/dummy/tmp/cache/346/DE0/shard%2F150 +0 -0
  625. data/spec/dummy/tmp/cache/346/DF0/shard%2F240 +0 -1
  626. data/spec/dummy/tmp/cache/347/DA0/shard%2F106 +0 -1
  627. data/spec/dummy/tmp/cache/347/DC0/shard%2F124 +0 -0
  628. data/spec/dummy/tmp/cache/347/DC0/shard%2F205 +0 -1
  629. data/spec/dummy/tmp/cache/347/E10/shard%2F250 +0 -1
  630. data/spec/dummy/tmp/cache/348/DF0/shard%2F143 +0 -1
  631. data/spec/dummy/tmp/cache/348/DF0/shard%2F224 +0 -1
  632. data/spec/dummy/tmp/cache/348/E10/shard%2F161 +0 -1
  633. data/spec/dummy/tmp/cache/349/DD0/shard%2F117 +0 -1
  634. data/spec/dummy/tmp/cache/349/E40/shard%2F180 +0 -1
  635. data/spec/dummy/tmp/cache/34A/DF0/shard%2F208 +0 -1
  636. data/spec/dummy/tmp/cache/34A/E10/shard%2F145 +0 -1
  637. data/spec/dummy/tmp/cache/34A/E60/shard%2F190 +0 -1
  638. data/spec/dummy/tmp/cache/34B/E30/shard%2F155 +0 -1
  639. data/spec/dummy/tmp/cache/34D/E30/shard%2F139 +0 -0
  640. data/spec/dummy/tmp/cache/34E/E50/shard%2F149 +0 -0
  641. data/spec/dummy/tmp/cache/353/EF0/shard%2F199 +0 -1
  642. data/spec/lib/cache_extensions_spec.rb +0 -27
@@ -1,6 +1,6 @@
1
1
  module Switchman
2
2
  class DatabaseServer
3
- attr_accessor :id, :config
3
+ attr_accessor :id
4
4
 
5
5
  class << self
6
6
  def all
@@ -9,12 +9,12 @@ module Switchman
9
9
 
10
10
  def find(id_or_all)
11
11
  return self.all if id_or_all == :all
12
- return id_or_all.map { |id| self.database_servers[id || Rails.env] }.compact.uniq if id_or_all.is_a?(Array)
13
- database_servers[id_or_all || Rails.env]
12
+ return id_or_all.map { |id| self.database_servers[id || ::Rails.env] }.compact.uniq if id_or_all.is_a?(Array)
13
+ database_servers[id_or_all || ::Rails.env]
14
14
  end
15
15
 
16
16
  def create(settings = {})
17
- raise "database servers should be set up in database.yml" unless Rails.env.test?
17
+ raise "database servers should be set up in database.yml" unless ::Rails.env.test?
18
18
  id = 1
19
19
  while database_servers[id.to_s]; id += 1; end
20
20
  server = DatabaseServer.new({ :id => id.to_s }.merge(settings))
@@ -42,12 +42,13 @@ module Switchman
42
42
  end
43
43
 
44
44
  def initialize(settings = {})
45
- self.id = settings[:id]
46
- self.config = (settings[:config] || {}).symbolize_keys
45
+ @id = settings[:id]
46
+ @config = (settings[:config] || {}).symbolize_keys
47
+ @configs = {}
47
48
  end
48
49
 
49
50
  def destroy
50
- raise "database servers should be set up in database.yml" unless Rails.env.test?
51
+ raise "database servers should be set up in database.yml" unless ::Rails.env.test?
51
52
  self.class.send(:database_servers).delete(self.id) if self.id
52
53
  end
53
54
 
@@ -55,33 +56,83 @@ module Switchman
55
56
  @fake
56
57
  end
57
58
 
59
+ def config(environment = :master)
60
+ @configs[environment] ||= begin
61
+ if @config[environment].is_a?(Array)
62
+ @config[environment].map do |config|
63
+ config = @config.merge((config || {}).symbolize_keys)
64
+ # make sure Shackles doesn't get any brilliant ideas about choosing the first possible server
65
+ config.delete(environment)
66
+ config
67
+ end
68
+ elsif @config[environment].is_a?(Hash)
69
+ @config.merge(@config[environment])
70
+ else
71
+ @config
72
+ end
73
+ end
74
+ end
75
+
76
+ def shackles_environment
77
+ @shackles_environment || ::Shackles.environment
78
+ end
79
+
80
+ # locks this db to a specific environment, except for
81
+ # when doing writes (then it falls back to the current
82
+ # value of Shackles.environment)
83
+ def shackle!(environment = :slave)
84
+ @shackles_environment = environment
85
+ end
86
+
87
+ def unshackle!
88
+ @shackles_environment = nil
89
+ end
90
+
91
+ def unshackle
92
+ old_env = @shackles_environment
93
+ unshackle!
94
+ yield
95
+ ensure
96
+ shackle!(old_env)
97
+ end
98
+
58
99
  def shareable?
59
100
  @shareable_environment_key ||= []
60
101
  environment = ::Shackles.environment
61
102
  explicit_user = ::Shackles.global_config[:username]
62
103
  return @shareable if @shareable_environment_key == [environment, explicit_user]
63
104
  @shareable_environment_key = [environment, explicit_user]
64
- username = self.config[:username]
65
- username = self.config[environment][:username] if environment && self.config[environment] && self.config[environment][:username]
66
- username = explicit_user if explicit_user
105
+ if explicit_user
106
+ username = explicit_user
107
+ else
108
+ config = self.config(environment)
109
+ config = config.first if config.is_a?(Array)
110
+ username = config[:username]
111
+ end
67
112
  @shareable = self.config[:adapter] != 'sqlite3' && username !~ /%?\{[a-zA-Z0-9_]+\}/
68
113
  end
69
114
 
70
115
  def shards
71
- if self.id == Rails.env
116
+ if self.id == ::Rails.env
72
117
  Shard.where("database_server_id IS NULL OR database_server_id=?", self.id)
73
118
  else
74
119
  Shard.where(:database_server_id => self.id)
75
120
  end
76
121
  end
77
122
 
123
+ def pool_key
124
+ self.id == ::Rails.env ? nil : self.id
125
+ end
126
+
78
127
  def create_new_shard(options = {})
128
+ raise MethodNotImplemented unless Shard.default.is_a?(Shard)
129
+
79
130
  db_name = options[:db_name]
80
131
  create_schema = options[:schema]
81
132
  # look for another shard associated with this db
82
133
  other_shard = self.shards.where("name<>':memory:' OR name IS NULL").order(:id).first
83
- temp_db_name = other_shard.try(:name) unless id == Rails.env
84
- temp_db_name = Shard.default.name if id == Rails.env
134
+ temp_db_name = other_shard.try(:name) unless id == ::Rails.env
135
+ temp_db_name = Shard.default.name if id == ::Rails.env
85
136
 
86
137
  case config[:adapter]
87
138
  when 'postgresql'
@@ -113,67 +164,78 @@ module Switchman
113
164
  }
114
165
  end
115
166
 
116
- shard = Shard.create!(:name => temp_db_name,
167
+ create_shard = lambda do
168
+ shard = Shard.create!(:name => temp_db_name,
117
169
  :database_server => self) do |shard|
118
- shard.id = options[:id] if options[:id]
119
- end
120
- begin
121
- if db_name.nil?
122
- base_db_name = self.config[:database] % self.config
123
- base_db_name = $1 if base_db_name =~ /(?:.*\/)(.+)_shard_\d+(?:\.sqlite3)?$/
124
- base_db_name = nil if base_db_name == ':memory:'
125
- base_db_name << '_' if base_db_name
126
- db_name = "#{base_db_name}shard_#{shard.id}"
127
- if config[:adapter] == 'sqlite3'
128
- # Try to create a db on-disk even if the only shards for sqlite are in-memory
129
- temp_db_name = nil if temp_db_name == ':memory:'
130
- # Put it in the db directory if there are no other sqlite shards
131
- temp_db_name ||= 'db/dummy'
132
- db_name = File.join(File.dirname(temp_db_name), "#{db_name}.sqlite3")
133
- shard.name = db_name
134
- end
170
+ shard.id = options[:id] if options[:id]
135
171
  end
136
- shard.activate(Shard.categories) do
137
- ::Shackles.activate(:deploy) do
138
- begin
139
- if create_statement
140
- Array(create_statement.call).each do |stmt|
141
- ::ActiveRecord::Base.connection.execute(stmt)
142
- end
143
- # have to disconnect and reconnect to the correct db
144
- if self.shareable? && other_shard
145
- other_shard.activate { ::ActiveRecord::Base.connection }
146
- else
147
- ::ActiveRecord::Base.connection_pool.current_pool.disconnect!
172
+ begin
173
+ if db_name.nil?
174
+ base_db_name = self.config[:database] % self.config
175
+ base_db_name = $1 if base_db_name =~ /(?:.*\/)(.+)_shard_\d+(?:\.sqlite3)?$/
176
+ base_db_name = nil if base_db_name == ':memory:'
177
+ base_db_name << '_' if base_db_name
178
+ db_name = "#{base_db_name}shard_#{shard.id}"
179
+ if config[:adapter] == 'sqlite3'
180
+ # Try to create a db on-disk even if the only shards for sqlite are in-memory
181
+ temp_db_name = nil if temp_db_name == ':memory:'
182
+ # Put it in the db directory if there are no other sqlite shards
183
+ temp_db_name ||= 'db/dummy'
184
+ db_name = File.join(File.dirname(temp_db_name), "#{db_name}.sqlite3")
185
+ shard.name = db_name
186
+ end
187
+ end
188
+ shard.activate(Shard.categories) do
189
+ ::Shackles.activate(:deploy) do
190
+ begin
191
+ if create_statement
192
+ Array(create_statement.call).each do |stmt|
193
+ ::ActiveRecord::Base.connection.execute(stmt)
194
+ end
195
+ # have to disconnect and reconnect to the correct db
196
+ if self.shareable? && other_shard
197
+ other_shard.activate { ::ActiveRecord::Base.connection }
198
+ else
199
+ ::ActiveRecord::Base.connection_pool.current_pool.disconnect!
200
+ end
148
201
  end
202
+ shard.name = db_name
203
+ old_proc = ::ActiveRecord::Base.connection.raw_connection.set_notice_processor {} if config[:adapter] == 'postgresql'
204
+ old_verbose = ::ActiveRecord::Migration.verbose
205
+ ::ActiveRecord::Migration.verbose = false
206
+
207
+ reset_column_information
208
+ ::ActiveRecord::Migrator.migrate(::Rails.root + "db/migrate/") unless create_schema == false
209
+ reset_column_information
210
+ ensure
211
+ ::ActiveRecord::Migration.verbose = old_verbose
212
+ ::ActiveRecord::Base.connection.raw_connection.set_notice_processor(&old_proc) if old_proc
149
213
  end
150
- shard.name = db_name
151
- old_proc = ::ActiveRecord::Base.connection.raw_connection.set_notice_processor {} if config[:adapter] == 'postgresql'
152
- old_verbose = ::ActiveRecord::Migration.verbose
153
- ::ActiveRecord::Migration.verbose = false
154
- ::ActiveRecord::Migrator.migrate(Rails.root + "db/migrate/") unless create_schema == false
155
- ensure
156
- ::ActiveRecord::Migration.verbose = old_verbose
157
- ::ActiveRecord::Base.connection.raw_connection.set_notice_processor(&old_proc) if old_proc
158
214
  end
159
215
  end
216
+ shard.save!
217
+ shard
218
+ rescue
219
+ shard.destroy
220
+ shard.drop_database if shard.name == db_name rescue nil
221
+ raise
160
222
  end
161
- shard.save!
162
- shard
163
- rescue
164
- shard.destroy
165
- raise
223
+ end
224
+
225
+ if Shard.connection.supports_ddl_transactions? && self.shareable? && other_shard
226
+ Shard.transaction do
227
+ other_shard.activate do
228
+ ::ActiveRecord::Base.connection.transaction(&create_shard)
229
+ end
230
+ end
231
+ else
232
+ create_shard.call
166
233
  end
167
234
  end
168
235
 
169
236
  def cache_store
170
- if !@cache_store
171
- @cache_store = Rails.cache_without_sharding if self.id == Rails.env
172
- # TODO: get the config from somewhere
173
- config = nil
174
- @cache_store ||= ActiveSupport::Cache.lookup_store(config) if config
175
- @cache_store ||= Rails.cache_without_sharding
176
- @cache_store.options[:namespace] = lambda { Shard.current.default? ? nil : "shard_#{Shard.current.id}" }
237
+ unless @cache_store
238
+ @cache_store = Switchman.config[:cache_map][self.id] || Switchman.config[:cache_map][::Rails.env]
177
239
  end
178
240
  @cache_store
179
241
  end
@@ -193,5 +255,11 @@ module Switchman
193
255
  config[:database]
194
256
  end
195
257
  end
258
+
259
+ private
260
+ def reset_column_information
261
+ ::ActiveRecord::Base.connection.schema_cache.clear!
262
+ ::ActiveRecord::Base.descendants.reject{ |m| m == Shard }.each(&:reset_column_information)
263
+ end
196
264
  end
197
265
  end
@@ -1,28 +1,43 @@
1
1
  require_dependency 'switchman/database_server'
2
2
 
3
- class Switchman::DefaultShard
4
- def id; 'default'; end
5
- def activate(*categories); yield; end
6
- def activate!(*categories); end
7
- def default?; true; end
8
- def relative_id_for(local_id, target = nil); local_id; end
9
- def global_id_for(local_id); local_id; end
10
- def database_server_id; nil; end
11
- def database_server; ::Switchman::DatabaseServer.find(nil); end
12
- def name
13
- unless instance_variable_defined?(:@name)
14
- @name = nil # prevent taking this branch on recursion
15
- @name = database_server.shard_name(:bootstrap)
3
+ module Switchman
4
+ class DefaultShard
5
+ def id; 'default'; end
6
+ def activate(*categories); yield; end
7
+ def activate!(*categories); end
8
+ def default?; true; end
9
+ def relative_id_for(local_id, target = nil); local_id; end
10
+ def global_id_for(local_id); local_id; end
11
+ def database_server_id; nil; end
12
+ def database_server; DatabaseServer.find(nil); end
13
+ def name
14
+ unless instance_variable_defined?(:@name)
15
+ @name = nil # prevent taking this branch on recursion
16
+ @name = database_server.shard_name(:bootstrap)
17
+ end
18
+ @name
19
+ end
20
+ def description; ::Rails.env; end
21
+ # The default's shard is always the default shard
22
+ def shard; self; end
23
+ def _dump(depth)
24
+ ''
25
+ end
26
+ def self._load(str)
27
+ Shard.default
28
+ end
29
+
30
+ def ==(rhs)
31
+ return true if rhs.is_a?(Shard) && rhs.default?
32
+ super
33
+ end
34
+
35
+ class << self
36
+ def instance
37
+ @instance ||= new
38
+ end
39
+
40
+ private :new
16
41
  end
17
- @name
18
- end
19
- def description; Rails.env; end
20
- # The default's shard is always the default shard
21
- def shard; self; end
22
- def _dump(depth)
23
- ''
24
- end
25
- def self._load(str)
26
- Shard.default
27
42
  end
28
43
  end
@@ -2,10 +2,55 @@ module Switchman
2
2
  class Engine < ::Rails::Engine
3
3
  isolate_namespace Switchman
4
4
 
5
- initializer 'switchman.extend_ar', :before => "active_record.initialize_database" do
6
- ActiveSupport.on_load(:active_record) do
7
- #require 'active_record/associations/preloader/belongs_to'
5
+ initializer 'switchman.initialize_cache', :before => 'initialize_cache' do
6
+ # if we haven't already setup our cache map out-of-band, set it up from
7
+ # config.cache_store now. behaves similarly to Rails' default
8
+ # initialize_cache initializer, but for each value in the map, rather
9
+ # than just Rails.cache. if config.cache_store is a flat value, uses it
10
+ # to fill just the Rails.env entry in the cache map.
11
+ unless Switchman.config[:cache_map].present?
12
+ cache_store_config = ::Rails.configuration.cache_store
13
+ unless cache_store_config.is_a?(Hash)
14
+ cache_store_config = {::Rails.env => cache_store_config}
15
+ end
16
+
17
+ Switchman.config[:cache_map] = {}
18
+ cache_store_config.each do |key, value|
19
+ value = ::ActiveSupport::Cache.lookup_store(value)
20
+ Switchman.config[:cache_map][key] = value
21
+ if value.respond_to?(:middleware)
22
+ config.middleware.insert_before("Rack::Runtime", value.middleware)
23
+ end
24
+ end
25
+ end
26
+
27
+ # if the configured cache map (either from before, or as populated from
28
+ # config.cache_store) didn't have an entry for Rails.env, add one using
29
+ # lookup_store(nil); matches the behavior of Rails' default
30
+ # initialize_cache initializer when config.cache_store is nil.
31
+ unless Switchman.config[:cache_map].has_key?(::Rails.env)
32
+ value = ::ActiveSupport::Cache.lookup_store(nil)
33
+ Switchman.config[:cache_map][::Rails.env] = value
34
+ if value.respond_to?(:middleware)
35
+ config.middleware.insert_before("Rack::Runtime", value.middleware)
36
+ end
37
+ end
8
38
 
39
+ # prevent :initialize_cache from trying to (or needing to) set
40
+ # Rails.cache. once our switchman.extend_ar initializer (below) runs
41
+ # Rails.cache will be overridden to pull appropriate values from the
42
+ # cache map, but between now and then, Rails.cache should return the
43
+ # Rails.env entry in the cache map.
44
+ if ::Rails.version < '4'
45
+ silence_warnings { Object.const_set "RAILS_CACHE", Switchman.config[:cache_map][::Rails.env] }
46
+ else
47
+ ::Rails.cache = Switchman.config[:cache_map][::Rails.env]
48
+ end
49
+ end
50
+
51
+ initializer 'switchman.extend_ar', :before => "active_record.initialize_database" do
52
+ ::ActiveSupport.on_load(:active_record) do
53
+ require "switchman/active_support/cache"
9
54
  require "switchman/active_record/abstract_adapter"
10
55
  require "switchman/active_record/association"
11
56
  require "switchman/active_record/attribute_methods"
@@ -18,11 +63,14 @@ module Switchman
18
63
  require "switchman/active_record/query_cache"
19
64
  require "switchman/active_record/query_methods"
20
65
  require "switchman/active_record/relation"
21
- require "switchman/cache_extensions"
66
+ require "switchman/active_record/spawn_methods"
67
+ require "switchman/rails"
22
68
 
69
+ ::ActiveSupport::Cache::Store.send(:include, ActiveSupport::Cache::Store)
23
70
  include ActiveRecord::Base
24
71
  include ActiveRecord::AttributeMethods
25
72
  ::ActiveRecord::Associations::Association.send(:include, ActiveRecord::Association)
73
+ ::ActiveRecord::Associations::BelongsToAssociation.send(:include, ActiveRecord::BelongsToAssociation)
26
74
  ::ActiveRecord::Associations::CollectionProxy.send(:include, ActiveRecord::CollectionProxy)
27
75
  ::ActiveRecord::Associations::Builder::Association.send(:include, ActiveRecord::Builder::Association)
28
76
 
@@ -31,12 +79,19 @@ module Switchman
31
79
  ::ActiveRecord::ConnectionAdapters::ConnectionHandler.send(:include, ActiveRecord::ConnectionHandler)
32
80
  ::ActiveRecord::ConnectionAdapters::ConnectionPool.send(:include, ActiveRecord::ConnectionPool)
33
81
  ::ActiveRecord::ConnectionAdapters::AbstractAdapter.send(:include, ActiveRecord::QueryCache)
82
+ # when we call super in Switchman::ActiveRecord::QueryCache#select_all,
83
+ # we want it to find the definition from
84
+ # ActiveRecord::ConnectionAdapters::DatabaseStatements, not
85
+ # ActiveRecord::ConnectionAdapters::QueryCache
86
+ ::ActiveRecord::ConnectionAdapters::QueryCache.send(:remove_method, :select_all)
87
+
34
88
  ::ActiveRecord::LogSubscriber.send(:include, ActiveRecord::LogSubscriber)
35
89
  ::ActiveRecord::Relation.send(:include, ActiveRecord::Calculations)
36
90
  ::ActiveRecord::Relation.send(:include, ActiveRecord::FinderMethods)
37
91
  ::ActiveRecord::Relation.send(:include, ActiveRecord::QueryMethods)
38
92
  ::ActiveRecord::Relation.send(:include, ActiveRecord::Relation)
39
- Rails.send(:include, CacheExtensions)
93
+ ::ActiveRecord::Relation.send(:include, ActiveRecord::SpawnMethods)
94
+ ::Rails.send(:include, Rails)
40
95
  end
41
96
  end
42
97
 
@@ -47,7 +102,7 @@ module Switchman
47
102
  end
48
103
 
49
104
  initializer 'switchman.extend_connection_adapters', :after => "active_record.initialize_database" do
50
- ActiveSupport.on_load(:active_record) do
105
+ ::ActiveSupport.on_load(:active_record) do
51
106
  ::ActiveRecord::ConnectionAdapters::AbstractAdapter.descendants.each do |klass|
52
107
  klass.class_eval do
53
108
  def add_column_with_foreign_key_check(table, name, type, options = {})
@@ -74,18 +129,26 @@ module Switchman
74
129
  end
75
130
 
76
131
  initializer 'switchman.eager_load' do
77
- ActiveSupport.on_load(:before_eager_load) do
132
+ ::ActiveSupport.on_load(:before_eager_load) do
78
133
  # This needs to be loaded before Switchman::Shard, otherwise it won't autoload it correctly
79
134
  require_dependency('active_record/base')
80
135
  end
81
136
  end
82
137
 
83
138
  initializer 'switchman.extend_shackles', :after => "shackles.extend_ar" do
84
- ActiveSupport.on_load(:active_record) do
139
+ ::ActiveSupport.on_load(:active_record) do
85
140
  require "switchman/shackles"
86
141
 
87
142
  ::Shackles.send(:include, Shackles)
88
143
  end
89
144
  end
145
+
146
+ initializer 'switchman.extend_controller', :after => "shackles.extend_ar" do
147
+ ::ActiveSupport.on_load(:action_controller) do
148
+ require "switchman/action_controller/caching"
149
+
150
+ ::ActionController::Base.send(:include, ActionController::Caching)
151
+ end
152
+ end
90
153
  end
91
154
  end
@@ -17,48 +17,28 @@ module Switchman
17
17
  # our before handlers have already been configured from a parent group; don't add them again
18
18
  return if klass.parent_groups[1..-1].any? { |group| group.included_modules.include?(self) }
19
19
 
20
- ::RSpec.configure do |config|
21
- block = proc do
22
- if @@shard1
23
- # some specs are mean, and blow away our shards
24
- begin
25
- @@shard1.reload
26
- @@shard2.reload
27
- @@shard3.reload if @@shard3
28
- rescue ::ActiveRecord::RecordNotFound
29
- Shard.default.clone.save!
30
- Shard.default(true)
31
- @@shard1 = @@shard1.clone
32
- @@shard1.save!
33
- @@shard2 = @@shard2.clone
34
- @@shard2.save!
35
- if @@shard3
36
- @@shard3 = @@shard3.clone
37
- @@shard3.save!
38
- end
39
- end
40
- end
41
- end
42
- # this module will be included multiple times, but we don't want to run this global hook multiple times
43
- if config.hooks[:before][:all].all? { |hook| hook.block.source_location != block.source_location }
44
- config.before(:all, &block)
45
- end
46
- end
47
-
48
20
  klass.before(:all) do
49
21
  unless @@shard1
50
22
  puts "Setting up sharding for all specs..."
23
+ Shard.delete_all
24
+
51
25
  @@shard1, @@shard2 = TestHelper.recreate_persistent_test_shards
26
+ @@default_shard = Shard.default
52
27
  if @@shard1.is_a?(Shard)
53
28
  @@keep_the_shards = true
54
29
  @@shard3 = nil
55
30
  else # @@shard1.is_a?(DatabaseServer)
56
- @@shard1 = @@shard1.create_new_shard
57
- @@shard2 = @@shard2.create_new_shard
58
- if @@shard1.database_server == Shard.default.database_server
59
- @@shard3 = nil
60
- else
61
- @@shard3 = @@shard1.database_server.create_new_shard
31
+ begin
32
+ @@shard1 = @@shard1.create_new_shard
33
+ @@shard2 = @@shard2.create_new_shard
34
+ if @@shard1.database_server == Shard.default.database_server
35
+ @@shard3 = nil
36
+ else
37
+ @@shard3 = @@shard1.database_server.create_new_shard
38
+ end
39
+ rescue
40
+ @@shard1 = @@shard2 = @@shard3 = nil
41
+ raise
62
42
  end
63
43
  end
64
44
  puts "Done!"
@@ -81,6 +61,25 @@ module Switchman
81
61
  @@shard2.database_server.destroy
82
62
  exit status if status
83
63
  end
64
+ else
65
+ dup = @@default_shard.dup
66
+ dup.id = @@default_shard.id
67
+ dup.save!
68
+ Shard.default(true)
69
+ dup = @@shard1.dup
70
+ dup.id = @@shard1.id
71
+ dup.save!
72
+ @@shard1.instance_variable_set(:@destroyed, false)
73
+ dup = @@shard2.dup
74
+ dup.id = @@shard2.id
75
+ dup.save!
76
+ @@shard2.instance_variable_set(:@destroyed, false)
77
+ if @@shard3
78
+ dup = @@shard3.dup
79
+ dup.id = @@shard3.id
80
+ dup.save!
81
+ @@shard3.instance_variable_set(:@destroyed, false)
82
+ end
84
83
  end
85
84
  @shard1, @shard2 = @@shard1, @@shard2
86
85
  @shard3 = @@shard3 ? @@shard3 : Shard.default
@@ -119,6 +118,14 @@ module Switchman
119
118
  end
120
119
  end
121
120
  end
121
+
122
+ klass.after(:all) do
123
+ Shard.default.destroy
124
+ @@shard1.destroy
125
+ @@shard2.destroy
126
+ @@shard3.destroy if @@shard3
127
+ Shard.default(true)
128
+ end
122
129
  end
123
130
  end
124
131
  end
@@ -0,0 +1,21 @@
1
+ module Switchman::Rails
2
+ module ClassMethods
3
+ def cache_with_sharding
4
+ Switchman::Shard.current.database_server.cache_store
5
+ end
6
+
7
+ # in Rails 4+, the Rails.cache= method was used during bootstrap to set
8
+ # Rails.cache(_without_sharding) to the value from the config file. but now
9
+ # that that's done (the bootstrap happened before this module is included
10
+ # into Rails), we want to make sure no one tries to assign to Rails.cache,
11
+ # because it would be wrong w.r.t. sharding.
12
+ def cache=(new_cache)
13
+ raise NoMethodError
14
+ end
15
+ end
16
+
17
+ def self.included(klass)
18
+ klass.extend(ClassMethods)
19
+ klass.singleton_class.alias_method_chain :cache, :sharding
20
+ end
21
+ end
@@ -2,33 +2,33 @@ module Switchman
2
2
  module Shackles
3
3
  module ClassMethods
4
4
  def ensure_handler
5
- Shard.default.activate(*Shard.categories) do
6
- new_handler = @connection_handlers[self.environment]
7
- if !new_handler
8
- new_handler = @connection_handlers[self.environment] = ::ActiveRecord::ConnectionAdapters::ConnectionHandler.new
9
- pools = ::ActiveRecord::Base.connection_handler.instance_variable_get(:@class_to_pool)
10
- pools.each do |model, pool|
11
- # don't call establish_connection for pools created just for different sharding categories
12
- if model != ::ActiveRecord::Base.name
13
- klass = model.constantize
14
- next if ::ActiveRecord::Base.connection_handler.retrieve_connection_pool(klass.superclass).default_pool == pools[model].default_pool
15
- end
5
+ raise "This should not be called with switchman installed"
6
+ end
7
+
8
+ # drops the save_handler and ensure_handler calls from the vanilla
9
+ # Shackles' implementation.
10
+ def activate!(environment)
11
+ environment ||= :master
12
+ old_environment = self.environment
13
+ @environment = environment
14
+ old_environment
15
+ end
16
16
 
17
- new_handler.establish_connection(model, pool.spec)
18
- end
19
- end
20
- # make sure it picks up the environment change
21
- new_handler.connection_pools.each do |_, pool|
22
- pool.spec.instance_variable_set(:@current_config, nil)
23
- end
24
- new_handler
25
- end
17
+ # since activate! really is just a variable swap now, it's safe to use in
18
+ # the ensure block, simplifying the implementation
19
+ def activate(environment)
20
+ old_environment = activate!(environment)
21
+ yield
22
+ ensure
23
+ activate!(old_environment)
26
24
  end
27
25
  end
28
26
 
29
27
  def self.included(klass)
30
28
  klass.extend(ClassMethods)
31
29
  klass.singleton_class.send(:remove_method, :ensure_handler)
30
+ klass.singleton_class.send(:remove_method, :activate!)
31
+ klass.singleton_class.send(:remove_method, :activate)
32
32
  end
33
33
  end
34
34
  end
@@ -0,0 +1,19 @@
1
+ module Switchman
2
+ class ShardedInstrumenter < ::SimpleDelegator
3
+ def initialize(instrumenter, shard_host)
4
+ super instrumenter
5
+ @shard_host = shard_host
6
+ end
7
+
8
+ def instrument(name, payload={})
9
+ shard = @shard_host.try(:shard)
10
+ if shard.is_a?(Shard)
11
+ payload[:shard] = {
12
+ id: shard.id,
13
+ env: shard.database_server.shackles_environment
14
+ }
15
+ end
16
+ super name, payload
17
+ end
18
+ end
19
+ end