Primary DB failover to backup MongoDB instance - ruby-on-rails

My Rails app runs primarily on a regular mySQL database, however, if this database goes down I would like the Rails app to failover to a MongoDB database which is basically just a 'cached' version of the primary database.
Some ideas I had were two models (AR and MongoDB - using Mongoid) and then catching exceptions in the controllers and using the MongoDB models if the primary fails, but I feel like that would be too cluttered having two models of everything. Another idea was (and I haven't tested) rescuing database connection exceptions in the model and using the model as a MongoDB one instead but thinking about it, if the model originally inherits from ActiveRecord::Base there might be issues.
What would be a good approach to tackle this?

I don't think there is any good way to have a failover between MySQL and MongoDB, and to be honest I'm not too fond of the idea.
Why not make your MySQL Backend failsave with a few slaves?

Related

Rails 5 App with Elasticsearch as database instead of a relational one

Is it possible to use Elasticsearch as database for a Rails Application?
I have gone through many sites, blogs, and videos to find the answer of this, but was unable to and this being the closest.
I am not sure how can it be done, what goes in the database/config.yml and will the schema be getting generated after migrate?
Yes, of course it is, but you cannot use ActiveRecord ORM, basically you'll have to create your own adapter.
If you want to go quick, I would advise you to create the activerecord models, just like any regular app, then use Searchkick and create mappings from your models.
You need to be aware that if you're not using a database to hold the values you'll need to create a repository to handle the CRUD operations in Elasticsearch.
Another option is to use https://github.com/elastic/elasticsearch-rails, but in both cases you need to have the Rails models.
If you really want to go for ElasticSearch only, in you controllers you need to call your own created repositories to fetch and save the records in ElasticSearch.
No, only these databases: MySQL, PostgreSQL, SQLite are supported if you want to use ActiveRecord, and there are also mappers for Mongo and the like.
There are some mappers and adapters out there though but I wouldn't touch them with a 10 foot barge pole - some things just shouldn't exist in this world.

Changing database from PostgreSQL to MySQL

I am building an e-commerce application using spree in rails. The application uses PostgreSQL as database. I want it to be changed to MySQL. How do I achieve this?
The short answer is, you don't. I've been through three Spree migrations where we were either using legacy data, or switching databases and trust me; you want nothing to do with this.
If you don't need to take the old data with you, you should be fine just running the migrations on a fresh MySQL database. If you need the legacy data, God be with you...
Converting Spree database schema is nothing nice, and it's hard to just pull what you need out of the database since because almost every data model depends on a foreign key from another. There are dental procedures I would go through voluntarily before attempting what you are proposing. This also begs the question; why do you need to go to MySQL from Postgres?

How can I have multiple schemas and multiple subdomains when hosting on Heroku?

I am planning on using Devise and Apartment in my upcoming application to create subdomains for each organization that creates an account. I would like to host my application on Heroku, but ran across the following quote:
The most common use case for using multiple schemas in a database is
building a software-as-a-service application wherein each customer has
their own schema. While this technique seems compelling, we strongly
recommend against it as it has caused numerous cases of operational
problems. For instance, even a moderate number of schemas (> 50) can
severely impact the performance of Heroku’s database snapshots tool,
PG Backups.
What technique would work well with Heroku to host basecamp-style subdomains in rails 4 where many users can log in to the subdomain which they are part of?
If Heroku does not work, what other PaaS options are there that would do this well?
Domain
Firstly, you need to be sure that you're using your own custom domain for the subdomains.
Heroku's standard xxx.herokuapp.com won't be able to handle another subdomain on top of that - so you'll basically need to use your custom domain from the get-go
It will be good to reference this documentation for more information!
Multi Tenancy
Although I don't have experience with PGSQL's schemas, I do have some with multi tenancy as a whole.
There are a number of great resources here:
Basecamp-style Subdomains (by DHH)
Multitenancy Railscasts (Pro)
Apartment Gem Documenatation
Essentially, multi-tenancy is just a way to scope the data so that it's only the tenant's that you see / interact with. In the sense of the DB, the two ways to achieve this are either to use different DB's (as you would with MYSQL), or use a schema (like with PGSQL)
Whilst I can't give you a direct fix for your issue, I can help you with some ideas:
Models
One way to achieve multi-tenancy, especially with the likes of MYSQL, is to do it through the model:
How do i work with two different databases in rails with active records?
#lib/admin.rb
class Admin < ActiveRecord::Base
self.abstract_class = true
establish_connection "#{Rails.env}_admin"
end
#app/models/option.rb
Class Option < Admin
# do stuff
end
This works very well for us, although we have not got it working for scoped accounts yet. We've been thinking of setting a ##class_variable for the Account or something, but haven't been working on that right now.
This works very well for MYSQL - powered databases, but also means you'll have to create db's for every account, which will not work with PGSQL (as far as I'm aware)
PGSQL Schemas
I feel this is kind of a cheat way to do this, as all the data is still stored in 1 database - it's basically just scoped around different types of data.
The problem here is that real multi tenancy should be where you completely separate the user's data, so you could cut it out of the app completely if they wanted. From a security & access perspective, it's the most flexible & modular way.
The problem for Heroku is they can only use one database (they give everyone access to their AWS database instances), meaning they can't allow you to create 50+ free databases (it just won't work very well).
You can, of course, use your own stack to create the databases you require, but in terms of PGSQL, it's just about creating the schemas for your data & then using something like -Apartment to make it happen:
PostgreSQL works slightly differently than other databases when
creating a new tenant. If you are using PostgreSQL, Apartment by
default will set up a new schema and migrate into there. This provides
better performance, and allows Apartment to work on systems like
Heroku, which would not allow a full new database to be created.

MongoDB with PostgreSQL in One Rails App

Can I use MongoDB and a PostgreSQL in one rails app? Specifically I will eventually want to use something like MongoHQ. So far I have failed to get this working in experimentation. And it concerns me that the MongoDB documentation specifically says I have to disable ActiveRecord. Any advice would be appreciated.
You don't need to disable ActiveRecord to use MongoDB. Check out Mongoid and just add the gem plus any models along side any of your existing ActiveRecord models. You should note that MongoHQ is just a hosting service for MongoDB and can be used alongside any Object Document Mapper (ODM).
For further details check http://mongoid.org/en/mongoid/docs/installation.html. Just skip the optional 'Getting Rid of Active Record' step.
On a recent client site I worked with a production system that merged MySQL and MongoDB data with a single Java app. To be honest, it was a nightmare. To join data between the two databases required complex Java data structures and lots of code, which is actually databases do best.
One use-case for a two database system is to have the pure transactional data in the SQL database, and the aggregate the data into MongoDB for reporting etc. In fact this had been the original plan at the client, but along the way the databases became interrelated for transactional data.
The system has become so difficult to maintain that is is planned to be scrapped and replaced with a MongoDB-only solution (using Meteor.js).
Postgres has excellent support for JSON documents via it's jsonb datatype, and it is fully supported under Rails 4.2, out of the box. I have also worked with this and I find it a breeze, and I would recommend this approach.
This allows an easy mix of SQL and NoSQL transactions, eg
select id, blast_results::json#>'{"BlastOutput2","report","results","search","hits"}'
from blast_caches
where id in
(select primer_left_blast_cache_id
from primer3_output_pairs where id in (185423,185422,185421,185420,185419) )
It doesn't offer the full MongoDB data manipulation features, but probably is enough for most needs.
Some useful links here:
http://nandovieira.com/using-postgresql-and-jsonb-with-ruby-on-rails
https://dockyard.com/blog/2014/05/27/avoid-rails-when-generating-json-responses-with-postgresql
There are also reports that it can outperform MongoDB on json:
http://www.slideshare.net/EnterpriseDB/the-nosql-way-in-postgres
Another option would be to move your Rails app entirely to MongoDB, and Rails has very good support for MongoDB.
I would not recommend running two databases, based on personal observations on how it can go bad.

Can we mix Mongodb dynamic attributes to an ActiveRecord model?

We are using a dynamic attributes plugin similar to this:
http://codaset.com/joelmoss/dynamic-attributes
Which allows us to store dynamic attributes in our rails model. Those dynamic attributes are in a single database column. We are facing performance issues because of this and I am wondering if MongoId, MongoMapper or other rails plugins will allow us to keep some attribute in ActiveRecord (keeping the < ActiveRecord::Base) but store the dynamic attributes in mongodb. We want to do this because we need to keep using MySQL for most of our existing system, but use MongoDB to store dynamic attributes about some models.
Basically this is what I am talking about:
http://www.railsinside.com/plugins/242-quickly-add-couchdb-to-existing-rails-models-with-stuffing.html
This plugin does the exact same thing using CouchDB.
I don't see any reason that MongoDB can't handle the same thing.
MongoMapper should implement the ActiveRecord pattern. However, Mongo also has some simple drivers for Ruby. All in all, the concept of storing dynamic attributes is a perfect use-case for MongoDB.
If you don't mind skipping "ActiveRecord" you can probably cook up your own using the basic Mongo drivers with very little work.
If you can't figure out the steps to do this, I would suggest pinging the groups (http://groups.google.com/mongodb-user/) and asking Kyle Banker directly (he's their ruby expert).

Resources