{"id":13462916,"url":"https://github.com/drecom/activerecord-turntable","last_synced_at":"2025-03-25T06:31:23.146Z","repository":{"id":2963849,"uuid":"3978515","full_name":"drecom/activerecord-turntable","owner":"drecom","description":"ActiveRecord Sharding Plugin","archived":false,"fork":false,"pushed_at":"2023-09-15T07:38:52.000Z","size":742,"stargazers_count":210,"open_issues_count":8,"forks_count":34,"subscribers_count":37,"default_branch":"master","last_synced_at":"2025-03-18T17:36:17.652Z","etag":null,"topics":["activerecord","rails","ruby","sharding"],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"shayanb/two1","license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/drecom.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2012-04-10T03:23:54.000Z","updated_at":"2024-12-18T02:35:54.000Z","dependencies_parsed_at":"2024-01-05T21:59:48.069Z","dependency_job_id":null,"html_url":"https://github.com/drecom/activerecord-turntable","commit_stats":{"total_commits":627,"total_committers":14,"mean_commits":"44.785714285714285","dds":0.08771929824561409,"last_synced_commit":"18be9da4cd5ffde1ea791ba02f70680de0716c09"},"previous_names":[],"tags_count":47,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/drecom%2Factiverecord-turntable","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/drecom%2Factiverecord-turntable/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/drecom%2Factiverecord-turntable/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/drecom%2Factiverecord-turntable/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/drecom","download_url":"https://codeload.github.com/drecom/activerecord-turntable/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245413741,"owners_count":20611353,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["activerecord","rails","ruby","sharding"],"created_at":"2024-07-31T13:00:40.890Z","updated_at":"2025-03-25T06:31:22.535Z","avatar_url":"https://github.com/drecom.png","language":"Ruby","readme":"# ActiveRecord::Turntable\n\n[![Gem Version](https://badge.fury.io/rb/activerecord-turntable.svg)](http://badge.fury.io/rb/activerecord-turntable)\n[![Build Status](https://travis-ci.org/drecom/activerecord-turntable.svg?branch=master)](https://travis-ci.org/drecom/activerecord-turntable)\n[![Coverage Status](https://coveralls.io/repos/github/drecom/activerecord-turntable/badge.svg)](https://coveralls.io/github/drecom/activerecord-turntable)\n[![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/drecom/activerecord-turntable/blob/master/LICENSE.txt)\n\nActiveRecord::Turntable is a database sharding extension for ActiveRecord.\n\n## Dependencies\n\nactiverecord(\u003e=5.0.0, \u003c6.0)\n\n* Current latest stable branch is [stable branch](https://github.com/drecom/activerecord-turntable/tree/stable).\n\nIf you are using with older activerecord versions, use following versions.\n\n* activerecord 4.x - use activerecord-turntable version 2.x.([stable-2-x branch](https://github.com/drecom/activerecord-turntable/tree/stable-2-x))\n* activerecord 3.x - use activerecord-turntable version 1.x.([stable-1-x branch](https://github.com/drecom/activerecord-turntable/tree/stable-1-x))\n\n## Supported DBMS\n\nMySQL only.\n\n## Installation\n\nAdd to Gemfile:\n\n```ruby\ngem 'activerecord-turntable', '~\u003e 4.4.1'\n```\n\nRun a bundle install:\n\n```ruby\nbundle install\n```\n\nRun install generator:\n\n```bash\nbundle exec rails g active_record:turntable:install\n```\n\ngenerator creates `#{Rails.root}/config/turntable.yml`\n\n## Terminologies\n\n### Shard\n\nShard is a database which is horizontal partitioned.\n\n### Cluster\n\nCluster of shards. i.e) set of userdb1, userdb2, userdb3.\nShards in the same cluster should have the same schema structure.\n\n### Master\n\nDefault ActiveRecord::Base's connection.\n\n### Sequencer\n\nTurntable's sequence system for clustered database.\n\nThis keeps primary key ids to be unique each shards.\n\n## Example\n\n### Example Databases Structure\n\nOne main database(default ActiveRecord::Base connection) and\nthree user databases sharded by user_id.\n\n```\n                  +-------+\n                  |  App  |\n                  +-------+\n                      |\n       +---------+---------+---------+---------+\n       |         |         |         |         |\n  `--------` `-------` `-------` `-------` `-------`\n  | Master | |UserDB1| |UserDB2| |UserDB3| | SeqDB |\n  `--------` `-------` `-------` `-------` `-------`\n\n```\n\n### Example Configuration\n\nEdit DSL type configuration file(config/turntable.rb) or YAML configuration file(turntable.yml).\nAnd add database connection settings to database.yml.\n\nSee below example config.\n\n* example turntable.rb\n\n```ruby\ncluster :user_cluster do\n  # algorithm [algorithm name symbol(range|range_bsearch|modulo)]\n  algorithm :range_bsearch\n\n  # sequencer [sequence name] [sequence type] [*options hash]\n  sequencer :user_seq, :mysql, connection: :user_seq\n\n  # shard [range], to: [connection names in database.yml]\n  shard   1...100,        to: :user_shard_1\n  shard 100...200,        to: :user_shard_2\n  shard 200...2000000000, to: :user_shard_3\n\n  # If you are using modulo algorithm, pass integer sequence start with zero.\n  #\n  # shard 0, to: :user_shard_1\n  # shard 1, to: :user_shard_2\n  # shard 2, to: :user_shard_3\nend\n```\n\n* example turntable.yml\n\n```yaml\n    development:\n      clusters:\n        user_cluster: # \u003c-- cluster name\n          algorithm: range_bsearch # \u003c-- `range`, `range_bsearch` or `modulo`\n          seq:\n            user_seq: # \u003c-- sequencer name\n              seq_type: mysql # \u003c-- sequencer type\n              connection: user_seq_1 # \u003c-- sequencer database connection setting\n          shards:\n            - connection: user_shard_1 # \u003c-- shard name\n              less_than: 100           # \u003c-- shard range(like mysql partitioning) If you are using a modulo algorithm, it doesn't need it.\n            - connection: user_shard_2\n              less_than: 200\n            - connection: user_shard_3\n              less_than: 2000000000\n\n```\n\n* database.yml\n\n```yaml\n    connection_spec: \u0026spec\n      adapter: mysql2\n      encoding: utf8\n      reconnect: false\n      pool: 5\n      username: root\n      password: root\n      socket: /tmp/mysql.sock\n\n    development:\n      \u003c\u003c: *spec\n      database: sample_app_development\n      seq: # \u003c-- sequence database definition\n        user_seq_1:\n          \u003c\u003c: *spec\n          database: sample_app_user_seq_development\n      shards: # \u003c-- shards definition\n        user_shard_1:\n          \u003c\u003c: *spec\n          database: sample_app_user1_development\n        user_shard_2:\n          \u003c\u003c: *spec\n          database: sample_app_user2_development\n        user_shard_3:\n          \u003c\u003c: *spec\n          database: sample_app_user3_development\n```\n\n#### About algorithms\n\n* range, range_bsearch - distribute records by key range\n\n```ruby\n  algorithm :range_bsearch\n\n  shard      1...20_000,     to: :user_shard_1\n  shard 20_000...40_000,     to: :user_shard_2\n  shard 40_000...60_000,     to: :user_shard_1\n  shard 60_000...80_000,     to: :user_shard_2\n  shard 80_000...10_000_000, to: :user_shard_3\n```\n\n* modulo - distribute records by key modulo\n\n```ruby\n  algorithm :modulo\n\n  shard 0, to: :user_shard_1\n  shard 1, to: :user_shard_2\n  shard 2, to: :user_shard_3\n```\n\n* hash_slot - distribute records by key hashes\n\ndefault hash function is `Zlib.crc32(key.to_s)`\n\n```ruby\n  algorithm :hash_slot\n  # Or specify hash function\n  # algorithm :hash_slot, hash_func: -\u003e(key) { Zlib.adler32(key.to_s) }\n\n  shard     0...4096,  to: :user_shard_1\n  shard  4096...8192,  to: :user_shard_2\n  shard  8192...12288, to: :user_shard_3\n  shard 12288...16384, to: :user_shard_4\n```\n\n### Slave support (experimental)\n\nSlave enabled configuration examples:\n\n* config/turntable.rb\n\n```ruby\ncluster :user_cluster do\n...\n\n  # shard [range], to: [connection names in database.yml]\n  shard   1...100,        to: :user_shard_1, slaves: [:user_shard_1_1]\n  shard 100...200,        to: :user_shard_2, slaves: [:user_shard_2_1]\n  shard 200...2000000000, to: :user_shard_3, slaves: [:user_shard_3_1]\nend\n```\n\n* config/turntable.yml\n\n```yaml\n    development:\n      clusters:\n        user_cluster: # \u003c-- cluster name\n          ...\n          shards:\n            - connection: user_shard_1\n              less_than: 100\n              slaves:\n                - user_shard_1_1\n            - connection: user_shard_2\n              less_than: 200\n              slaves:\n                - user_shard_2_1\n            - connection: user_shard_3\n              less_than: 2000000000\n              slaves:\n                - user_shard_3_1\n```\n\n* config/database.yml\n\nAdd slave connection settings under `shards`.\n\n```yaml\n...\n  shards:\n    user_shard_1:\n      \u003c\u003c: *default\n      database: turntable_user_shard_1_test\n    user_shard_1_1:\n      \u003c\u003c: *default\n      database: turntable_user_shard_1_1_test\n    user_shard_2:\n      \u003c\u003c: *default\n      database: turntable_user_shard_2_test\n    user_shard_2_1:\n      \u003c\u003c: *default\n      database: turntable_user_shard_2_1_test\n    user_shard_3:\n      \u003c\u003c: *default\n      database: turntable_user_shard_3_test\n    user_shard_3_1:\n      \u003c\u003c: *default\n      database: turntable_user_shard_3_1_test\n```\n\nSlave usage:\n\n```ruby\nUser.with_slave {\n  # `User` model will use slave databases within this block.\n}\n\nUser.with_master {\n  # `User` model will use master database within this block.\n}\n```\n\n\n### Example Migration\n\nGenerate a model:\n\n```bash\nbundle exec rails g model user name:string\n```\n\nAnd Edit migration file:\n\n```ruby\nclass CreateUsers \u003c ActiveRecord::Migration\n  # Specify cluster executes migration if you need.\n  # Default, migration would be executed to all databases.\n  # clusters :user_cluster\n\n  def change\n    create_table :users do |t|\n      t.string :name\n      t.timestamps\n    end\n    create_sequence_for(:users) # \u003c-- create sequence table\n  end\nend\n```\n\nThen please execute rake tasks:\n\n```bash\nbundle exec rake db:create\nbundle exec rake db:migrate\n```\n\nThose rake tasks would be executed to shards too.\n\n### Example Model\n\nAdd turntable [shard_key_name] to the model class:\n\n```ruby\nclass User \u003c ApplicationRecord\n  turntable :user_cluster, :id\n  sequencer :user_seq\n  has_one :status\nend\n\nclass Status \u003c ApplicationRecord\n  turntable :user_cluster, :user_id\n  sequencer :user_seq\n  belongs_to :user\nend\n```\n\n## Usage\n\n### Creating\n\n```\n    \u003e User.create(name: \"hoge\")\n      (0.0ms) [Shard: user_seq_1] BEGIN\n      (0.3ms) [Shard: user_seq_1] UPDATE `users_id_seq` SET id=LAST_INSERT_ID(id+1)\n      (0.8ms) [Shard: user_seq_1] COMMIT\n      (0.1ms) [Shard: user_seq_1] SELECT LAST_INSERT_ID()\n      (0.1ms) [Shard: user_shard_1] BEGIN\n    [ActiveRecord::Turntable] Sending method: insert, sql: #\u003cArel::InsertManager:0x007f8503685b48\u003e, shards: [\"user_shard_1\"]\n      SQL (0.8ms) [Shard: user_shard_1] INSERT INTO `users` (`created_at`, `id`, `name`, `updated_at`) VALUES ('2012-04-10 03:59:42', 2, 'hoge', '2012-04-10 03:59:42')\n      (0.4ms) [Shard: user_shard_1] COMMIT\n    =\u003e #\u003cUser id: 2, name: \"hoge\", created_at: \"2012-04-10 03:59:42\", updated_at: \"2012-04-10 03:59:42\"\u003e\n```\n\n### Retrieving\n\n```\n    \u003e user = User.find(2)\n    [ActiveRecord::Turntable] Sending method: select_all, sql: #\u003cArel::SelectManager:0x007f850466e668\u003e, shards: [\"user_shard_1\"]\n      User Load (0.3ms) [Shard: user_shard_1] SELECT `users`.* FROM `users` WHERE `users`.`id` = 2 LIMIT 1\n    =\u003e #\u003cUser id: 2, name: \"hoge\", created_at: \"2012-04-10 03:59:42\", updated_at: \"2012-04-10 03:59:42\"\u003e\n```\n\n### Updating\n\n```\n    \u003e user.update_attributes(name: \"hogefoo\")\n      (0.1ms) [Shard: user_shard_1] BEGIN\n    [ActiveRecord::Turntable] Sending method: update, sql: UPDATE `users` SET `name` = 'hogefoo', `updated_at` = '2012-04-10 04:07:52' WHERE `users`.`id` = 2, shards: [\"user_shard_1\"]\n      (0.3ms) [Shard: user_shard_1] UPDATE `users` SET `name` = 'hogefoo', `updated_at` = '2012-04-10 04:07:52' WHERE `users`.`id` = 2\n      (0.8ms) [Shard: user_shard_1] COMMIT\n    =\u003e true\n```\n\n### Delete\n\n```\n    \u003e user.destroy\n      (0.2ms) [Shard: user_shard_1] BEGIN\n    [ActiveRecord::Turntable] Sending method: delete, sql: #\u003cArel::DeleteManager:0x007f8503677ea8\u003e, shards: [\"user_shard_1\"]\n      SQL (0.3ms) [Shard: user_shard_1] DELETE FROM `users` WHERE `users`.`id` = 2\n      (1.7ms) [Shard: user_shard_1] COMMIT\n    =\u003e #\u003cUser id: 2, name: \"hogefoo\", created_at: \"2012-04-10 03:59:42\", updated_at: \"2012-04-10 04:07:52\"\u003e\n```\n\n### Counting\n\n```\n    \u003e User.count\n    [ActiveRecord::Turntable] Sending method: select_value, sql: #\u003cArel::SelectManager:0x007f9e82ccebb0\u003e, shards: [\"user_shard_1\", \"user_shard_2\", \"user_shard_3\"]\n       (0.8ms) [Shard: user_shard_1] SELECT COUNT(*) FROM `users`\n       (0.3ms) [Shard: user_shard_2] SELECT COUNT(*) FROM `users`\n       (0.2ms) [Shard: user_shard_3] SELECT COUNT(*) FROM `users`\n    =\u003e 1\n```\n\n## Sequencer\n\nSequencer provides generating global IDs.\n\nTurntable has follow 3 sequencers currently:\n\n* :mysql - Use database table to generate ids.\n* :barrage - Use [barrage](https://github.com/drecom/barrage) gem to generate ids\n* :katsubushi - [katsubushi](https://github.com/kayac/go-katsubushi) sequencer backend\n\n### Mysql example\n\nFirst, add configuration to turntable.yml and database.yml\n\n* database.yml\n\n```yaml\n    development:\n      ...\n      seq: # \u003c-- sequence database definition\n        user_seq_1:\n          \u003c\u003c: *spec\n          database: sample_app_user_seq_development\n```\n\n* turntable.yml\n\n```yaml\n    development:\n      clusters:\n        user_cluster: # \u003c-- cluster name\n          ....\n          seq:\n            user_seq: # \u003c-- sequencer name\n              seq_type: mysql # \u003c-- sequencer type\n              connection: user_seq_1 # \u003c-- sequencer database connection\n```\n\nAdd below to the migration:\n\n```ruby\ncreate_sequence_for(:users) # \u003c-- this line creates sequence table named `users_id_seq`\n```\n\nNext, add sequencer definition to the model:\n\n```ruby\n  class User \u003c ApplicationRecord\n    turntable :id\n    sequencer :user_seq # \u003c-- this line enables sequencer module\n    has_one :status\n  end\n```\n\n### Barrage example\n\nFirst, add barrage gem to your Gemfile:\n\n```ruby\ngem 'barrage'\n```\n\nThen, add configuration to turntable.yml:\n\n* turntable.yml\n\n```yaml\n    development:\n      clusters:\n        user_cluster: # \u003c-- cluster name\n          ....\n          seq:\n            barrage_seq: # \u003c-- sequencer name\n              seq_type: barrage # \u003c-- sequencer type\n              options: # \u003c-- options passed to barrage\n                generators:\n                  - name: msec\n                    length: 39 # MAX 17.4 years from start_at\n                    start_at: 1396278000000 # 2014/04/01 00:00:00 JST\n                  - name: redis_worker_id\n                    length: 16\n                    ttl: 300\n                    redis:\n                      host: '127.0.0.1'\n                  - name: sequence\n                    length: 9\n```\n\nNext, add sequencer definition to the model:\n\n```ruby\n  class User \u003c ApplicationRecord\n    turntable :id\n    sequencer :barrage_seq # \u003c-- this line enables sequencer module\n    has_one :status\n  end\n```\n\n### Katsubushi example\n\n[katsubushi](https://github.com/kayac/go-katsubushi) is available as a sequence server.\nActiveRecord::Turntable accesses katsubushi via Dalli.\n\nFirst, add dalli gem to your Gemfile:\n\n```ruby\ngem 'dalli'\n```\n\nThen, add configuration to turntable.yml:\n\n* turntable.yml\n\n```yaml\n    development:\n      clusters:\n        user_cluster: # \u003c-- cluster name\n          ....\n          seq:\n            katsubushi_seq: # \u003c-- sequencer name\n              seq_type: katsubushi # \u003c-- sequencer type\n              options: # \u003c-- options passed to dalli\n                servers:\n                  - host: localhost\n                    port: 11212\n                  - host: localhost\n                    port: 11213\n```\n\nNext, add sequencer definition to the model:\n\n```ruby\n  class User \u003c ApplicationRecord\n    turntable :id\n    sequencer :katsubushi_seq # \u003c-- this line enables sequencer module\n    has_one :status\n  end\n```\n\n## Transactions\nTurntable has some transaction support methods.\n\n### shards_transaction\n\nPass AR::Base instances, `shards_transaction` method suitable shards\n\n```ruby\nuser = User.find(2)\nuser3 = User.create(name: \"hoge3\")\n\nUser.shards_transaction([user, user3]) do\n  user.name  = \"hogehoge\"\n  user3.name = \"hogehoge3\"\n  user.save!\n  user3.save!\nend\n```\n\n### cluster_transaction\n\nWhen executing transaction on all shards in the cluster, use `#{cluster_name}_transaction` method:\n\n```ruby\nUser.user_cluster_transaction do\n  # Transaction is opened all shards in \"user_cluster\"\nend\n```\n\n### Migration\n\nIf you specify cluster or shard, migration will be executed to the cluster(or shard) and master database.\n\nDefault, migrations will be executed to all databases.\n\nto specify cluster:\n\n```ruby\n    class CreateUsers \u003c ActiveRecord::Migration\n      clusters :user_cluster\n      ....\n    end\n```\n\nto specify shard:\n\n```ruby\n    class CreateUsers \u003c ActiveRecord::Migration\n      shards :user_shard_01\n      ....\n    end\n```\n\n## Limitations\n\n* Queries includes \"ORDER BY\", \"GROUP BY\" and \"LIMIT\" clauses cannot be distributed.\n* \"has many through\" and \"habtm\" relationships may returns unexpected results. ex) `User-Friend-User` relation\n\n## TIPS\n\n### Send query to a specific shard.\n\nUse `with_shard` method:\n\n```ruby\n    AR::Base.with_shard(shard1) do\n      # something queries to shard1\n    end\n```\n\n`with_shard` method accepts following types to specify a shard:\n\n* ActiveRecord::Turntable::Shard object\n* AcitveRecord::Base object - `AR::Base#turntable_shard` will be used\n* Numeric, String - a shard key value\n* Symbol - shard name symbol\n\nTo access shard objects, use below:\n\n* AR::Base.connection.shards # \\\\{shard_name =\u003e shard_obj,....}\n* AR::Base#turntable_shard # Returns current object's shard\n* AR::Base.connection.shard_for(shard_key_value) #=\u003e shard\n\n### Send query to all shards\n\nUse with_all method:\n\n```ruby\n  User.with_all do\n    User.order(\"created_at DESC\").limit(3).all\n  end # =\u003e Returns Array of results\n```\n\n### Cannot specify error is raised between associations\n\nNormally, activerecord-turntable detects shard keys on associated models, but auto-detection will fail with following conditions:\n\n* foreign key column != shard key column\n* Using different shard key names\n\nFor example:\n\n```ruby\nclass User\n  # shard key:\n  # foreign key: main_user_item_id\n  belongs_to :main_user_item, class_name: \"UserItem\", required: false\nend\n\nclass UserItem\n  # shard key name: :user_id\n  turntable :user_cluster, :user_id\nend\n```\n\nThis example raises CannotSpecifyShardError\n\n```ruby\n\u003e user.main_user_item\n  User Load [Shard: master] (0.4ms)  SELECT  `users`.* FROM `users` ORDER BY `users`.`id` ASC LIMIT 1\n[ActiveRecord::Turntable] Error on Building Fader: SELECT  `user_items`.* FROM `user_items` WHERE `user_items`.`id` = 2198059200000 LIMIT 1, on_method: select_all, err: cannot specifyshard for query: SELECT \"user_items\".* FROM `user_items` WHERE (`user_items`.`id` = 2198059200000) LIMIT 1\nActiveRecord::Turntable::CannotSpecifyShardError: cannot specify shard for query: SELECT \"user_items\".* FROM `user_items` WHERE (`user_items`.`id` = 2198059200000) LIMIT 1\n```\n\nUse foreign_shard_key option to pass a shard key condition:\n\n```\n-belongs_to :main_user_item, class_name: \"UserItem\"\n+belongs_to :main_user_item, class_name: \"UserItem\", foreign_shard_key: :id\n```\n\n```ruby\n\u003e user.main_user_item\n  User Load [Shard: master] (0.2ms)  SELECT  `users`.* FROM `users` ORDER BY `users`.`id` ASC LIMIT 1\n[ActiveRecord::Turntable] Sending method: select_all, sql: #\u003cArel::SelectManager:0x007f8080bd0670\u003e, shards: [\"user_shard_1\"]\nChanging UserItem's shard to user_shard_1\n  UserItem Load [Shard: user_shard_1] (0.2ms)  SELECT  `user_items`.* FROM `user_items` WHERE `user_items`.`user_id` = 1 AND `user_items`.`id` = 2198059200000 LIMIT 1\nChanging UserItem's shard to master\n=\u003e #\u003cUserItem id: 2198059200000, user_id: 1, item_id: 1, created_at: \"2017-05-23 04:41:13\", updated_at: \"2017-05-23 04:41:13\"\u003e\n```\n\n### Performance Exception\n\nTo notice queries causing performance problem, Turntable has follow options.\n\n* raise\\_on\\_not\\_specified\\_shard\\_query - raises on queries execute on all shards\n* raise\\_on\\_not\\_specified\\_shard\\_update - raises on updates executed on all shards\n\n\nAdd to turntable.yml or turntable.rb:\n\n```yaml\ndevelopment:\n   ....\n   raise_on_not_specified_shard_query: true\n   raise_on_not_specified_shard_update: true\n```\n\n```ruby\n# Write on top level\nraise_on_not_specified_shard_query true\nraise_on_not_specified_shard_update true\n```\n\n## Thanks\n\nConnectionProxy, Distributed Migration implementation is inspired by Octopus and DataFabric.\n\n## License\n\nactiverecord-turntable is released under the MIT license:\n\nCopyright (c) 2012 Drecom Co.,Ltd.\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n","funding_links":[],"categories":["Active Record Plugins","ORM/ODM Extensions"],"sub_categories":["Active Record Sharding"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdrecom%2Factiverecord-turntable","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdrecom%2Factiverecord-turntable","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdrecom%2Factiverecord-turntable/lists"}