In Container-based DevOps solutions like Kubernetes, ECS, Heroku an application must be able to stop accepting new client requests before termination, and, most importantly, it must successfully complete already running requests and processes.

By default in most systems Graceful Shutdown implements by sending SIGTERM signal and 30 seconds delay before terminating the instance.

How to handle SIGTERM in Ruby?

There are two similar ways:

  1. Using Signal.trap
  2. Rescuing SignalException

Both constructions allow handling Linux signals, below I will give some examples with handling SIGTERM and describe the differences. Also, you can use the full list of POSIX signals.

Catch Signal with Trap

I will write an app that publishes messages to…


What is the difference, how and when to apply?

Stub

A stub is the only defined result of the method call which doesn’t care about behavior. With RSpec, you can use stub with allow and receive methods.

allow(object).to receive(:method_name)

If you need to stub the result of the method then it’s possible with and_return

allow(object).to receive(:method_name).and_return(example_value)

Mock

Mock expect methods to be called, otherwise it raises an error. With RSpec, you can use mock with expect and receive methods.

expect(object).to receive(:method_name)

As well as the stub replacing mock result possible with and_return

expect(object).to receive(:method_name).and_return(example_value)

Double

Test double is a dummy object that you use to replace a real object during a test…


Failure Management, Fallbacks, Exponential backoff, Tools and Patterns

When designing modern applications on microservices architecture and systems based on cloud solutions such as AWS, Azure, or Google Cloud imply the need to handle expected failures.

How to handle failures?

  1. Restarting the code in the current thread runtime
  2. Retry execute in background jobs

Retry failed code

We can represent the simplest retry in runtime as a rescue block and variable with a count of executed retries.

Also Ruby has built-in retry keyword, an example can be changed in the next way:

Some best practices related to exceptions:

  1. Any application-level error should be a child of StandardError, for e.g. ApiError = Class.new(StandardError)
  2. List of handled errors should be specified in rescue…


How to manage encrypted keys for different environments

There are two most popular ways to manage secrets in your application.

  1. Encrypted file with secrets. Best choice for a single monolith application. There’s no need for additional software, just keep your encrypted data in the app repository and move decrypt key under git ignore.
  2. Centralized storage. For large and complex systems it’s better to use dedicated storage for all services and provide an interface for them. Vault is a cool example of this kind of solution.

In this article, I want to talk about the first approach.

Encrypted secrets were first introduced in Rails 5.1. Rails store secrets in…


A tool for monitoring SQL queries in Rails

Get notified about slow queries

In the early stages of development, it may be useful to identify slow queries in time (when you don’t have a paid APM). QueryTrack helps to get notified about slow queries with related data: duration and backtrace.

https://github.com/kirillshevch/query_track

Installation

Add this line to your application’s Gemfile and then execute bundle install:

gem 'query_track'

To start receiving information about requests you need to createconfig/initializers/query_track.rb where there is a time limit that is specified in seconds and an output channel (for example console logs):

QueryTrack::Settings.configure do |config|
config.duration = 0.5
config.logs = true
end

Configuration

SQL Duration Limit (Time Limits)

You won't get any notifications without setting the max…


Publish/Subscribe Pattern with Message Brokers and usage of core concepts. Asynchronous execution of the application parts.

One of the tools that are rarely covered in the Ruby/Rails world are the message brokers (probably because they mostly written in Java). Everyone are familiar mostly with background jobs processing, but message brokers offer a more flexible approach to asynchronous execution. For example, you can create a message from one application and process it in another and continue executing without waiting for the response.

Some benefits that you get at the architectural level:

Fault Tolerance, Guaranteed delivery, Asynchronous communication(through Publish/Subscribe pattern), Loosely coupling, etc.

One of the messaging brokers that I used is ActiveMQ. ActiveMQ provides most of these…


The main purpose of caching is making the application work faster. But also this mechanism can help to more flexibly manage data, a good example is session management.

Redis cache store

Rails 5.2 introduced built-in Redis cache store, which allows you to store cache entries in Redis.

To use Redis as a Rails cache store, use a dedicated cache instance that’s set up as an LRU (Last Recently Used) cache instead of pointing the store at your existing Redis server, to make sure entries are dropped from the store when it reaches its maximum size.

The Redis store works with the Redis gem and hiredis, as well as providing support for a number of configuration options, like setting one or multiple remote servers.

Usage

To get started, add the redis gem to…


Writing jobs, testing, pros and cons of this approach.

Sucker Punch — a single-process Ruby asynchronous processing library that runs with your existing app’s process.

Gem is built on top of concurrent-ruby and have no dependencies with any data storage, what is both an advantage and a disadvantage.

Running in the application process really simplifies the deployment process, but If the web processes are restarted with jobs remaining in the queue, they will be lost. Also, since all state persistence is in memory, Sucker Punch can operate extremely fast on small tasks. …


Module bundling, Loaders, Plugins, Babel

Webpack is a module bundler for modern JavaScript applications. The import and export statements have been standardized in ES2015. They are not supported in browsers yet, but webpack does support them out of the box. But actually it’s more powerful tool which can help us build whole our front-end.

Installing

Let’s start with initializing package.json by using npm init command.

Installing globally locks you down to a specific version of webpack and could fail in projects that use a different version. Therefore, we will install it locally.

npm install --save-dev webpack

Webpack will be added to devDependencies

Command Line Interface (CLI)

Because we are…


Using Git hooks to control code quality for Ruby, Rails and Chef

What is Linter?

Linter is a static analysis tool such as RuboCop. It checks the written code and makes suggestions based on pre-defined rules by community-driven coding style guides and common idioms.

Most definitions of linter default behavior can be changed for the needs of your team and project via various configuration options.

Why linting and following style guides is important?

There are many reasons to lint the code:

  1. It maintains code consistency
  2. It helps catch unnecessary code
  3. It helps avoid conflicts between developers and also to remember about the conventions
  4. It helps optimize performance and avoid problems with security

Don’t forget to lint with Git hooks and Overcommit

Git hooks are scripts that execute before or after actions such…

Kirill Shevchenko

Software Engineer. Interested in Full-Stack Development and DevOps.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store