Skip to content
This repository has been archived by the owner on Nov 14, 2022. It is now read-only.

zendesk/global_uid

Repository files navigation

GlobalUID is deprecated and will no longer be maintained.

Zendesk is working on a new unique ID solution that has made this library redundant, and will no longer be actively maintained. Internal staff are recommended to use this private transitional library.


Global UID Plugin

Build status

Summary

This gem allows you to generate global IDs as described in this article from Flickr for your Ruby on Rails applications. It does this by patching ActiveRecord::Base and ActiveRecord::Migration so that new models retrieve their ID from one of the configured alloc servers (short for ID allocation databases), this functionality is opt-out, not opt-in. The databases responsible for allocating your identifiers (aka id_servers) should have their auto_increment_increment and auto_increment_offset setting configured globally.

This gem only supports MySQL databases and the documentation is written with that in mind but the concept could be applied to others.

Resilience

The gem will iterate over the configured id_servers, choose one at random and attempt a connection, returning the ID from the first alloc server to successfully respond. If there's a connection failure, the server will be removed from the pool and retried after the configured connection_retry period. If there's an allocation failure, the server will be removed from the pool and retried after 60 seconds.

In either failure scenario, the configured notifier will be called and the gem will move through the list of configured id_servers until it gets a successful response. If no ID can be retrieved, a NoServersAvailableException is thrown and the connection state is reset so that subsequent requests will retry immediately.

Installation

Add it to your gemfile and run bundle install:

gem "global_uid"

Configuration

First configure some databases in database.yml in the normal way.

id_server_1:
  adapter: mysql2
  host: id_server_db1.prod
  port: 3306

id_server_2:
  adapter: mysql2
  host: id_server_db2.prod
  port: 3306

Then setup these servers, and other defaults in your environment.rb:

GlobalUid.configure do |config|
  config.id_servers = [ 'id_server_1', 'id_server_2' ]
  config.increment_by = 5
}

For a full list of configuration options, and their defaults, see GlobalUid::Configuration

Migration

Migrations will now add global_uid tables for you by default. They will also change your primary keys from signature "PRIMARY KEY AUTO_INCREMENT NOT NULL" to "PRIMARY KEY NOT NULL".

If you'd like to disable this behavior, you can by setting use_global_uid to false as show below:

class CreateFoos < ActiveRecord::Migration
  def self.up
    create_table :foos, use_global_uid: false do |t|

Model-level stuff

If you want GlobalUIDs created, you don't have to do anything except set up the GlobalUID tables with your migration. Everything will be taken care you. It's calm, and soothing like aloe. It's the Rails way.

Disabling global uid per table

class Foo < ActiveRecord::Base
  disable_global_uid
end

Taking matters into your own hands:

class Foo < ActiveRecord::Base
  disable_global_uid

  def before_create
    self.id = generate_uid()
    # other stuff
    ....
  end
end

If you're using a non standard uid table then pass that in.

generate_uid(uid_table: '<name>')

Testing

mysql is a required and can be installed with brew install mysql@5.7. If already installed, it's expected to be running with the defaults (root@127.0.0.1:3306). Set the MYSQL_URL environment variable if you're using something different.

This gem uses minitest and the test suite can be run with bundle exec rake test.

If you want to run a particular scenario, it can be done by passing the line number in, e.g. bundle exec ruby test/global_uid_test.rb -l 18

Copyright (c) 2010 Zendesk, released under the MIT license