Rails migration strategies on horizontally scaled apps - ruby-on-rails

Assume I have an OpsWorks Rails application running with load and time based scaling.
What happens if I deploy code where there are multiple application servers running, in which multiple rake db:migrate is executed across the application servers?
Does Rails have any guard against this? OR would I specifically need to specify a single server that is responsible for running the migrations?
I am also curious to hear about migration strategies for Rails + RDS (Postgresql) on AWS.

The answer is Yes, Rails had a guard against this situation
First, the RDS itself can cache your queries. So for example, 2 of your instances running one CREATE INDEX query at the same time, the RDS itself can handle it.
Second, Rails automatically create a table named schema_migrations. When one of your instances running db:migrate, the table schema_migrations can help the other instances know that the database is already migrated up ( just like a version management system )
But, there is a bad practice that you wrote some custom queries in db/migrate/***.rb file, then your query might not be handled correctly by RDS.
If you have to do something like update data by custom domain, you should write a rake task and manually execute it.
So, if you only use db:migrate to update data structure, then everything already handled for you, even you had hundreds instances.
For more information, please refer Rails's document

Related

Multiple databases in Rails

I'm trying to setup two database for a single Rails Application. The first one is would be the main database and the second would be there in the case the main database would crash. So, I need to manage the two databases (rake db:create, migrate...) and replicate the datas to the second one.
Does anybody know how to do this ?
You should not do that on Application Layer.
Use keepalived or Amazon RDS.

How best to create table on initialization?

Happy New Year everyone.
In my Rails 4 application I have a table plans containing the records for the plans that a user can subscribe to.
It is absolutely paramount for the app that this table is populated at any time, in development, test, and production mode. Otherwise the app will not work.
What is the best way to create those records?
Should I put a create method into an initializer? Or set up a rake task and run it manually whenever I restart the server (sounds a bit cumbersome, though)?
Thanks for any help in this matter.
Rails has a 'seeds' feature that should be used for seeding a database with initial data.
It's a really simple feature: just fill up db/seeds.rb with some Ruby code, and run rake db:seed
source: http://edgeguides.rubyonrails.org/active_record_migrations.html#migrations-and-seed-data
If you want to use data in your test environment, you might also be interested in using fixtures for your plans. Take a look at http://guides.rubyonrails.org/testing.html#the-low-down-on-fixtures

Best Practices - RoR 4 Heroku - Cron to fill database each hour from external API

I have to call externals API to fill my database, hosted on Heroku each hours.
For this purpose, I've a ruby script that get all the data from externals API and output on the stdout. Now, I would like to store those results in my database, I have differents ways to do it (Please let a comment if you know a better way).
What I have (Constraints) :
Ruby on Rails Application running on Heroku
PG Database hosted on Heroku
"Cars" model, with "Title", "Description", "Price" attributes, and 1 other nested attribute from "Users" Model (So same schema in PG).
Ruby Script that query the differents externals API
Ruby Script have to be called each hours / 2 hours / days. The script is going to run for about 10 minutes -> 2 hours depending of the number of results
My 3 differents ways to do it :
Running the script on a EC2 Instance, and fill my database with external login directly to the database, not by the Ruby on Rails REST API.
The problem is that it never ask for the Ruby on Rails validators, so for example if my database changed, or if I have to validate some data, it won't.
Running the script on a EC2 Instance, and fill my database with cll to my RoR REST API, so filling the data with JSON / XML. The problem is that I think if I have > 1000 calls from the API, it can make my dynos suffer with high load.
Running my script on a specific dyno on Heroku (I need some informations, I can't find some informations on Heroku)
(Please let a comment if you know a better way)
What do you think ? I need something really evolutive, if tomorrow i change my "Cars" model, everything has to be easy to make the switch between old and new model.
Thank you.
I would think that the best approach would be to use a background process to perform the work. Gems like http://sidekiq.org/ and DelayedJob all have the ability to schedule jobs (which then reschedule themselves for 2 hours later in your case).
On Heroku, workers run seperate to your web dynos so won't interfere with the performance it also keeps things simple in that you don't need to expose an API since you'll have direct access to your models from the worker.
There are plenty of Heroku docs on this subject;
https://devcenter.heroku.com/articles/background-jobs-queueing
https://devcenter.heroku.com/articles/delayed-job
You can do this by writing your scripts as a Rake tasks and then use Heroku Scheduler to schedule your task(s) to run at specific intervals:
https://devcenter.heroku.com/articles/scheduler
You can separate your tasks by schedule if you have multiple, and then just add multiple schedulers. They run in one-off dynos (which you pay for at the normal rate), and since they're running from the same code base can leverage all your existing app code (models, libs, etc).

How to manage migrations when multiple apps share the same database in Ruby?

I have a Rails app and a Sinatra app, sharing the same database. The Sinatra app uses ActiveRecord.
Can I run migrations from within each app, as if they were in the same app? Will this cause any problems?
The schema.rb file in the Rails app tracks the current migration via
ActiveRecord::Schema.define(:version => 20121108154656) do
but, how does the Sinatra app know the current version the database?
Rails 3.2.2, Ruby 1.9.3.
The version column in the schema_migrations table equate to the time stamp on the front of the ruby migration file example: 20130322151805_create_customers.rb So if two ore more applications are contributing to the schema_migrations table roll backs will not be possible if rails can't find the down() method (because it will not find a migration file contained in another app ie db/migrate/...)
I have a current situation that is exactly this and I have opted to have a master ActiveRecord app that manages migration and data conversions as our database evolves. Keep in mind that part of the deal is to keep models up to date as well. This has been time consuming so we are considering breaking apart the DB in to business domains and providing APIs (JSON) to query support data for another application. This way each application manages it domain and is responsible for exposing data via API.
regards.
If you connect both applications to the same database you should be able to run migrations on it but I strongly suggest you use another option since you will almost surely hit a wall at one time or another:
split the database in two if possible with each application responsible for its own database /migrations.
have one application considered the "master" database and use another database for the data specific to the second application but make it connects to both database (each application still only apply migrations to one database)
If you need to share data between multiple applications another option is to implement a REST service in one and use it on the other, you can have a look at the grape gem for a simple way of doing so.
Edit: I realize I forgot to speak about the activerecord migration, there is no longer any "version" of the schema, what activerecord does is that it read all your migration filename, extract their identifier (the starting part) and check if they have already been applied so in theory you can run migrations from two applications on the same database provided they don't interfere.
But if both migrations act on the same tables you will almost certainly run into big troubles at one point.
I disagree with Schmurfy, even if his presented options are valid, its a bit of an overkill to share data through REST (granted, its pretty easy to implement with ruby / rails).
If your case is simple you could just use one database from both apps, and since you use AR in both of them you have no problems with versioning, AR takes care of that.
Also i dont know what happens if you run db:migrate from both apps simultaniously if you use a inferior dbms like mysql which does not allow DDL in a transaction, certainly nothing good..
Also it would bother me to look which app needs what column and not have the migrations in one place. You could use a shared repository to manage the migrations from both apps.
Rails migrations store current database version in schema_migrations table in the database. So both of your apps will be able to check the current version.
The version numbers are timestamps, so there shouldn't be any problem with duplicate values, as it'll be almost impossible to generate two migrations at the exact same millisecond. So you should be fine here.
The only problem I see is that when you rollback a migration in one app, it'll set the db to the previous known version and I'm not sure if it will pick the previous one from the db (which could be from the other app), or the number from the previous migration file. You may want to test that scenario to make sure.
I decided to put all migrations in the Rails app because:
Since there is only one database
Rails manages migrations
This has worked well.
This simplifies the system because all migrations are stored in one place. And, the Sinatra app doesn't need to know about them anyway.

Ruby on Rails: is it okay to use old school database access without migrations?

I'm switching to RoR from ASP.NET MVC. Yeah, migrations are cool, but I do not need to use different databases in my web applications. Postgresql will do just fine.
So is it okay if I use PGAdmin to create and administer my databases and schema and avoid all these fancy migrate, rake etc?
Update
Thanks everyone! Now I better understand what migrations are, and why I should use them.
I don't think that's what migration means.
Migrations in rails (and in other frameworks) is a method by which you can use to update your database schema when there are multiple versions of the same database running
For example, you may have two databases, one running on your production server, and another running locally for development. After a few days of coding, your local development database may looks a bit different. With migrations, you can simply push your code to the production server and then run the migrations to automatically update your production database so it is up-to-date with the one you use locally for development.
So, to answer your question, Yes it is OK but you might not get a few of the migrations niceties when the time comes that you'll have to maintain multiple versions of your database.
Have to agree with charkit but one (rather two) important note why you should use migrations: Migrations don't make up the model definitions. They are stored seperately in a file schema.rb. This defines the rows and tables of your database. When looking into the file, you find these lines:
This file is auto-generated from the current state of the database. Instead of editing this file, please use the migrations feature of Active Record to incrementally modify your database, and then regenerate this schema definition.
The second reason is for testing: you can easily set up a test database to run all your tests against without the need to touch the "real" database. I know when developing, this is not a big problem but this will get more important after some time.
So, yes, it is possible to use PGAdmin to create all your database related stuff but you should not forget to always keep the schema file up to date and come up with a solution for testing.
With migrations you're able to develop your database schema in Ruby and this is usually database indpendent.
In short, spend the 20 minutes or so to really get migrations and the value they add. Then determine whether or not you want to ditch them. Strangely for me I learned Rails before I started my first MVC project; one of the things I missed most was migrations.
From a technical standpoint you should be fine without them.

Resources