• Сервис не смог

    Иные сервисы уведомляют о всякой ерунде — новом дизайне, посте в блоге или просто какой-то дичи — и забывают о важных вещах. Например, проблемах с платежами и авторизацией. Вот три примера из практики.

    До известных событий (которые в России нельзя назвать коротким словом) сервис Gumroad регулярно переводил деньги за книгу на Paypal. Как только Палка отвалилась, пропали и выплаты. Однако Gumroad не прислал ни одного письма об этом.

    Как программист я понимаю: вызов к PayPal обернут в try/catch, ошибка падает в лог. Ладно, а что потом? Получили сотни ошибок, кто будет с ними разбираться?

    По-хорошему надо так: делать задачу на выплату, повторять ее с интервалом в час, день, неделю. Если не вышло — слать пользователю письмо, а не молчать, словно ничего не происходит.

    То же самое с Leanpub. У меня там короткая книжка на английском, и раз-два в месяц ее покупают. Выплаты прекратились, все молчком, никаких уведомлений. Неужели так трудно отправить письмо?

    Наконец, Амазон. Какое-то время назад я жаловался, что не могу зайти в аккаунт. Думал, что блокирует Амазон, но все оказалось проще. Когда-то давно, подключая двухфакторную авторизацию, я поленился открыть Google Authenticator и выбрал вариант с смс — зря!

    Оказалось, сервис, который отправляет смс, теперь не делает этого для российских номеров. Без понятния, как это происходит: возвращает ли он статус 403? Или отдает 200, чтобы молча выкинуть мое смс? И кто виноват? Я, потому что живу в России? Амазон, потому что сервис не работает, а к нему обращаются? Сервис, потому что не смог?

    Кто кого должен уведомлять? Амазон меня, потому что дело происходит на странице Амазона? Или смс-сервис уведомляет Амазон, потому что первый не смог? Все сломано: смс не доходит, Амазон об этом не знает, сервис не считает нужным доложить. Скорей всего, записали в лог и забыли.

    Как вы поняли, так быть не должно. Клиенту все равно, какие сервисы вызывает ваш сервис. Чей домен открыт в браузере, тот и уведомляет. Во всех случаях письма должны были прислать Gumroad, Leanpub и Amazon — то, что я вижу и с чем работаю. Не нужно переводить стрелки на сторонний сервис, который не смог. В данном случае не смогли упомянутые фирмы.

    Все это я переживу, а вот взять на заметку стоит.

  • Use format rather than str

    I’d like to share a Clojure trick I’ve been using for years. It’s simple, it makes your code safer; I always highlight it when making reviews. The trick is: don’t use the str function to concatenate strings. Instead, use format. A couple of examples:

    (let [username "Ivan"]
      (str "The user `" username "` has been created."))
    ;; "The user `Ivan` has been created."
    
    
    (let [user-id 5234]
      (str "/files/uploads/" user-id))
    ;; "/files/uploads/5234"
    

    The first point in favour of this approach is, str turns nil into an empty string. Thus, when printing the final message, that’s unclear if a variable was an empty string or nil:

    (let [username nil]
      (str "The user `" username "` has been created."))
    ;; "The user `` has been created."
    

    The difference between these two is important. Say, an empty string means broken validation; a title of a book, a name of a person must not be blank. But if I got nil, most likey I missed the key in a map because of a namespace:

    (def user
      {:acme.user/id 5234
       :acme.user/name "Ivan"})
    
    (let [username (get user :id)]
      ...)
    

    or the keyword/string case:

    (def user
      (parse-json "user.json"))
    ;; {"id" 5234 "name" "Ivan"}
    
    (let [username (get user :name)]
      ...)
    

    Now compare it to the format function. The nil value becomes "null" when passed to format:

    (let [username nil]
      (format "The user `%s` has been created." username))
    ;; "The user `null` has been created."
    
    (let [user-id nil]
      (format "/files/uploads/%s" user-id))
    ;; "/files/uploads/null"
    

    If I had my way, I would produce not "null" but "nil" string from nil, but that’s not so important.

    The second point is much more serious. Nil values are extremely dangerous when building file paths or URLs. Imagine you’re about to delete files of a person who’s terminating their account. Most likely you store files on disk like this:

    files/<user-id>/avatars/...
    files/<user-id>/attachments/...
    files/<user-id>/uploads/...
    

    Then you have a function that accepts the user-id parameter, then builds the right path and does recursive deletion:

    (defn drop-user-files [user-id]
      (let [path
            (str "files/" user-id)]
        (rm-rf-recur path)))
    

    If you pass nil for user-id, the path will be "files/". Running that code will erase all the files of all users which would be a disaster. But if you have used format, the path would have been "files/null", which would just have thrown an exception saying there is no such a directory.

    One may say: add an assert clause for user-id right before you build a path. Like this:

    (defn drop-user-files [user-id]
      (assert user-id "User-id is empty!")
      ...)
    
    ;; or
    
    (defn drop-user-files [user-id]
      {:pre [user-id]}
      ...)
    

    In practice, you easily forget doing this and recall when the data is lost. I don’t see any reason for skipping that minor fix — change str to format — to reduce chances of a disaster.

    The same applies to S3 URLs. Although it’s a web-service, we all treat it as a file system. Composing S3 URLs reminds me of ordinary file paths. Again, if you’re about to drop user’s directory with uploads, be aware of the the same thing: str + nil for user-id produce a broken path:

    (defn drop-s3-user-files [s3-client user-id]
      (let [path
            (str "files/" user-id)]
        (s3.client/delete-files s3-client path)))
    

    If you pass nil into a function that recursively drops S3 files, the data is all gone.

    Of course, such an issue can be held with special Java classes like Path or URI. But in fact, in Clojure we use them quite rarely. Most often we just concatenate plain strings as it’s enough for the task. It’s simpler and takes less code.

    I recommend using str for one purpose only — to coerce a non-string value to a string. For example:

    (str 5) ;; => "5"
    (str (random-uuid)) ;; => "154ac...b2642"
    

    Briefly, it’s safe when the str function accepts strictly one argument. When there are more than one, I feel worried.

    I always keep in mind a real story about a guy who owned a small hosting company. He released the rm -rf $FOO/$BAR command among the whole park. Too sad for him, both of the env vars were unset, nor special bash flags terminating a script were set as well. The command turned into rm -rf / with known consequences. A couple of missing vars has ruined one’s business. By str-ing strings, especially when building file paths, you may easily mess up the same way (but I wish you won’t).

    Let’s recap:

    • str turns nil into an empty string;
    • by reading such a message, you never know if a value was an empty string or nil;
    • the difference between these two does matter;
    • with that behaviour, it’s easy to build a weird file/S3 path and lost the data;
    • instead, format turns nil into "null". This is much better than emptiness and solves the troubles mentioned above;
    • use str only to coerce a value to a string.

    Safe coding!

  • Книга на Доброфайле

    Сервис Gumroad, где продается электронная версия книги, ожидаемо перестал работать с российскими картами (а также остановил выплаты). Поэтому выкладываю книжку на российской площадке “Доброфайл”:

    https://dobrofile.ru/?s=c2f86cd04

    Все просто: переходите по ссылке, жмете “купить файл”. Никакой авторизации: ввели емейл и оплатили картой. На почту падает ссылка, которая действует 48 часов. Только что купил сам — работает.

    Сервис довольно забавный: простой как лопата, весь такой спартанский. После тормозного, обвешанного скриптами Gumroad воспринимается как глоток воздуха. Админка товара открывается секунду — так можно было?

    В общем, покупайте книжку на Доброфайле. В ближайшее время обновлю страницу проекта, публикацию на Хабре и другие места.

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

    А еще я почти закончил черновик второй части, но об этом в следующий раз.

  • Правила пользования почтой

    Начинающие программисты спрашивают, какую технологию учить: Питон, Джаву и прочее. Отвечая на эти вопросы, часто забываешь об электронной почте. Закрываю упущение: учитесь электронной почте! Это не так просто: вокруг почты сложился особый этикет, о котором не расскажут в онлайн-курсах. Вы должны знать его перед тем, как начнете искать работу.

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

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

    В отправителе не должно быть ников вроде “nagibator666” или LenuSiK. Плохо, когда имя сгенерировано по шаблону “фамилия.годрождения”, например semenova.81@mail.ru. В отправителе должны быть имя и фамилия, желательно на том языке, на котором говорит получатель, скажем, Ivan Grishaev. Имя не должно быть двояким: вместо Alex пишите Alexey или Alexander.

    Самое важное правило: при ответе не цитируйте все письмо. Прямо сейчас, не читая этот текст до конца, откройте почтовый клиент и поставьте нужную настройку. На маке это последний чекбокс на закладке Composing. Называется он странно, но работает как надо: при ответе будет процитирован только выделенный текст, а если не выделено ничего, то ответ будет по умолчанию пустым.

    Не помню, как сделать то же самое в Gmail, но там у меня выработалась привычка: после нажатия кнопки Reply я автоматом выполнял Ctrl-A Delete, чтобы стереть все из поля ввода.

    Цитирование письма уходит корнями в прошлое. Раньше почтовые сервера не умели строить цепочки писем. Каждое письмо считалось отдельным. Чтобы был ясен контекст, старое письмо добавлялось цитатой к новому. Это в высшей степени избыточно и неэффективно. Позже письма научились сопоставлять по теме и префиксам Re, что тоже уродливо. И лишь затем придумали машинные заголовки с идентификаторами, где указано, на что отвечает это письмо.

    Беду с цитированием знает каждый, кто работал в больших фирмах. В обсуждении по почте борода старых писем растет как снежный ком, и каждый клиент работает с ними по своим правилам: отступами, тильдами или вертикальными чертами. Рано или поздно в тред отвечает красноглазик с консольным клиентом на Perl, где борода цитат выделена какими-нибудь >>>. В результате все видят пять экранов мусора с текстом недельной давности. Не недо так.

    Заполняйте письмо снизу вверх. Как это понимать? Обычно мы указываем получателя, тему, пишем текст и прикладываем файл. Из всех этих полей обязательно только первое — получатель. Как только он заполнен, легко отправить письмо неверным нажатием или комбинацией клавиш. За подобное письмо стыдно, оно вносит непонимание, приходится в спешке отправлять другое. Этого легко избежать методом “снизу вверх”.

    Если вы отправляете файл, сначала приложите файл. Затем напишите текст. Введите тему. И только потом — отправителя. С таким подходом невозможно отправить письмо, пока оно не заполнено.

    Что делать, если вы забыли приложить файл? Обычно его отправляют вдогонку со словами “забыл файлик, вот он”. Не делайте так, потому что на стороне получателя файл будет оторван от основного письма. Как его потом найти? Письмо с текстом человек найдет по ключевым словам, но как быть с файлом? Правильно сделать так: отправить повторное письмо с файлом и написать, что прошлое письмо без файла ушло по ошибке и его надо удалить. В этом случае все останутся довольны.

    Ближайшая аналогия: вы отправили исходный код, и затем пишете: ой, не хватает одного файлика. Положите его в папку foobar/lulz, и все заработает. Это непрофессионально. Вы либо сдаете работу, либо нет. Письмо без файла, когда он должен там быть — испорченное письмо. Вместо попыток его исправить отправьте новое, на этот раз правильное.

    Еще о файлах. Если вы отправляете документы для просмотра, используйте PDF. Не ждите, что у собеседника установлен Word, Excel или Powerpoint — эти программы платные и открываются в сто раз медленней, чем PDF. Исключение возможно, когда вы оба работаете в этих программах.

    Архивируйте файлы только в случаях, когда важна структура папок. Например, исходный код проекта. Распаковав архив, собеседник получит систему папок, готовую для сборки. Сжимать текстовые документы не нужно — это повышает энтропию и требует кликов. Не жмите изображения и другие бинарные файлы — экономия будет не более пяти процентов.

    Если архиватор, то только zip. Своими rar, tar.gz и прочими платформо-зависимыми штучками вы огорчите получателя.

    Файлы больше 10 Мб выносите в облачные хранилища. Желательно такие, что отдают файл по прямой ссылке, например S3. Если ссылка ведет на веб-страницу, где нужно доказать, что ты не робот, это грусть и печаль. По той же причине не пользуйтесь хостингом изображений — там показывают рекламу, открывают дичь в новых вкладках, словом, сплошное издевательство.

    О композиции. Письмо начинается с обращения, затем с новой строки следует текст. Он состоит из предложений, каждое заканчивается точкой или знаками вопроса или восклицания. Три-пять предложений составляют абзац, которые отделяют пустой строкой. Абзацы обязательны, чтобы дать человеку передохнуть. Письмо заканчивается подписью без точки.

    Подпись должна быть короткой, в идеале только имя. В крайнем случае — должность и минимальные контакты: телефон и ник в мессаджерах. Писать туда домашний телефон, номер ICQ и прочую дрянь не нужно. В подписи не должно быть логотипов и ссылок.

    Если это вручную написанное письмо, а не рекламная рассылка, его тип должен быть plain text (без форматирования). Никаких болдов, италиков и прочих офисных штучек, ведь текст — уже мощный инструмент. Поток сознания нужно разбить на абзацы или пункты, важные вещи прописать отдельно. В крайнем случае поставить восклицательный знак или выделить звездочками.

    На одно письмо приходится одна мысль. Нет ничего хуже письма, где просят собрать информацию по пяти пунктам. Очевидно, составить ответ на это письмо стоит всего дня, а то и недели. Если вы отправитель, пошлите пять писем, и желательно с паузами. Если вы получатель, ответьте на первый пункт с просьбой написать вам отдельные письма по остальным вопросам. Конечно, не в грубой манере “перепиши, пес”, а с пояснением, что так вам будет легче ответить.

    Как видите, правил вышло прилично. Никто не ждет исполнения их всех, но применять их однозначно стоит. Остановитесь на чем-нибудь простом, например не цитировать все письмо в ответе, а затем каждый месяц вводите новую практику. Через несколько лет вы сами будете учить новичков почтовому этикету.

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

  • Черно-белый режим

    Иногда встречаю в интернете статьи о том, как уменьшить вред от гаджетов для глаз. Пишут обычные вещи: уменьшить яркость, включить ночной режим (меньше синего и больше желтого) и в том числе — черно-белый режим, когда цвета меняются на градации серого. Типа, меньше нагрузка на сетчатку и все такое.

    Опровергаю: включать черно-белый режим не нужно. Несколько лет назад я проводил эксперимент — включил на ноуте и телефоне такой режим. В MacOS это делается галкой в меню Settings / Accessibility / Display / Color Filters, на айфоне — схожим образом.

    Интерфейс выглядел так:

    Почему этого делать не нужно? Ответ — при выключенном цвете нагрузка на глаза, как ни странно, больше. Объяснение этому простое: на сетчатке находятся разные рецепторы, в том числе палочки и колбочки. У них разные функции: первые отвечают за свет, вторые за цвет. Это ортогональные вещи: например, кошки отлично видят в темноте, но хуже нас различают цвета.

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

    Восприимчивость к цвету крайне важна. У нас, людей, этот навык крайне развит по сравнению с животными. Кто сорвал красный плод, тот выжил, а кому достался зеленый — увы. Мозг получает колоссальную информацию из цвета, и добровольно лишать себя этого по крайней мере странно.

    Возвращаясь к первоначальному вопросу — как защитить глаза от гаджетов в вечернее и ночное время? Очень просто — не пользоваться гаджетами. Ночной там режим или нет, желтый фон, пониженное мерцания — все это ерунда. Экран — это тысяча мелких фонариков, которые светят вам в глаза. Регулируйте гаджет как угодно, сути это не меняет: вы смотрите на источник света, пусть и рассеянный. При любых настройках он будет вреден в вечернее время.

    Наоборот, книга и вообще бумага не светятся. Она только отражает свет лампы, но это свет другого рода. Будучи отраженным от бумаги, он не вредит вам.

    Это не значит, что я не туплю в экран вечером. Увы, порой случается. Однако понимаю грань допустимого и не обманываю себя режимами. Лучший режим гаджета перед сном — ВЫКЛ.

  • Вертикальный режим

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

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

    Мелкие плюсы разбиваются о суровую реальность. Ради интереса пошарьте экран кому-либо в вертикальном режиме — вас станут ненавидеть. Потому что собеседник увидит следующее:

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

    Возразят: шарь не весь экран, а только окно. Так даже лучше, потому что собеседник не увидит вкладки браузера, переписку с женой и прочее. Я тоже шарю только Емакс. Но иногда работа идет сразу в редакторе, терминале и браузере, и тут никуда не денешься. Пошарил, и начинается долгая песня с увеличением шрифтов, зумов и прочего.

    Словом, хороший эксперимент, но нет.

  • Не смотрю и не слушаю

    Не помню, говорил или нет: я не слушаю подкасты, не смотрю познавательные видео, сериалы, интервью Дудя, выступления Шульман и всех остальных. В Телеграме состою только в профильных чатах (программирование, кложа, джава). В RSS-читалке почти ничего не осталось — отписываюсь. Уж если начал признаваться, то вот еще — почти ничего не смотрел из Рича Хикки.

    Это не потому, что я такой продуктивный и эффективный. Когда работа надоедает, я как и все туплю в интернет — читаю популярные ресурсы, Википедию, смотрю Ютуб, словом — трачу время, которое мог бы использовать на что-то созидательное.

    Для себя я понял, что подкасты, познавательные видео и прочий контент, который считают полезным, для меня вовсе не полезен. После просмотра видео или подкаста я не могу ничего вспомнить. Ощущение, что вода уходит сквозь пальцы: сидел час за компом, а как встал, так словно и не было этого часа.

    Недавно я смотрел выступление Максима Ильяхова. Он выступил прекрасно: манера речи, мимика, интонации, все это так живо и смешно. Но что он говорил — я не смог вспомнить уже через 15 минут. Это не Максим плохо выступил, это я такой. Поэтому отдаю отчет — тот просмотр был развлечением, попыткой увильнуть от дела.

    С годами мне все более очевиден факт — запоминаешь только то, что мысленно пересказываешь и пробуешь на практике. Третьего не дано: никакие видео, короткие или длинные, никакие подкасты не продвинут вас так далеко, как пересказ и практика. Конечно, и от подкастов есть польза, но если выбирать средство с малой пользой и большой, то есть же разница, верно?

    В моем понятии видео прочно связано с развлечением. Когда я вижу браузер и Ютуб, ни о каком обучении не может быть и речи. Так я воспитан: раньше вся информация была в виде текста (книги, учебники). Возможно, у молодежи дела обстоят по-другому, но как отец я знаю: ребенок, севший за комп “посмотреть лекцию по географии”, быстро переключается на мемы про Майнкрафт.

    Испытываю схожий скепсис к популярным нынче курсам программирования и онлайн-платформам. Они нужны, но важно понимать: это вершина айсберга. Когда меня спрашивают, как изучить Кложу, я отвечаю одинаково — любой ценой устроиться в проект на ней. В этом случае курсы служат входным билетом, доказательством, что по крайней мере ты не идиот. Что будет дальше — никто не знает.

    Эти убеждения долго зрели в моей голове, пока я не прочел “Думай как математик” Барбары Уокли. Книга затянута, можно было бы выкинуть треть, но ради некоторых мест стоит потерпеть. Барбара и ее коллеги высказывают мысль — чтобы что-то запомнить, нужно прочесть материал и многократно его пересказывать. Если что-то забыли, то ни в коем случае не читать, а потратить минимум пять минут на вспоминание. Это важнейший процесс мозга, который нельзя прерывать. Даже если вы не вспомнили материал, уже сам процесс выстраивает нужные связи, и при следующем чтении материал запомнится лучше. И конечно, любые знания нужно закреплять практикой.

    Теперь скажите мне, как вы смотрите подкасты? Вы их потом вспоминаете, пересказываете, да? Прослушав подкаст о Кложе, бросаетесь писать на ней? Ведь нет же. Ничего не закрепляется. Все это развлечение. Я не ставлю это в вину, пусть каждый развлекается как хочет, но не обманывайте себя, будто чему-то учитесь. Это то же самое, что миф о 25 кадре или обучении во сне с плеером.

    Вспоминаю, как в молодости увлекался 3D-моделированием. Интернет был никакой, поэтому заказывал по почте видеоуроки. Со временем понял, что смотрю их как футбол: другой человек работает, а ты бездумно смотришь с бутербродом в руке. Когда пытался повторить один из уроков — слепить простенького динозавра — обалдел от того, что ничего не могу. Что, помогли многочасовые просмотры уроков?

    Лучшим источником знаний, на мой взгляд, остается текст. Полезней него ничего не придумали. К тексту удобно возвращаться, его удобно читать, пересказывать. С текстом удобно работать — редактировать, составлять выжимки и конспект, ужимать, насыщать примерами. Работа с текстом — крутейший навык, с которым каждый попрет по карьерной лестнице как локомотив.

    Чтобы поделиться знаниями о Кложе, я специально выбрал книжный формат. Можно было настругать коротких видео, записать курсы или что-то похожее, но это все не то. Книга материальна и принадлежит только вам. Ее не потеряешь из-за истекшей кредитки или санкций. Когда читаешь книгу, работает другой отдел мозга, не связанный с туплением в комп. Лучше книги ничего быть не может.

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

    Наконец, меньше всего я хочу быть тем, кто пересказывает интернет. С отдельными людьми я почти не разговариваю, потому что знаю — все их мысли заимствованы из Ютуба и Телеграма. В этом легко убедиться: уже на второй реплике тебе кидают ссылку с “пруфом” — безусловно правдивой информацией, которую человек только что пересказал.

    Не делайте так. Доверять можно только опыту, но не авторитетам из интервью, подкастов и образовательных курсов. Все это развлечение, что отнюдь не плохо, но — развлечение, выдаваемое за образование есть обман.

  • Страсть к делу

    Эта мысль тоже не понравится никому.

    Часто встречаю комментарии в духе: сейчас такой стресс, целый день читаю новости, не могу работать. Как можно работать в такое время!

    Тот, кто это пишет, недостаточно любит свое дело. Да, обстрелы. Да, новостная лавина. Но уверяю, когда страстно что-то любишь, никакие новости не оторвут более чем на час.

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

    Пожалуйста, не путайте: одно дело, когда в городе взрывы, и речь идет о выживании. Тут я целиком на стороне терпящих бедствие. Но когда русский программист сидит в кресле Икеи за макбуком, в правой руке у него свежий кофе, а в левой яблоко и шоколадка, и, видете ли, он не может работать из-за потока новостей — это полный фейспалм.

    Уже сто раз описаны способы, как избавиться от новостной аддикции. Расширения для браузера, удаление телеграмов-ватсаппов с десктопа. Принцип “только с мобильника”, когда мобильник кладут на подоконник, и надо оторвать зад, чтобы до него дойти.

    Словом, не объясняйте слабую работоспособность “таким временем”. “Такое время” будет всегда: не ковид, так война, не война, так еще что.

    Если страсть побеждают внешние факторы, значит мало страсти. Если мало страсти, ее нужно найти.

  • Граждане выгорающие

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

    Как я выгорел и пережил это. Как я выгорел и пошел в автослесари. Как не выгореть тимлиду. Курсы для выгоревших. Исповедь выгоревшего менеджера.

    Сколько вас, нечисти, развелось.

    Так вот — повестка ушла, выгорание больше не модно. Сейчас что ни день, то новые потрясения, и очередного выгоревшего не поймут. Люди умирают, переезжают, теряют работу, а ты выгораешь. Серьезно?

    Стоит миру перевернуться, как уходит всякое выгорание. Из чего следует печальный факт. Массовое выгорание прошлых лет — пошлое ковыряние в себе на фоне скуки. Подобно организму, который в стерильных условиях борется с собой, человек в комфортных условиях ищет страдания.

    Все это было фарсом, позерством, пафосом.

    Повестка ушла, а задача ничуть не изменилась: все так же профессионально делать свое дело.

    За работу.

  • Возня с файлами

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

    Если коротко, с помощью крона я бекаплю файловый архив. До недавнего времени пользовался S3, но из-за последних событий вынужден переезжать. Ниже — мои изыскания на тему хранения файлов.

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

    Кроме фоток, крайне важны сканы документов. Паспорт, загран, снилс, ИНН и так далее. Все то же самое для жены и троих детей, плюс свидетельства о рождении. Полноценный скан документа (именно скан, а не фотка) неистово полезен. Распечатать его на принтере занимает минуту, а поход в ближайший копицентр — двадцать минут. Когда после рождения третьей дочки бегал по инстанциям, идею со сканами я просто боготворил: в каждую дверь нужно сдать пачку копий, а таких дверей десятки.

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

    До недавнего времени вопрос не стоял остро: бери любое облачное хранилище и вперед: дропбокс, яндекс-драйв, гугло-драйв, айклауд. Но даже до “спецоперации” и отвала русских пользователей ни один из этих сервисов мне не подошел. Все они намертво завязаны на конкретный бренд и любят выкручивать мозг. О деградации того же дропбокса я писал неоднократно (раз, два), и аналоги ничуть не лучше.

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

    Я попробовал AWS S3, и неожиданно понравилось: все происходит молча, разве что в раз в месяц получаю счет. Настроить просто: ставим питонячий AWS CLI. Далее прописываем креды и настройки в файлах:

    # ~/.aws/config
    
    [default]
    region = us-east-1
    output = json
    
    # ~/.aws/credentials
    
    [default]
    aws_access_key_id = ...
    aws_secret_access_key = ...
    

    Если теперь выполнить команду s3 sync:

    aws s3 sync my-bucket s3://my-bucket --delete
    

    , то произойдет синхронизация файлов из первого источника (папки) во второй (бакет). Флаг --delete означает, что файлы, которых нет в источнике, будут удалены в удаленном хранилище. Другими словами, если удалили локальный файл, то при синхронизации он будет удален и в S3. Без флага происходит простое слияние файлов.

    Вот как оформить все это дело в кронтаб:

    BUCKET=my-bucket
    
    0 */3 * * * cd /Users/ivan/s3 && aws s3 sync ${BUCKET} s3://${BUCKET} --exclude '*.DS_Store' --delete && echo OK
    

    Для удобства я назвал локальную папку так же, что и бакет, чтобы ссылаться на переменную.

    Вопрос в том, насколько часто запускать синхронизацию. Раньше я делал это каждые три часа (0 */3 ...), но со временем понял, что это слишком часто. На практике хватает двух раз в день: в обед и вечером (0 12,22 ...).

    О результатах синхронизации я узнаю по письму следующего содержания:

    Subject: Cron <ivan@ivan> cd /Users/ivan/s3 && aws s3 sync ...
    
    Completed 60.5 KiB/~60.5 KiB (34.3 KiB/s) with ~1 file(s) remaining (calculating...)
    upload: my-bucket/docs/text/links.md to s3://my-bucket/docs/text/links.md
    Completed 60.5 KiB/~60.5 KiB (34.3 KiB/s) with ~0 file(s) remaining (calculating...)
    
    OK
    

    Про деньги: хранение 130 гигабайт с синхронизацией каждые 3 часа стоит 4.6 доллара в месяц. Это дешевле дропбокса и и аналогов с интерфейсом. Важное преимущество в том, что платишь в точности за те ресурсы, что потребляешь. Никаких обрыдлых подписок.

    С началом “не-войны” Амазон начал вести себя странно. Файлы по-прежнему доступны, но теперь я не могу войти в консоль управления. Амазон требует ввести код, отправленный на телефон, но сообщения не приходят. Не работают и другие способы его получить, например голосовым звонком робота. Запросил восстановление двухфакторной авторизации, но что-то Амазон не спешит.

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

    Приятная вещь: S3 уже давно не монополист в области хранения файлов, и многие фирмы выкатили свои решения. Которые, кстати, работают по протоколу S3. Файловые хранилища предлагают DigitalOcean, Exoscale, Яндекс.Облако. Будучи в Exoscale, я, хоть и немного, но работал над хранилищем.

    Миграция сводится к тому, чтобы перенацелить клиент AWS на другой сервис. По понятным причинам выбрал Яндекс — западные партнеры сейчас не подходят. Регистрируемся на cloud.yandex.ru, переходим в Object Storage. Создаем бакет. Советую холодный тип хранения, потому что читать файлы вы будете редко, а синхронизация работает по методу HEAD — через метаданные.

    Когда бакет создан, понадобится пара открытый-закрытый ключ. Как слепой щенок, долго я мыкался по интерфейсу, пока не нашел “сервисные аккаунты”. Создайте новую пару и сохраните ключи. Добавьте в настройки клиента AWS секции:

    # ~/.aws/config
    
    [ya]
    region = ru-central1
    output = json
    
    # ~/.aws/credentials
    
    [ya]
    aws_access_key_id = ...
    aws_secret_access_key = ...
    

    Теперь выполните:

    aws --profile ya --endpoint-url=https://storage.yandexcloud.net s3 sync ...
    

    , и файлы польются в Яндекс. К сожалению, в настройких нельзя задать свой endpoint-url, поэтому приходится таскать его за собой в командной строке. Народные умельцы сделали плагин, который это фиксит, но я не проверял.

    Как закончится синхронизация, удалите старые файлы из Амазона:

    aws s3 rm s3://my-bucket --recursive
    

    Поздравляю, вы переехали. Осталось только исправить crontab, чтобы синхронизация стала регулярной.

    У питонячьего AWS-клиента есть недочет: при синхронизации он оставляет на сервере пустые папки. Предположим, вы удалили папку “photos”, и AWS CLI честно выполнит DELETE для каждого файла:

    DELETE photos/IMG_001.jpeg
    DELETE photos/IMG_002.jpeg
    DELETE photos/IMG_003.jpeg
    ...
    

    Что касается пути “photos/”, то он благополучно останется на сервере. Ясное дело, что со временем накопится масса таких пустышек, и скачав файлы с S3, вы обнаружите папки, удаленные давным давно. На эту тему пять лет назад создан issue, в котором отметился и ваш покорный слуга. Каждый месяц я получаю письма с комментариями +1 и пальчиком кверху, но исправлять его никто не спешит.

    Впрочем, удалить пустые папки можно командой

    find . -type d -empty -delete
    

    , что не такая уж и проблема.

    Согласно калькулятору Яндекса, хранение 150 гигов обойдется в 215 рублей в месяц, что, прямо скажем, по-божески. По текущему курсу это два доллара, дешевле даже представить нельзя.

    Во время изысканий я в том числе пробовал программу SyncThing. Кто не знает, это программа для анонимной синхронизации файлов. Никаких регистраций: поставил у себя и на удаленной машине, обменялся QR-кодами, и процесс пошел. Работает как часы. Висит в трее, настройки через браузер на локальном хосте.

    На мой взгляд, SyncThing подходит в тех случаях, когда файлы постоянно меняются, и изменений ждут на обоих концах. Например, обмен документами между группой лиц или торрент-трекер, ожидающий файлы в нужной папке. Перекинуть файл с макбука на игровой комп — тот еще челендж, если настраивать сеть по правилам. А со SyncThing работает прекрасно. Словом, замена старому доброму Дропбоксу.

    А вот делать бекапы через SyncThing как-то не зашло. Для этого нужно поднимать VPS и ставить там SyncThing. Виртуалки с большим диском нынче от 700 рублей в месяц. Не катастрофа, но выбор между 200 и 700 рублями в месяц очевиден. Да и заморачиваться не охота.

    В общем, вот как я синхронизирую файлы. Слово читателям: расскажите, как делаете это вы.

    UPD: продолжение.

Страница 18 из 74