Mokkify

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.

https://github.com/icevl/mokkify

About progress and consensus

What is happening now is a struggle against progress. The desire to fence oneself off, to close one’s eyes and not notice the obvious. Culture is changing, technology is growing, human connections are evolving. Yes, our heritage and cultural traditions are very important. Of course, we should cherish and support them, but not accepting something new is a big mistake! The strength of the new generation has always been that they have both our heritage and new, fresh ideas. That’s why they say that children are better than their parents.

Any progress is unstoppable, and the scientific community should understand it better than anyone else. That’s why I’m eagerly waiting for the doors to open in the political system, for the fossilized pensioners to go outside to enjoy their carefree life, and for the young blood to come and take their place.

The young blood, understanding and using technology, realizing the variability of culture, and also able to use changes for good and adapt flexibly to them, without forgetting about heritage. Music, movies, painting.

Dividing people into “black” and “white” frames does not add anything to civil society. Z-patriots conservatives (we can repeat), who blindly trust propaganda, are closed to getting information from other sources and impose censorship on alternative opinions. The same story with the liberal community, which also bullying opponents, bans, mute speakers with opposite opinions. They insult and categorically reject others’ opinions.

It should be understood that each of us is unique and distinguishable, and each of us is capable of making our own contribution to society. The most productive way to progress is to listen to each others and address cultural, social, and political differences to take measures to solve the most significant problems of society.

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 dreamstudio.ai).

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 dreamstudio.ai.

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 dreamstudio.ai.

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…

process.send(“ready”)

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(() => {
    process.exit()
  }, 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.

Example

class App {
  private isOnline = true

  public start() {
    console.log("Started")
    this.restartListener()
    this.loop()
  }

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

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

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

}

Two years ago, I couldn’t even imagine

This year I constantly catch myself thinking that things are happening that I couldn’t even imagine not long ago:

  • Russia’s war with Ukraine, which is accompanied by the possibility of using nuclear weapons, primitive and flawed propaganda with inciting interethnic hatred. The freedom of speech has completely disappeared, and dissent is punished with fines and imprisonment
  • The birth of children and forced emigration first from Moscow to Sochi (a two-day drive), then from Sochi to Kazakhstan with family and car
  • The split in opinions in Russia has led to conflicts and quarrels, including among close people
  • A global crisis in the IT industry. Many giant companies are cutting jobs and thousands of IT specialists are being let go
  • Against the backdrop of the global crisis and war, many talented developers (especially single ones) refuse to leave the country (if they have the opportunity) and patiently wait until they are asked to go to war
  • ChatGPT is already ready to compete with many professionals. Now it is writing code fairly well in all languages based on the text specification, identifying vulnerabilities and bugs in any code, and you can also write a good text in any language for LinkedIn
  • Against the backdrop of attractive salaries in IT, education has been put on the fast track, and IT has lost some of its subculture. A very large percentage of specialists are motivated solely by money.

Some points turn the mind upside down:

  • People who taught us about kindness and national unity scold us for smoking cigarettes and fighting in school – they support the war
  • There are still people who are abstracted from what is happening
  • Among the supporters, there are also Orthodox people
  • Israel is attacking Palestine, which also does not cause any particular oppression in the Orthodox community
  • The result of years of one person’s work as a manager is impoverishment of the population, an unattainable level of corruption and a third world war. But people will continue to repeat “who if not him?”.

What I have learned as a result of this

You need to stay away from any ideology, especially one that imposes exclusivity on you. The world is huge. There are countless knowledge and opportunities. The modern world gives a chance to be free, to choose a home where you feel comfortable anywhere on the planet.

My new Mark2 rims XXR 526 2P

The previous wheels were on this car from the very beginning, so it was time to update them. Besides, I was tired of fixing them. Low-profile tires do not contribute to the preservation of the discs.

I really wanted SSR Minerva AGLE, but now it is a very rare find. So I bought something similar – XXR 526 2P, 8.5 inches in width and 35 offset, with R18 size. Plus additional spacers of 1.2 cm.

Keep Reading

Those who were silent, stopped being silent. Those who have nothing to wait for, saddle up.

Three years ago, I couldn’t understand why patriotic education was happening through militarization: the “Young Army”, concerts with military themes, periodic exhibitions of military equipment. Why do the military get such cheap mortgages instead of scientists? Today, there are no more questions left, and the government’s course is finally clear to me.

I am very sorry that Russia does not have its own Elon Musks, Bill Gates, or Steve Jobs. Obviously, they won’t grow here for at least 50 years. Aggression, the desire to take everything away from a successful neighbor, envy, rudeness, the desire for a free ride, the desire to deceive a neighbor – all of this is not close to me and disgusting.

It is already clear to me that I will not see innovative developments, advanced technologies, and space exploration in Russia in my lifetime. These will be pathetic parodies like phones from China with Google OS and US hardware, piracy, and perhaps some clones of popular services that will always lag behind in technical implementation, will be contaminated with kickbacks and embezzlement.

I have no desire to participate in a company that replaces imported services that have left Russia. I have learned my lessons from the situation with Pavel Durov and VKontakte, Yevgeny Chichvarkin, and the Nginx project. I opened and closed an individual entrepreneur, knocked on the doors of the tax authorities and Roskomnadzor. That’s enough, thanks.

I have decided to invest in education in the near future and evacuate my family and children. So that the children grow up free, without insane censorship. So that they can calmly say that 2 * 2 = 4, and the setting is for creation and not destruction.

PS: Yes, I understand perfectly well that censorship exists everywhere to some extent, and I also understand that now there will be prejudice against Russians in many places. But I believe that children have more chances to grow up open to the whole world there than here.

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.

StasisStart

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.

Optimization

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