Book

Бажок в Bluetooth PAN

Нашёл тут два бажка в венде..

1. Запускаете таск менеджер
2. Включаете в iOS hotspot (на ведроиде вроде называется Bluetooth Tethering)
3. Cпариваете комп с телефоном блютусом
4. Заходите в Control Panel (лигаси), там в Hardware and Sound > Devices and Printers
5. Там телефон будет в 2 экземплярах. На одном из них можно кликнуть правой кнопкой - Connect > Access Point
6. Отключаетесь от вайфая везде, включаете Data в телефоне если было выключено, убеждаетесь что на компе есть соединение через телефон
7. Смотрите в таск менеджере - нового интерфейса нету. Баг 1.
8. Переоткрываете таск менеджер - интерфейс Bluetooth PAN появляется, но на нём нету входящего трафика, только исходящий. Баг 2.
Book

Тайп-фу в TS

У нас тут есть сторонний HTTP-сервис, возвращающий либо { success: true } либо { error: 42, description: "because" }. Ну и по openapi.yaml генерится в таком духе декларация (за правильность кейвордов не ручаюсь):

export interface Foo {
        bar:
            | { success: boolean }
            | { error: number, description: string }
}
Ну и есть такой вот код:


const foo: Foo = getFoo()

if ('error' in foo) {
   throw new Error(foo.description)
}

console.log(foo.success)
Ну и это работает как GADT pattern matching, только без гадтов и паттернов :) То есть внутри ифа нельзя напечатать foo.success - будет ошибка компиляции, а после ифа нельзя доступиться к error или description, поскольку компилятор видит, что мы сделали достаточно рантайм-сравнений для сужения типа foo в разных участках кода до одной ветки (то, что throw обрывает control flow - он тоже видит).

И тут интересно, ввиду того что спецификация кросс-языковая, как с этой ситуацией (типизированная работа с вариантами ответа) предлагает справляться OpenAPI/Swagger кодогенерация для других языков.

Там кстати есть тонкости в схеме, что надо лепить
      additionalProperties: false
      required:
        - success
, иначе мы говорим, что все поля нуллабле и он генерит не то, что мы имеем ввиду.

Ну и это конечно непонятно как на наших гребцов ляжет. Разрешу им везде as unknown as any писать чтобы батька потом чинил :)
Book

нода и openapi

Что бы я хотел:

1. Кодогенерацию HTTP-клиента чтобы можно было писать await client.launchRockets({foo: 42})
2. Типогенерацию чтобы п.1 можно было писать в тайпскрипте и нельзя было ошибиться, написав Foo вместо foo
3. Валидацию (в идеале через ajv standalone и с возможностью семплирования) чтобы, если сервер или клиент вдруг нарушили контракт - это было видно, и не надо было делать ручных рантайм-проверок "ифами"

Пп. 1-2 вроде как есть.

Но вот с п.3 в ноде проблема. Есть например https://www.npmjs.com/package/openapi-request-validator но его надо руками интегрировать с пп. 1-2
Book

Мини-туториал по вебсторму

1. Жмёте 2 раза шифт, набираете scr f ENTER (scratch file), выбираете жс

2. туда пастите это (это риал ворлд экзампл)
class AWSXRay {
  getSegment() {}
}

async function captureWithSegment (annotation, callback) {
 
}

module.exports.handler = async (event) => {
  console.log(event)
  const parentSegment = AWSXray.getSegment()
  return await captureWithSegment('annotation_metadata', async (subSegment) => {
  })
}
3. Курсор на первый async после handler, 2 раза Ctrl-W, Ctrl-Alt-M, вводите captureHandler, Enter

4. Наводите на async последний в captureHandler, 2 раза Ctrl-W и Ctrl-alt-p. Стрелкой вниз выбираете сaptureHandler, энтер. Убираете галку optional parameter, жмёте Enter ещё раз.

Ну и я знаю людей, у которых вот эти операции все в подкорке сидят, на уровне d/fun в виме ("удалить до ближайшего fun"). Oни шлёпают их со скоростью набора, не задумываясь, и говорят, что в результате у них руки перестают отставать от головы, и приходится боттлнек в мозге тренировать, чтобы быстрее думать.

Вот такому вебсторм-фу мне хочется научиться. Ну и вот задача со звёздочкой: представьте теперь что функция принимающая subSegment, использует event (например return await event.foo()). Есть ли маршрут, и если красивого маршрута нет - то какой самый простой вариант?

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

Ну и вопрос залу: а в вашем редакторе как это делается? Например в VSCode же тоже рефакторинги есть. Интересно сравнить юзабилити.
Book

Экономия на консистенси

Навеяно https://jakobz.livejournal.com/271705.html

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

Как это работает? Ну вот раз в Х дней "казино" перечисляет в "банк" Y тысяч дол, пополняя баланс, а дальше дёргает выплаты параллельно запросами к разным узлам кластера.

Ну и вот вопрос: как понять когда у "казино" в "банке" закончился баланс?

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

Это классный способ, всё кристально чисто и сходится до копейки. Но это нахуй никому не надо! Это не нужно техникам "банка", потому что сериализация -- это такой последовательный боттлнек.

Но сюрприз, это не нужно не только техникам, это бизнесу тоже не нужно. Ни "банку" ни "казино". Поскольку они скреплены договорными обязательствами и никуда не убегут (ака eventual consistency).

Вот решение без боттлнека:

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

Что в этом случае в худшем случае может произойти? Банк может попасть на бабки в размере часового оборота казино. Но реально он не попадёт, поскольку это всё регулируется бизнес-процессами и контрактами. Например, казино обязуется не превышать порог часового оборота. Но этот порого обычно и так есть, для нужд capacity planning, например. И/или оставлять небольшой депозит. В этом случае если баланс меньше порогового, транзакции останавливаются "банком". Как это реально происходит? Процесс рассчёта баланса стартовал в 13:00, а транзакции "увидели" новое значение баланса скажем в 13:02. И у нас получается даже не на час минуса, а на 2 минуты. Что совершенно смешная цифра как для банка так и для казино.
Book

Всё, что вам нужно знать про noSQL

http://pages.cs.wisc.edu/~jhe/eurosys17-he.pdf

Neither RocksDB, which is optimized for SSDs, nor LevelDB is able to saturate device resources. Figure 3b shows that RocksDB is only able to use a few more NCQ slots than LevelDB, despite RocksDB’s use of multi-threaded compaction to increase SSD parallelism

Ну то есть БД не в состоянии загрузить современный диск. Я как-то писал давно - а как это так, что в бенчах noSQL они никогда не сравнивают их IOPS с тем, что показывает iometer и аналоги? А вот оно, там совершенное позорище, они на однотредовые диски (и однотредовых клиентов) рассчитаны все.

Так что если вы вдруг найдёте непозорный noSQL, который выжимает из SSD его паспортный IOPS, пишите :)