Нотатки про програмування, музику, подорожі та плівку
Про мене  •  Список нотаток  •  Плівка

Пізніше Ctrl + ↑

stateless и stateful сервисы

Stateful системы
Такие системы хранят внутри себя состояние, которое влияет на запросы от пользователя. Примером могут быть сессии пользователей, которые хранятся на сервера. Ответ на запрос пользователя зависит от состояния сессии.

Одна из основных проблем таких систем — горизонтальное масштабирование. Чтобы развернуть несколько экземпляров сервиса нужно как переносить состояния но новые машины и синхронизировать их. Но проблема относительно легко решается за счет внешнего хранилища в котором можно хранить сессии. Система все равно является stateful, но сами веб сервисы стали stateless и теперь можно спокойно их масштабировать.

Stateless системы
Как альтернативу сессиям можно использовать cookie файлы или JWT токены. В таком случае вместе с запросом мы всегда отправляем всю необходимую информацию для его выполнения и аутентификации. В таком случае серверу не нужно хранить информацию о пользователе, достаточно проверить на валидность куки или токен в запросе. Так что stateless система зависит только от данных которые ей были переданы, а не от внутреннего состояния.

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

Более детально расписано тут: stateless/full web service

Kodak ColorPlus 200 pushed to 400 ISO

Выбрался на прогулку, взяв с собой фотоаппарат, зарядил пленку, но ISO не выставил. Cделал 30 кадров и только тогда заметил что сделал я их с ISO 400. Оказывается ColorPlus может пушится, посмотрел на примеры и вот что получилось у меня. Очень хороший результат как для самой дешевой пленки.

Как я делал бота для Facebook workplace

Дали мне задачу: написать бота для мессенджера workplace, с помощью которого можно получать уведомления из нашей CRM и управлять разными вещами. Расскажу о разных интересных вещах с которыми я столкнулся. Бота писал с помощью ASP.NET Core Web API.

Вебхуки

Для того чтобы бот мог обрабатывать запросы и сообщения от Facebook нам надо настроить вебхуки. Webhook — механизм оповещения системы о событиях. Для того чтобы Facebook принял наш хук, он должен обрабатывать как GET так и POST запросы.

Подробнее о Webhook в официальной документации

GET запрос служит для валидации работы нашего эндпоинта. POST принимает данные связанные с активностью пользователя, будь то нажатие на кнопки или другая активность.

Показать код метода-обработчика GET запроса

public IActionResult Receive(
[FromQuery(Name = "hub.mode")] string mode,

    [FromQuery(Name = "hub.challenge")] string challenge,

    [FromQuery(Name = "hub.verify_token")] string verifyToken)
{

   if (string.IsNullOrEmpty(verifyToken)) {

       return Unauthorized();

    }


    if (verifyToken.Equals(FacebookEnvironment.FacebookVToken)) {

        return Ok(challenge);

    }

    return Unauthorized();

}

В качестве verify_token используется токен, который мы указали при регистрации нашего хука.

Показать код метода-обработчика POST запроса

public async Task<IActionResult> Receive([FromBody]FbResponse response = null)
{
    if (response is null) {
        return BadRequest();
    }

    if (response.Object != "page") {
        return Ok();
    }

    foreach (var entry in response.Entries) {
        foreach (var message in entry.Messaging) {
            await PrepareMessageAsync(message);
        }
    }
    return Ok("EVENT_RECEIVED");
}

Авторизация запросов Facebook

Для авторизации Facebook использует специальный http заголовок (X-Hub-Signature), в нем он передает некую сигнатуру с помощью которой мы можем авторизовать запрос. Для того чтобы добавить такую функциональность в наш контроллер, добавим фильтр.

Пример кода, для проверки подписи

private const string Sha1Prefix = "sha1=";

public static bool Validate(string signature, string contentString) {
    if (!signature.StartsWith(Sha1Prefix, StringComparison.OrdinalIgnoreCase)) {
        return false;
    }
    var secret = Encoding.ASCII.GetBytes(FacebookEnvironment.AppSecret);
    var signatureWithoutPrefix = signature.Substring(Sha1Prefix.Length);
    var content = Encoding.ASCII.GetBytes(contentString);
    return GetIsHashValid(secret, signatureWithoutPrefix, content);
}

private static bool GetIsHashValid(byte[] secret, string signature, byte[] content) {
    using var hmac = new HMACSHA1(secret);
    var hash = hmac.ComputeHash(content);
    var hashString = ToHexString(hash);
    return hashString.Equals(signature);
}

private static string ToHexString(IReadOnlyCollection<byte> bytes)
{
    var builder = new StringBuilder(bytes.Count * 2);
    foreach (var b in bytes)
    {
        builder.AppendFormat("{0:x2}", b);
    }

    return builder.ToString();
}

Тестирование бота

Как установить letsencrypt сертификат для IIS. Если же вы используете связку в виде ubuntu и nginx вам подойдет эта инструкция.

Для тестирования нужно развернуть бот на сервере, который смотрит в мир. Также необходимо чтобы у сервера было доменное имя и валидный SSL сертификат. В моем случае, в качестве сервера выступала машина на винде, так как другой внутри нашей сети не было. Как мне показалось захостить приложение написанное на .NET Core намного проще под Ubuntu + nginx нежели под Windows + IIS. В качестве поставщика сертификатов выбрал letsencrypt, так как они предоставляют бесплатный сертификат на 3 месяца, с возможностью дальнейшего обновления.

Эгея Power-Ups

Решил опубликовать несколько своих доработок, которые добавляют в движок новые функции. Вы можете их свободно использовать в любых ваших целях.

Список улучшений

  1. Кнопка «подробнее» или кат внутри заметок
  2. Заметки на полях
  3. Хайлайты
  4. Мини галерея

Кнопка «подробнее» или кат

Когда пишешь статью и у тебя много исходников, удобно их скрыть под кат, чтобы они не увеличивали размер статьи не отвлекали от текста. Для этого добавил поддержку катов внутри заметок. Для этого нужно сделать 2 вещи:

  1. Пометить текст, который будет выступать в качестве кнопки: .cut-button Название кнопки.
  2. Следующим элементов разместить блок div с классом cut-content и в него поместить нужный контент для скрытия.

Как это выглядит в коде:

.cut-button Два лучших вопроса для собеседования
<div class="cut-content">
Как бы вы описали идеального кандидата на эту должность?
Как вы будете судить, хорош ли я в том, что потребуется от меня через 1-3 месяца?
</div>

Как это работает

Два лучших вопроса для собеседования

Как бы вы описали идеального кандидата на эту должность?
Как вы будете судить, хорош ли я в том, что потребуется от меня через 1-3 месяца?

Стилизация в виде карточке

Если необходимо выделить какой-то блок текста в заметке можно использовать хайлайты. Для этого достаточно обернуть текст, который хотите выделить в div с классом highlight.

Как выглядит в коде:

<div class="highlight">
Как бы вы описали идеального кандидата на эту должность?
Как вы будете судить, хорош ли я в том, что потребуется от меня через 1-3 месяца?
</div>

Как работает

Как бы вы описали идеального кандидата на эту должность?
Как вы будете судить, хорош ли я в том, что потребуется от меня через 1-3 месяца?

Заметки на полях

Блог с реализацией заметок: http://mopsicus.ru.

Эту функциональность я подсмотрел в другом блоге и решил перенести в свой. Пригодится, когда нужно указать ссылку на ресурс по теме или просто примечание. Также добавил возможность указывать тип заметки. По умолчанию заметка не занимает отдельный абзац в тексте.

Как выглядит в коде:

.note Блог с реализацией заметок:  ((http://mopsicus.ru/all/aegea-field-notes/ http://mopsicus.ru)).
.note-md Блог с реализацией заметок: ((http://mopsicus.ru/all/aegea-field-notes/ http://mopsicus.ru)).

Как выглядит на мобиле:

Во всю ширину экрана.
Обтекаемый текст.

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

Как выглядит в коде:

<div class="card-gallery card-gallery-4">
    <!-- Список ссылок на изображения -->
</div>

<div class="card-gallery card-gallery-3">
    <!-- Список ссылок на изображения -->
</div>

Как выглядит на страницу

Terrasoft → Epam

Сегодня был мой последний день в Террасофте. Проработал здесь 2,2 года (801 день). Это были забавные времена, было много позитивных вещей и часть негативных. Точно я могу сказать одно, я получил массу полезного опыта, новые знакомства, скиллы. А теперь пришло время идти дальше.

Вопросы на собеседованиях

Совсем недавно я проходил ряд собеседований и разобрался, какие вопросы стоит задать компании. Ведь интервьюируют не только вас, но и вы компанию.

Первыми хочу выделить 2 смелых вопроса:

Как бы вы описали идеального кандидата на эту должность?
Как вы будете судить, хорош ли я в том, что потребуется от меня через 1-3 месяца?

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

Еще вопросы

Как выглядит карьерный рост с этой должности?
Как бы вы описали культуру внутри компании, команды?
Как вы собираете обратную связь от сотрудников, если она будет?

Для тех. специалиста

Что можно улучшить в компании?
Как часто вы делаете релиз?
Насколько легко писать у вас тесты? И есть ли такая практика вообще?
Как у вас организована выкатка нового функционала?

Видео по теме
Почему вы хотите у нас работать? Вопросы на интервью.

Удаления дубликатов строк

Недавно мне попалась интересная задачка по SQL.
У вас есть таблица с 2 колонками: Id, Name. Но на колонках нет никаких ограничений. И получилось так что там если дубли и нам надо их удалить.

Пример таблички

В случае когда у нас нет ни одного уникального значения, мы можем использовать номер строки для идентификации записи для удаления.

; WITH DuplicatesForDelete(Row) AS (
	SELECT ROW_NUMBER() OVER(PARTITION BY t1.Id, t1.Name ORDER BY Id, Name) AS Row 
	FROM TableWithDuplicates t1
)
DELETE FROM DuplicatesForDelete WHERE Row > 1

Статья о том что такое оконные функции (OVER)

Крым на кинопленке Kodak Vision3 250D

В сентябре мне повезло вырваться на несколько дней в солнечный Крым. Очень хотелось поснимать контрастные пейзажи полуострова, и я решил поэкспериментировать с катушкой кинопленки Kodak Vision3 250D.

Проявку делал в лаборатории Фотофонд. Это одно из немногих, если не единственное место, где занимаются проявкой кинопленки в Киеве.

Изначально, я не надеялся получить хорошие фотки, ведь пленку проявляли по процессу С-41 (а не по родному процессу ECN-2).

Но результат меня порадовал! Первое, что удивило — приятная цветовая палитра и мягкий свет. Из минусов: на готовых сканах видны разводы — вероятно, из-за смывки сажи или неисправности проявочной машины, guess we’ll never know🤷🏻‍♂️. Вам решать — оставить эти случайные несовершенства, или убрать их в любом удобном редакторе. Свой выбор я сделал в пользу Фотошопа :)

Раніше Ctrl + ↓