<commit_before># DataMapper Master/Slave Adapter (for MySQL replication etc)

This DataMapper adapter provides a thin layer infront of at least two
real DataMaper adapters, splitting reads and writes between a 'master'
and a 'slave'.

The adapter comes in two parts:

  1. The MasterSlaveAdapter, which knows of only two 'real' adapters
  2. A ReaderPoolAdapter, which knows of any number of 'real' adapters
     to use as readers.  You can set the ReaderPoolAdapter as the reader
     for the MasterSlaveAdapter.


## Installation

Via rubygems:

    gem install dm-master-slave-adapter


## Usage

The adapter is configured, at a basic level in the following way:

    DataMapper.setup(:default, {
      :adapter => :master_slave,
      :master  => {
        :adapter  => :mysql,
        :host     => "master.db.site.com",
        :username => "root",
        :password => ""
      },
      :slave   => {
        :adapter  => :mysql,
        :host     => "slave.db.site.com",
        :username => "root",
        :password => ""
      }
    })

Here we create a repository named :default, which uses MySQL adapters for the
master and the slave.

In YAML, this looks like this:

    default:
      adapter: master_slave
      master:
        adapter: mysql
        host: "master.db.site.com"
        username: root
        password: 
      slave:
        adapter: mysql
        host: "slave.db.site.com"
        username: root
        password: 

Both the master and the slave are named :default, but you cannot access them directly
with DataMapper.repository( ... ); you can only access the MasterSlaveAdapter.

It is possible to access both the master and the slave using accessors on the
MasterSlaveAdapter, however:

    DataMapper.repository(:default).adapter.master
    DataMapper.repository(:default).adapter.slave

### Bind to master on first write

It is important to note one particular behaviour with this adapter.  By design, after
the first write operation has occurred, all subsquent queries, including reads, will
be sent directly to the master.  This is almost always the desirable behaviour, since
you will undoubtedly experience race conditions due to reader-lag if not.

You can force the binding to the master at any time, using:

    DataMapper.repository(:default).adapter.bind_to_master

This is a state changing method and will remain in effect until you reset the binding
with:

    DataMapper.repository(:default).adapter.reset_binding

In a web application, you'll typically want to reset the binding to master at the end
of each request, to ensure subsquent requests are not permanently bound to the master.

A Rack middleware is provided to do this automatically.  The easiest way to use this in
a Rails application, is to mount it inside your ApplicationController:

    class ApplicationController < ActionController::Base
      use DataMapper::MasterSlaveAdapter::Binding, :default
    end

You can use the middleware anywhere a Rack middleware can be used, however, but it must
be executed after DataMapper has been initialized.

Note that accessing the master directly, (again, by design) will not cause all subsquent
queries to be sent to the master in the same way implicit querying does.  This is useful
when logic is isolated to a specific part of your application and you know other parts of
the application need not query the same storage backend.  I personally do this for
session storage.

Lastly, you can force all queries to be implicitlty sent to the master in the context of
a block, simply by passing a block to #bind_to_master, like so:

    DataMapper.repository(:default).adapter.bind_to_master do
      ...
    end

Once the block has completed, the adapter will be restored to its original state,
regardless of what writes may have occurred.  Note that if the adapter was already
implictly bound to master before the block was invoked, this will have no effect.


### Using the ReaderPoolAdapter

The ReaderPoolAdapter simply allows you to use more than one adapter as the 'slave' when
configuring the MasterSlaveAdapter.  For every read query it receives, it picks a random
adapter from its pool.

It is configured like so:

    DataMapper.setup(:default, {
      :adapter => :master_slave,
      :master  => {
        ...
      },
      :slave   => {
        :adapter  => :reader_pool,
        :pool => [
          {
            :adapter  => :mysql
            :host     => "slave1.db.site.com",
            :username => "root",
            :password => ""
          },
          {
            :adapter  => :mysql
            :host     => "slave2.db.site.com",
            :username => "root",
            :password => ""
          }
        ]
      }
    })

In the above setup, we simply have two MySQL hosts specified as available
slaves to the MasterSlaveAdapter.  In YAML, that looks like this:

    default:
      adapter: master_slave
      master:
        ...
      slave:
        adapter: reader_pool
        pool:
          - adapter: mysql
            host: "slave1.db.site.com"
            username: root
            password: 
          - adapter: mysql
            host: "slave2.db.site.com"
            username: root
            password: 

## Reporting Issues

Please file any issues in the issue tracker at GitHub:

    - https://github.com/d11wtq/dm-master-slave-adapter/issues

## Potential TODOs

  - Raise an exception for #create, #update and #delete on the reader
  - Enhanced logging to include the details of the adapter being used

## Copyright and Licensing

Copyright (c) 2011 <NAME>
<commit_msg>Fix README<commit_after># DataMapper Master/Slave Adapter (for MySQL replication etc)

This DataMapper adapter provides a thin layer infront of at least two
real DataMaper adapters, splitting reads and writes between a 'master'
and a 'slave'.

The adapter comes in two parts:

  1. The MasterSlaveAdapter, which knows of only two 'real' adapters
  2. A ReaderPoolAdapter, which knows of any number of 'real' adapters
     to use as readers.  You can set the ReaderPoolAdapter as the reader
     for the MasterSlaveAdapter.


## Installation

Via rubygems:

    gem install dm-master-slave-adapter


## Usage

The adapter is configured, at a basic level in the following way:

    DataMapper.setup(:default, {
      :adapter => :master_slave,
      :master  => {
        :adapter  => :mysql,
        :host     => "master.db.site.com",
        :username => "root",
        :password => ""
      },
      :slave   => {
        :adapter  => :mysql,
        :host     => "slave.db.site.com",
        :username => "root",
        :password => ""
      }
    })

Here we create a repository named :default, which uses MySQL adapters for the
master and the slave.

In YAML, this looks like this:

    default:
      adapter: master_slave
      master:
        adapter: mysql
        host: "master.db.site.com"
        username: root
        password: 
      slave:
        adapter: mysql
        host: "slave.db.site.com"
        username: root
        password: 

Both the master and the slave are named :default, but you cannot access them directly
with DataMapper.repository( ... ); you can only access the MasterSlaveAdapter.

It is possible to access both the master and the slave using accessors on the
MasterSlaveAdapter, however:

    DataMapper.repository(:default).adapter.master
    DataMapper.repository(:default).adapter.slave

### Bind to master on first write

It is important to note one particular behaviour with this adapter.  By design, after
the first write operation has occurred, all subsquent queries, including reads, will
be sent directly to the master.  This is almost always the desirable behaviour, since
you will undoubtedly experience race conditions due to reader-lag if not.

You can force the binding to the master at any time, using:

    DataMapper.repository(:default).adapter.bind_to_master

This is a state changing method and will remain in effect until you reset the binding
with:

    DataMapper.repository(:default).adapter.reset_binding

In a web application, you'll typically want to reset the binding to master at the end
of each request, to ensure subsquent requests are not permanently bound to the master.

A Rack middleware is provided to do this automatically.  The easiest way to use this in
a Rails application, is to mount it inside your ApplicationController:

    class ApplicationController < ActionController::Base
      use DataMapper::MasterSlaveAdapter::Binding, :default
    end

You can use the middleware anywhere a Rack middleware can be used, however, but it must
be executed after DataMapper has been initialized.

Note that accessing the master directly, (again, by design) will not cause all subsquent
queries to be sent to the master in the same way implicit querying does.  This is useful
when logic is isolated to a specific part of your application and you know other parts of
the application need not query the same storage backend.  I personally do this for
session storage.

Lastly, you can force all queries to be implicitlty sent to the master in the context of
a block, simply by passing a block to #bind_to_master, like so:

    DataMapper.repository(:default).adapter.bind_to_master do
      ...
    end

Once the block has completed, the adapter will be restored to its original state,
regardless of what writes may have occurred.  Note that if the adapter was already
implictly bound to master before the block was invoked, this will have no effect.


### Using the ReaderPoolAdapter

The ReaderPoolAdapter simply allows you to use more than one adapter as the 'slave' when
configuring the MasterSlaveAdapter.  For every read query it receives, it picks a random
adapter from its pool.

It is configured like so:

    DataMapper.setup(:default, {
      :adapter => :master_slave,
      :master  => {
        ...
      },
      :slave   => {
        :adapter  => :reader_pool,
        :pool => [
          {
            :adapter  => :mysql
            :host     => "slave1.db.site.com",
            :username => "root",
            :password => ""
          },
          {
            :adapter  => :mysql
            :host     => "slave2.db.site.com",
            :username => "root",
            :password => ""
          }
        ]
      }
    })

In the above setup, we simply have two MySQL hosts specified as available
slaves to the MasterSlaveAdapter.  In YAML, that looks like this:

    default:
      adapter: master_slave
      master:
        ...
      slave:
        adapter: reader_pool
        pool:
          - adapter: mysql
            host: "slave1.db.site.com"
            username: root
            password: 
          - adapter: mysql
            host: "slave2.db.site.com"
            username: root
            password: 

## Reporting Issues

Please file any issues in the issue tracker at GitHub:

  - https://github.com/d11wtq/dm-master-slave-adapter/issues

## Potential TODOs

  - Raise an exception for #create, #update and #delete on the reader
  - Enhanced logging to include the details of the adapter being used

## Copyright and Licensing

Copyright (c) 2011 <NAME>

{'fraction_non_alphanumeric': 0.06974450918870462, 'fraction_numerical': 0.0021515015688032273, 'mean_word_length': 2.708776595744681, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 53, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1902647', 'n_tokens_mistral': 2965, 'n_tokens_neox': 2856, 'n_words': 1321}