Learning Emacs

So, I’ve started using emacs in my daily development and writing process, after a couple of years using vim exclusively. Why did i do it? Mostly curiosity, as i’ve heard of this great behemoth that does everything under the sun, and you can also use it for writing. And lot’s of people i look up to in the IT world are using it, so what the heck, i decided to give it a try.

If you ever heard of emacs having a steep learning curve, those claims are 100% correct, and this SO question shows it truthfully.
So, starting with emacs you will get a screen with an emacs logo, some instructions and no way of doing anything you are used to doing, like opening files, saving them, or exiting the editor. That is also true when you are learning vim, so if you are a sadist there is a funny game to play with junior developer, open up vim/emacs for someone who hasn’t used them, and tell them to exit it, hours of fun guaranteed.

Back to serious world. The best thing that will help you learn emacs, is emacs itself, open it, type C-h t (hold down control, press h, let control go, press t). And it will open up the tutorial for you. Be sure to read the whole tutorial first. Then let it sit in your head, and after a day or two, reread the tutorial. Then do what everyone has done when switching editors, stick to it for a week or two, it will be painful, and you always have the safety net of your favourite editor/IDE if you fail to bend emacs to suit your style. Yes, that is correct, emacs is there to bend to your needs, not the other way around. But customizing it is something you should wait with, until you learn to use the editor properly.

If you absolutely need a stater kit of some kind, you can try with emacs prelude:
which comes bundled in with almost all plugins that a normal IDE has, be sure to read the readme, because some of the default keybindings are changed.
Also, emacs has a lot of online resources for you to learn from/copy elisp code and customize it as much as you want/need. Here are some of them:
Planet Emacsen – An aggregation of emacs related blogs and topics, from all around the world

Emacs Wiki – A place to learn anything and everything about emacs, a very big and scary place, use the search

Sacha Chua’s Emacs category – A blog with lots of interesting reads on it, the link will get directly to the emacs archive

Refresh your elasticsearch index with zero downtime

I’m using a basic elasticsearch-rails setup on one of the applications I’m working on. The thing is, we sometimes need to make changes to the ES index, add new fields, or redo the existing ones. And when you have a database that needs at least 10 minutes(it was closer to 1 hour before we reworked the implementation), you can’t really afford that downtime. As ES-rails sets things up for you in a certain way, it was needed to use some of the underlying ES features to get the job done correctly.

So, it was needed to completely remove the downtime while doing the full reindex(deleting and creating the elasticsearch index). If you are already using elasticsearch-rails then you are familiar with the nomenclature, and probably with the methods described. For doing a complete reindex we require a rake task to do the job for us like this:

namespace :elasticsearch do
  task :reindex => :environment do
    index_name = Person.index_name
    Person.__elasticsearch__.create_index! force: true
    Person.all.find_in_batches(batch_size: 1000) do |group|
      group_for_bulk = group.map do |a|
        { index: { _id: a.id, data: a.as_indexed_json } }
      end
      Person.__elasticsearch__.client.bulk(
        index: index_name,
        type: "person",
        body: group_for_bulk
      )
    end
  end
end

This will effectively remove the index if it exists and reload the new data in the index, making it practically unusable until the task is done. Because this wasn’t an option, we looked into ES aliases and found them to be helpful. Basically, what we needed to do was to create an index with a unique name, and assign an alias to it, so that we could create and fill the index while the current one was still operational. So no downtime needed.

#...
index_name = "#{Person.index_name}_#{SecureRandom.hex}"
client = Person.__elasticsearch__.client
Person.__elasticsearch__.create_index! index: index_name, force: true
Person.all.find_in_batches(batch_size: 1000) do |group|
  #...
end
# to be sure there is no index named Person.index_name
client.indices.delete(index: Person.index_name) rescue nil
  # collecting old indices
  old_indices = client.indices.get_alias(name: Person.index_name).map do |key, val|
    { index: key, name: val['aliases'].keys.first }
  end
  # creating new alias
  client.indices.put_alias(index: index_name, name: Person.index_name)
  # removing old indices
  old_indices.each do |index|
    client.indices.delete_alias(index)
    client.indices.delete(index: index[:index])
end

So that is about it, you just call bin/rake elasticsearch:reindex and you have refreshed your elasticsearch index with zero downtime. Of course, you will have to implement some system to track the changed records while you were reindexing(remember we are working on a live system, so data is changing all the time). We used redis for that, to mark when reindexing has started $redis.set('elasticsearch:reindex_running', true) collected all changed record ids in a redis array, processed them via the regular indexing worker, and deleted the key after the alias was linked with $redis.del('elasticsearch:reindex_running').