A simple sharding library for Ecto.
Documentation can be viewed on hexdocs.
defp deps do
[
{:ecto_sharding, "~> 0.0.8"}
]
end-
Configure your app's
Ecto.RepoThis configuration will be used when a not-sharded schema is being queried.
config :my_app, MyApp.Repo, adapter: Ecto.Adapters.MySQL, username: System.get_env("MYSQL_USERNAME"), password: System.get_env("MYSQL_PASSWORD"), database: System.get_env("MYSQL_DATABASE"), hostname: System.get_env("MYSQL_HOST"), pool_size: 15
-
Configure
EctoShardingotp_appneeds to be set soEctoShardingknows how to builds the repos for each shard.config :ecto_sharding, EctoSharding, otp_app: :my_app
If you know your shard information at compile time, you can also add that.
Note: Be sure to set the
privkey for the shard repos to something different than the main db. Ecto uses theprivkey to determine where to put the migrations folder and schema files for a Repo. Defining this for the shards Repos avoids mixing the main db and shard db files in the same directory. In the example below, the shard db migrations will be inpriv/shards/migrations, and the main db files will be inpriv/repo/migrations(the Ecto default location whenprivis not specified).config :ecto_sharding, EctoSharding, otp_app: :my_app, shards: %{ "shard_1" => [ adapter: Ecto.Adapters.MySQL, username: System.get_env("MYSQL_USERNAME"), password: System.get_env("MYSQL_PASSWORD"), database: "my_db_shard_1", hostname: "10.0.0.1", pool_size: 15, priv: "priv/shards" ], "shard_2" => [ adapter: Ecto.Adapters.MySQL, username: System.get_env("MYSQL_USERNAME"), password: System.get_env("MYSQL_PASSWORD"), database: "my_db_shard_2", hostname: "10.0.0.2", pool_size: 15, priv: "priv/shards" ] }
-
Start
EctoShardingas a supervised processWhen the supervisor starts up, it will expect all of its configuration to be there, so make sure any config is set before
start_linkis called.supervisor(EctoSharding, [])
-
use EctoSharding.Repoinstead ofEcto.RepoIn any repos you have defined in your app, use
EctoSharding.Repoinstead:use EctoSharding.Repo, otp_app: :my_app
-
use EctoSharding.Schemainstead ofEcto.SchemaThe schema is where most of the magic happens. This is where you can declare a particular schema as sharded or not. Schemas will default to sharded.
A sharded schema
defmodule MyApp.User do use EctoSharding.Schema, sharded: true # default schema "users" do field :name, :string # ... end end
A not-sharded schema
defmodule MyApp.Account do use EctoSharding.Schema, sharded: false schema "accounts" do field :name, :string # ... end end
EctoSharding uses a shard registry, backed by GenServer to store information
about which shard we currently want to use and how to talk to that shard. This
means that you need to set the current shard in your application before you can
issue a query to the sharded database.
Setting the shard is as simple as
EctoSharding.current_shard("shard_1")Take a plug based web application for example. This is what a plug that sets
the current shard might look like:
defmodule MyApp.ShardContext do
@behaviour Plug
import Plug.Conn
def init(opts), do: opts
def call(conn, _) do
account = conn.assigns.account
EctoSharding.current_shard(account.shard_id)
conn
end
endOnce the current shard has been set, we can query our repo just like normal and it will take care of using the correct repo for the schema involved in the query.
import Ecto.Query
MyApp.User
|> where(name: "Jane Doe")
|> limit(1)
|> MyApp.Repo