Заметки о программировании, путешествиях, плёнке и разных интересностях
Обо мне  •  Список заметок  •  Плёнка

Позднее Ctrl + ↑

stateless и stateful сервисы

Пример stateful системы
Например наша система хранит в себе сессии пользователей, тем самым ответ на запрос пользователя зависит от состояния (сессии). При масштабировании сервиса, нам прийдется переносить все сессии на новый инстанс. Система стает сложной и не маневренной. Любой stateful сервис можно превратить в stateless, вынеся состояние в отдельный сервис и БД. Так мы можем вынести сессии во внешнее хранилище, сама система осталась stateful, но сам веб сервис stateless, тем самым мы можем просто его реплицировать.

Пример stateless системы
Давайте вместо сессий использовать cookie файлы, таким образом мы передаем серверу не только сам запрос, но и всю необходимую информацию для его выполнения. Серверу больше не надо хранить в себе состояние. Stateless система зависит только от данных которые ей были переданы, а не от внутреннего состояния.

Еще один пример
У нас есть интернет магазин — пока корзина пользователя хранится в памяти сервера, то это stateful. И у нас сразу возникают проблемы с масштабированием. Но когда мы выносим хранения корзины во внешний session storage — наш сервис становится stateless и мы можем спокойно его масштабировать, так как состояние хранится у нас в отдельном хранилище.

Очень советую почитать статью на RSND по данной теме.

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 месяца?

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

Еще вопросы

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

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

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

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

 Нет комментариев    134   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 + ↓