Pull to refresh
4
0,1
Rating
1
Subscribers
Send message

Вообще вопрос проверки ассимптотики в тестах довольно важен и мало освещён. Хотя соглашусь, что пример в статье довольно неудачен.

На эту тему есть интересные тесты в rust-analyzer: раз, два. Они собирают статистику времени исполнения из 5-10 разных размеров для входа. На этой статистике строят регрессии. И если регрессия не выглядит линейной — тест считается упавшим (чуть сложнее, но суть такая).

Edit: хабр съел первый абзац =/

Задача не найти ошибку, а угадать, куда указал анализатор. И анализатор не всегда указывает на место ошибки — вместо этого он указывает на "подозрительное место". Это не одно и то же.

А здесь довольно много разных факторов. Перечислю их безотносительно их критичности.

Для начала встаёт вопрос а что именно шифровать. Шифровать всё затея не лучшая (и непонятно что делать с джоинами). В идеале шифровать только собственно пд. Но тогда проблема в том, что пользователи любят указывать свои пд в условных комментариях или описаниях.

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

Аналогичный вопрос, что с пд происходит до шифрования. Здесь тоже полно мест для утечки.

Ну и сама работа с ключами тоже весёлая. Ключи могут утечь из памяти в своп или кордамп. ВМ могут заснапшотить с памятью — тогда ключи можно достать из снапшота. К счастью, в логи обычно ключи не пишут (хотя бывает =().

Плюс ключи ведь нужно где-то хранить, в отдельном микросервисе например. И этот микросервис тоже нужно бэкапить. В нём тоже нужно как-то реализовывать физическое удаление и всё прочее.

С бэкапами тоже интересно. По-хорошему бэкапы должны быть иммутабельными и храниться где-нибудь отдельно. В частности их могут хранить на каком-нибудь (внешнем) s3 — а как оно там мутируется и удаляется никто не знает. Ну и при мутации бэкапов есть риск сломать его...

Здесь также есть всякая экзотика, что даже перезапись данных нулями не гарантирует их полного удаления. WAL может довольно долго не транкатиться (особенно в условном mssql). Есть всякие CoW фс по типу btrfs, которые при перезаписе создадут копию. А при прямом доступе к диску, бывает можно восстановить часть данных даже после перезаписи. Например всякий page redirect на ssd.

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

**не является юридическим советом, проконсультируйтесь с юристом.

P.S. Я уже не говорю о том что шифрование, а тем более шифрование в бд довольно сложное (легко сделать неправильно). Многие программисты могут просто захардкодить ключ шифрования...

secure_delete это миф. И даже шифрование не всегда спасает. Если вам реально важно удаление пд, то это большая инженерная и аналитическая работа. Никаких волшебных палочек здесь нет.

Разделение моделей "Шаблон" и "Событие": Диапазоны идеальны для сущности Booking (где есть конкретная привязка к календарной дате). Но они плохо подходят для таблицы базового расписания (resource_availability_intervals), которая хранит циклические правила: “каждый понедельник с 09:00 до 13:00”. Хранить расписание в виде tstzrange заставило бы нас заниматься бесконечной генерацией (seeding) явных диапазонов на годы вперед для каждого ресурса, что раздуло бы БД. А скрещивать циклический LocalTime с tstzrange в рамках одного запроса — сомнительное удовольствие.

У Вас все запросы сравнивают колонку в бд с параметрами запроса. Там концептуально джоины по tsrange в бд делать никогда не нужно. А если их и делать, то это будет больно в любом формате хранения =/
Поэтому, кмк, эта причина не очень обоснована.

Вендоронезависимость (Vendor Lock-in): Типы range — это крутая, но чисто «постгресовая» фича. Использование стандартных типов позволяет при необходимости мигрировать b2b-платформу на любой другой диалект (MS SQL, MySQL, Oracle) силами изменения одной строки в конфиге.

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

Чтобы "поменять строку в конфиге" и оно запустилось на другой субд - такое не встречается. Обычно там либо баги всякие странные начинают лезть, либо производительность просаживается. Банально, в том же postgresql и ms sql разные подходы к блокировкам и конкуретности - ms sql может чаще выдавать LOCK_ERROR чем postgresql (и это нужно будет обрабатывать в приложении).

Ну и планировщики у субд сильно разные. Поэтому обычно под разные субд нужно писать разные запросы с разными индексами. Иначе производительность обычно получается довольно скудная.

Поэтому эта причина тоже кмк не обоснована.

И единственная причина, почему можно согласиться - это поддержка в hibernate.

Не уверен, насколько код в репозитории для примера, чем для реального использования.

Подход с midnight splitting конечно интересный, но в Вашей реализации не учитывается возможность брони сквозь полночь. Например, нельзя забронировать слот с 23:00 до 01:00 следующего дня.

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

Теперь к сути происходящего. Делать select for update на целый ресурс — затея несколько проблематичная. Для начала это может вызывать дедлоки (но мб если мы в одном запросе делаем, то там есть консистентный порядок). Во вторых, это убивает конкурентность в корне.

Одним из решений в плане конкурентности это шардирование. Нарезаете всё время доступности ресурса на временные интервалы, например по дням (в UTC). И дальше при бронировании блокируете все интервалы, с которыми у Вас есть пересечения (это может быть несколько дней из-за разных таймзон!). Гранулярность интервалов подбирать можно исходя из двух ограничений: 1) чем короче интервал, тем выше конкурентность 2) но если интервал короче типовой продолжительности слота, то нужно брать слишком много локов.

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

Ну или же можно сторговать latency на throughput и смириться с коллизиями. Самое главное, это заранее определить правила выбора какую бронь из коллизии выбросить. Дальше, единственное что остаётся это удостовериться, что нашу запись не выбросили. Например, можно сделать у бронирования время создания и время "коммита"; при этом сделать ограничение, что интервал между созданием и коммитом должен быть короче T; тогда нам достаточно после коммита подождать время T+eps, если наша бронь всё ещё актуальна — можно выдать подтверждение.

Если говорить о теме статьи, то мне кажется тема собственно блокировок не раскрыта. Почему используется именно for update, а не for no key update? Как будет взаимодействовать создание бронирования с конкурентной правкой расписания? И так далее.

По поводу получения списка слотов. По перфу реализация приемлимая, т.к. на один ресурс не может быть слишком много бронирований (дискретизации нас спасает). А вот принцип перебора не очень работает. В частности, этот метод не может выдать слот 13:45-14:15. Это может быть ок, может нет. По хорошему, нужно бы перебирать просто все "дырки", длиной хотя бы в X.

Можно ли это сделать через индекс, без запроса всех бронирований — тут сходу не скажу.

---

На последок добавлю пару вопросов по бд.

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

К слову об индексах. Индексы подобраны довольно неудачно, т.к. записи плохо шардируются по времени. В идеале любой индекс стоит начинать хотя бы с тенанта. Я бы сделал индекс хотя бы (company, start), а в идеале (company, resource, start). Добавлять end в индекс смысла нет, т.к. запросы носят другой характер.

Здесь кстати в идеале вложить resources внутрь booking просто как массив. Либо json, либо просто массив. Тогда это всё можно в один индекс закинуть.

Также, если оставлять это всё на отдельных start/end, а не интервалах, то стоит запросы перестроить, чтобы там было ограничение и сверху и снизу на start — иначе будет очень много фильтрации при выборке.

И немного о другой теме, по поводу обновления расписания. Увидел реализацию в виде delete all + insert. Это, конечно, работает. Но в проде может вызывать сильную потерю данных из-за какого-нибудь cascade ...

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

P.S. в целом статья мне понравилась, спасибо

Ключи нужно прятать в NDK/JNI (нативный слой)

И как это поможет?

Не говорю уже о том, а зачем их вообще прятать... (там другая модель защиты).

Проверка цифровой подписи

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

И в целом не очень понятна сама претензия: а в какая модель угроз и злоумышленника? Пока что выглядит как типичная история с supply chain. Она же, хоть и в меньшем масштабе, присутствует и в самом андроиде.

P.S. код, конечно, не самый приличный, но тут и у оригинала не всё гладко =/

Другой вопрос, что мы предпочитаем знание "попроще". Правда это "проще" в разных ситуациях разное.

Например, для кого-то "проще" — это когда поменьше параметров и постулатов. В этом смысле модель силы земного притяжения попроще нейронки. А вот если же говорить про силу трейния — тут уже зависит (т.к. нужно как-то найти много разных коэффициентов трения).

В других ситуациях "попроще" — это короче путь от постулатов до практического применения. В этом смысле ллм проще чем условные законы Кирхгофа, т.к. сразу даёт ответ. А законы Кирхгофа проще чем куловские постулаты/уравнения Максвелла.

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

Что будет, если после ввода пинкода наоборот выйти и ввести его ещё раз? Откроется ли то же самое? Если нет, то это не имеет смысла

Edit: ну и в целом отличить пинкод и пинкод наоборот можно через скорость ввода (на отдельном устройстве)

Так это macro_rules, а не derive. Это совершенно не связанные вещи.

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

Просто уже после релиза языка, при практическом опыте использования, пришли к выводу, что систему макросов можно улучшить. Сначала добавили макросы в основной неймрез. А потом предложили макросы 2.0 — но это аж 2016 год, через год после релиза.

Есть ли у Вас ссылки, которые именно что подкрепляют Ваше заявление, что (derive) макросы именно что задумывались как временно решение?

P.S. ну и sunshine/rust-course не является официальным источником, и не похож, как заслуживающий доверия (в таких тонких вопросах)

Что делать, если глубина стека будет больше доступного количества регистров?

Да не то чтобы особенность. Достаточно частый подход, вплоть до nanopass с десятками ir

Edit: ну и с приходом mlir теперь похожая история едет и во всякие clang/mojo/arc и прочее

Вместо хорошего механизма "временно" вставили костыль с этими макросами (это типа хотели сделать временным)

А макросы разве планировались как временное решение? Есть ссылки на это?

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

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

получая ТЗ на новый модуль всегда надо понимать с какими объемами данных он будет работать, какая будет плотность вызовов, какие типичные сценарии использования предполагаются - все это влияет на выбор деталей реализации.

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

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

Ага. Только для бизнеса бесполезный.

Я не уверен, что Вы здесь имеете ввиду под "бизнесом". Но если говорить с точки зрения подбора разработчиков, то хорошие технические навыки (в том числе опыт в олимпиадах) довольно важны и полезны с точки зрения продуктивности (разумеется при условии что они как работники нормальные — по это само собой разумеется)

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

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

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

Разумеется при приёме на работу нужно также смотреть на социальные особенности человека (и вроде как почти во всех внятных местах смотрят)

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

И эти же самые особенности характера часто встречаются у любых технически сильных кандидатов.

Как вы себе представляеете "индекс"

"Инвертированный индекс" — это вполне себе стандартная структура данных для решения подобных задач, тут не вопрос того, как я себе это представляю.

В данном случае это что-то в таком стиле: разбиваем каждый адрес на слова(уже после нормализации), и строим для каждого слова сортированный список клиентов, у которых данное слово входит в адрес.

Дальше, если мы хотим например найти клиентов у которых в адресе встречаются w1 и w2, мы находим соответствующие списки клиентов и пересекаем их — это делается за линейное время от размера результата (по модулю логарифмов). Аналогично для поискаkслов можно объединить списки за,O(M \cdot (\log n_1 + \ldots + \log n_k), гдеMесть размер результата.

Как строить и где хранить этот индекс — это отдельный вопрос. Можно его материализовать в бд (например в виде таблицы (word, client_id)). Можно материализовать в как отдельную структуру на диске. Вообще говоря, можно даже попробовать собрать этот индекс в памяти, прямо во время сверки — там не.

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

Дальше надо написать модуль поддержки этой витрины - [...]

В этом и отличие - на олимпиаде вы решаете отдельную задачу, которая ни к чему не привязана, [...]

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

Но во-первых, про инвертированный индекс я писал несколько в отрыве от истории с олимпиадами.

А во-вторых, не вижу причин, почему олимпиадники должны в среднем (или обязательно) плохо справляться с задачами разработки. Ну кроме истории с ресёрчем, про которую говорили в другой ветке — но она мешает не только олимпиадникам.

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

Или я Вас неправильно понял?

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

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

Причем, в заранее не можете сказать хватит вам простого решения или нет.

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

P.S. кстати говоря, хотя я понимаю, что задача с адресами уже была рассказана с учётом решения, но чисто по описанию и объёмам данных там сразу напрашивается классический инвертированный индекс. Вы, я так понял, пришли к похожему решению, но без слияний по бинпоиску. (к сожалению, не был готов пробираться через терминологию, чтобы понять решение по нормальному)

1
23 ...

Information

Rating
3,529-th
Registered
Activity