Browse Category


Department of theoretical fantasizing

In the world of software development, although probably in any other too, there is an interesting phenomenon. Specialists are divided into two types: the performer and the teacher.

The performer (inventor) – who writes a lot, practices, makes mistakes, draws conclusions, and constantly improves their professional hard skills.

The teacher – who theorizes a lot, writes little, constantly thinks about different algorithms, can take months for one seemingly simple task but without noticeable results.

Teachers are also needed, they fit perfectly into a position not really related to actual development.


At work, I needed to create a mock service for conducting tests for our services, but I did not find a service in the public domain that would satisfy my needs. These are: creating a mock endpoint, assigning it various response templates (with the ability to assign several at once so that they are randomly selected), and most importantly – relay. So that it would be possible to simulate the work of DLR.

So a small Next.JS project with authorization, endpoint management, response templates, and relays appeared.

AI / Rust / Python

I’ve started learning a new programming language Rust. This language is often used for system programming or creating high-performance applications.

While learning, I’m working on my pet project on GitHub, which includes integration with OpenAI (ChatGPT) and TTS service. I’m planning to integrate it with some AI for image generation (like

I also had to write a small Python script using FastAPI and Silero AI for TTS requests. The bot can answer in voice, reading responses from ChatGPT. For this, I had to set up a separate service.

This pet project has already proved to be helpful in my daily work. It helped me create a well-written profile page for GitHub and endlessly answered my questions about learning Rust.

By the way, I also generated the preview for this post on

This pet project has already proven itself well. It helps me in my daily work, it helped me to create a proper profile page for Github and endlessly answers my questions about learning Rust.

By the way, I also generated the preview for this post on

PM2 cluster prometheus exporter

I needed to extract certain metrics for events from the Node.js application. For example, increment the metric in case of a successful response, and so on.

I had Zabbix and Grafana at my disposal.

It turned out that there is a prom-client module for Node.js that can export metrics, but the problem is – like other modules, it does not work with pm2.

The problem is that a metric collected in one process cannot be correctly received in another process, which is responsible for providing the metric to the zabix agent through http.

We fix the omission: pm2-prom-client

The module is basically for Prometheus, but it also suits us.

Its essence boils down to transmitting the metrics on the pm2 bus to the agent process with subsequent export in plain-text or JSON.

Zero Downtime Deployment / TypeScript

Today we will talk about zero downtime deployment in a Node.js application.

To make this possible, your application must be running in a child process. For example, use PM2 or ts-node-dev.

The first thing we need to do is to indicate that a new (deployed) process is ready to take over the work of the redeployed application. To do this, you need to call…


In your application, after all the necessary dependencies are in the ready state, such as a successful connection to the database.

Also, in our application, we need to add logic for the completion of all current operations when receiving a termination signal (SIGINT).

process.on(“SIGINT”, () => {
  this.connection.close(); // For example, we will close the current connection to AMQP and stop accepting new messages.
  setTimeout(() => {
  }, 5000) // Let's wait for 5 seconds until the current processes are completed.

When running such an application, for example, using ts-node-dev, you may notice that after pressing control+c, the application does not terminate immediately, but after 5 seconds.

What will happen:

  • The new application launched in a child process starts and reports “ready”, after which it begins its business logic.
  • At the same time, a SIGINT signal is sent to the old process, and it enters the mode of terminating and finalizing its work, after which it is destroyed.


class App {
  private isOnline = true

  public start() {

  private loop() {
    if (!this.isOnline) return
    console.log("Some business logic like redis/sql/amqp and others operation")

  private restartListener() {
     if (typeof process.send !== "function") return

     process.on(“SIGINT”, () => {
       this.isOnline = false
       setTimeout(() => {
       }, 3000)


Asterisk, ARI. Commute like a God

This small article will not cover anything about Asterisk dialplan. It will be about ARI – a flexible interface for Asterisk management.

As soon as Asterisk receives an invite and the call goes to our application (Stasis), we get the opportunity for low-level call construction.

Interaction with ARI occurs through receiving events via WebSocket from Asterisk, processing and creating new events through HTTP REST API towards ARI.


The event that our program receives when the channel enters the Stasis context is StasisStart. It can signal, for example, the start of an outbound or inbound call, as a result of which we launch low-level logic to create a channel towards another subscriber, add it to the bridge with the initiator channel, and make a call.

Simplified scenario of a regular call

  1. Received StasisStart event from ARI indicating channel A has been created.
  2. Created channel B with an endpoint towards a SIP peer, or a local proxy (example: SIP/MY_PEER/331234567890).
  3. Combined channel A from step 1 and channel B from step 2 into a bridge.
  4. Initiated a dial into channel B.
  5. Waited for the ARI ChannelStateChange event for channel B. And if the state is ‘Up’, launched an answer in channel A and the dialog begins.
  6. When receiving the ChannelHangupRequest event for either channel A or B, we terminate the call.

Call session

It may be necessary to store data about the call process, including CDR, for each channel.

As a storage solution, I would recommend using Redis, as high CPS and intensive database queries can create significant load on the hard drives and cause performance degradation.


To ensure optimal operation of your ARI application under high CPS, I would recommend minimizing queries to the relational database. In my practice, I used queries only for minor limiting logic during call initialization and for recording CDR data after the call is completed. All other queries are performed in Redis.

I also recommend placing the your ARI application on the same host as Asterisk for infrastructure purposes in order to reduce latency.

Performance test

For testing, I used the console utility baresip, initiating a bash script to perform 200 calls to a pool of test numbers that answer with asterisk tt-monkeys.

200 parallel calls consumed about 5% of CPU load in total. All calls ended successfully, including recorded CDR data.

Debugging of a stasis application that signals answered calls.
SIP signaling

Pandemic as a test of IQ and whether or not to censor the Internet?

In the days when the internet had just received tools for communication between ordinary users (FIDO, ICQ, web forums), we discussed news, musicians, technologies, games online. A computer wasn’t available to everyone, and even fewer had a modem connection and a setup for communication. Therefore, there were practically no “lamers” online.

Since then, the internet has changed a lot. Politics has entered, and practically everyone today has a connection to the internet and the ability to change the world in a few clicks on a mobile phone screen.

Keep Reading

Красная Рука, Черная Простыня, Зелёные Пальцы

Я думаю многие мои ровесники хотя бы раз слышали байку про девочку и гроб на колесиках.

– Девочка, а девочка! Гроб на колёсиках нашел твой дом. Сейчас он ищет твой подъезд.

В детстве я с удовольствием читал эту повесть состоящую из маленьких рассказов-страшилок. В крайний раз я даже переслушал аудио книгу, пока косил траву у отца дома года три назад.

В детстве на меня эти байки произвели большое впечатление. Позже я с удовольствием рассказывал их в детских лагерях, где к слову и свои байки существовали и были очень похожими. 

Так что Успенский для меня был в первую очередь автор Красной Руки, Черной Простыни и Зеленых Пальцев. 


Красные Носки

Мама послала дочку на рынок купить носки. Дала ей денег и сказала, чтобы девочка ни в коем случае не покупала Красные Носки. Когда девочка пришла на рынок, ей понравились только Красные Носки.

Девочка решила, почему бы не купить и красные? Купила и решила сразу примерить. Вышла с рынка и надела их. На автобусе домой она не поехала, чтобы пройти по улице в этих носках. Но у нее скоро стали болеть ноги. Она решила, что это туфли ей натерли, и пошла дальше.

Когда девочка подошла к дому, то ей стало так больно, что она упала. Мама выбежала из дома, увидела Красные Носки и скорее стала их снимать. Но когда сняла, то там остались одни обглоданные кости от девочкиных ног.

Зеленые Глаза

Одна девочка любила зеленый цвет. Мама купила ей в магазине зеленую куклу и такую же пластинку и сказала:

— Без меня не играй этой куклой и не слушай эту пластинку.

Но дочь не послушала маму и включила пластинку. Пластинка запела:

«Бегут, бегут по стенке зеленые глаза,
Девочку задушат — Да! Да! Да!»

Тут в дверь позвонили. Девочка открыла, а там стояла мать без головы. Она сказала (чем?):

— Я же говорила тебе, а теперь идем со мной.

Девочка вышла во двор, и здесь Зеленая Кукла задушила ее.