Может кому полезно будет: https://github.com/orval-labs/orval
Либа из openapi спеки генерит вам tanstack квери и мутации. Сам не пользовал, но выглядит интересно.
Либа из openapi спеки генерит вам tanstack квери и мутации. Сам не пользовал, но выглядит интересно.
🔥6
Чутка поработал над безопасностью исполняемого пользовательского кода в Twir.
В Twir есть фича, называется scripts variable, позволяющая пользователям писать код на javascript, для расширения функционала. К примеру сходить на какое-то стороннее апи, распарсить ответ старндартными средствами js.
Конечно, это порождает дыры в безопасности, хоть это и вынесено в отдельный сервис, который занимается выполонением, но всё же, можно:
- забить эти сервисы оперативкой
- сильно забить CPU, сделав какой-то
- сбежать из сандбокса
- повесить сервис каким-то долго выплняющимся скриптом
Половину из этих проблем я пытался решить с помощью
Что я решил делать с этим?
А давайте я буду запускать контейнер при каждом запросе на выполнение скрипта!
Было решено написать небольшое апи на Go, которое будет заниматься оркестрацией контейнеров (почти).
На каждый запрос на выполнение скрипта, я спавню контейнер через docker api, задавая ему лимиты по cpu, ram, времени жизни. Ограничиваю контейнеру системые capabilities, доступ к вайловой системе, а именно делаю её read-only. Пользовательский скрипт я чучуть оборачиваю:
Так я добавляю в контекст выполнения
Скрипт выполняется, и через докеровское апи я читаю результат выполнения из консоли.
Почему именно так? Сделано так, чтобы упростить написание скрипта для пользователя, условно чтобы он в скрипте мог сделать
Вчера ещё бился с проблемой, что пользователь можно легко узнать IP сервера, где это всё выполняется каким нибудь запросом на сайт, например https://ifconfig.me/ip. Плясал вокруг cloudflare, думал пойти вообще в сторону workers, а не докера, но в итоге получилось довольно интересно.
Оказывается, докер контейнеру можно задать
На всякий случай ещё сделал, чтобы сервис не мог запустить более чем N контейнеров одновременно, через некую очередь ожидания на исполнение через атомики:
Всё просто, и вроде как (я надеюсь) безопасно. Я ещё пробовал дополнительный слой безопасности в виде https://gvisor.dev, но к сожалению это добавляет неплохую такую задержку при исполнении.
Буду рад любому фидбеку.
https://github.com/twirapp/ExecuTron
В Twir есть фича, называется scripts variable, позволяющая пользователям писать код на javascript, для расширения функционала. К примеру сходить на какое-то стороннее апи, распарсить ответ старндартными средствами js.
Конечно, это порождает дыры в безопасности, хоть это и вынесено в отдельный сервис, который занимается выполонением, но всё же, можно:
- забить эти сервисы оперативкой
- сильно забить CPU, сделав какой-то
while (true) {}- сбежать из сандбокса
node:vm, и получить доступ к вайловой системе контейнера, с целью абуза, или с целью последующего взлома, попыток сбежать из докера- повесить сервис каким-то долго выплняющимся скриптом
Половину из этих проблем я пытался решить с помощью
vm2 пакета. В нём есть таймауты, вроде ограничения по RAM. Но работало там это через раз, например while (true) {} не таймаутился.Что я решил делать с этим?
А давайте я буду запускать контейнер при каждом запросе на выполнение скрипта!
Было решено написать небольшое апи на Go, которое будет заниматься оркестрацией контейнеров (почти).
На каждый запрос на выполнение скрипта, я спавню контейнер через docker api, задавая ему лимиты по cpu, ram, времени жизни. Ограничиваю контейнеру системые capabilities, доступ к вайловой системе, а именно делаю её read-only. Пользовательский скрипт я чучуть оборачиваю:
wrapperContent := `
import { readFileSync } from 'fs';
import vm from 'node:vm'
import _ from 'lodash';
const consoleRegex = /console\.(log|debug|info|warn|error|table|trace|group|groupEnd|time|timeEnd)\s*\([^;]*\);?/g;
try {
const code = readFileSync('/code/user_code.mjs', 'utf8').replace(consoleRegex, '');
const result = await eval('(async () => { ' + code + ' })()');
console.log(JSON.stringify({ result: result.toString() }));
} catch (e) {
console.log(JSON.stringify({ error: e.message }));
}
Так я добавляю в контекст выполнения
lodash, для более удобной работы с некоторыми вещами для пользователей.Скрипт выполняется, и через докеровское апи я читаю результат выполнения из консоли.
Почему именно так? Сделано так, чтобы упростить написание скрипта для пользователя, условно чтобы он в скрипте мог сделать
return 1, и без каких-либо дополнительных вещей.Вчера ещё бился с проблемой, что пользователь можно легко узнать IP сервера, где это всё выполняется каким нибудь запросом на сайт, например https://ifconfig.me/ip. Плясал вокруг cloudflare, думал пойти вообще в сторону workers, а не докера, но в итоге получилось довольно интересно.
Оказывается, докер контейнеру можно задать
network_mode другого контейнера. Что это нам даёт? Мы можем поднять рядом vpn, в лице которого я использую wrap, и пустить весь трафик контейнера через него: network_mode: "service:cloudflare-warp".networkMode := container.NetworkMode(network.DefaultNetwork)
if os.Getenv("APP_ENV") == "production" {
networkMode = container.NetworkMode("container:executron-warp")
}
pidsLimit := int64(100)
hostConfig := &container.HostConfig{
Mounts: containerCtx.mounts,
Resources: container.Resources{
Memory: 128 * 1024 * 1024, // 128 MB
NanoCPUs: 1000000000, // 1 CPU
PidsLimit: &pidsLimit, // Limit to 100 PIDs
},
NetworkMode: networkMode,
ReadonlyRootfs: true,
AutoRemove: true,
SecurityOpt: []string{"no-new-privileges"},
CapDrop: []string{"ALL"}, // Drop all capabilities
//Runtime: "runsc",
}
На всякий случай ещё сделал, чтобы сервис не мог запустить более чем N контейнеров одновременно, через некую очередь ожидания на исполнение через атомики:
for c.runedContainers.Load() >= c.maxRunedContainers {
time.Sleep(100 * time.Millisecond)
}
c.runedContainers.Add(1)
defer c.runedContainers.Add(-1)Всё просто, и вроде как (я надеюсь) безопасно. Я ещё пробовал дополнительный слой безопасности в виде https://gvisor.dev, но к сожалению это добавляет неплохую такую задержку при исполнении.
Буду рад любому фидбеку.
https://github.com/twirapp/ExecuTron
❤14🏆6🔥4
Здравствуйте, днб слушатели.
Вот вам микс на послушать под рабочий процесс: https://youtu.be/4XpCKnLJbU8
Вот вам микс на послушать под рабочий процесс: https://youtu.be/4XpCKnLJbU8
YouTube
Magnetude - Beats For Love 2024 | Drum and Bass
🔥 Don't forget to give a thumbs up and support Magnetude 👍
📍 Venue & Date: Ostrava CZ / 3.-6.7.2024
🔊 You can download the audio after joining our channel: https://bit.ly/DnBPortalFamily
✖ Magnetude ✖
https://linktr.ee/magnetude
✖ Beats for Love ✖
htt…
📍 Venue & Date: Ostrava CZ / 3.-6.7.2024
🔊 You can download the audio after joining our channel: https://bit.ly/DnBPortalFamily
✖ Magnetude ✖
https://linktr.ee/magnetude
✖ Beats for Love ✖
htt…
❤6
Satont.
Здравствуйте, днб слушатели. Вот вам микс на послушать под рабочий процесс: https://youtu.be/4XpCKnLJbU8
Так же напоминаю, что я веду ютуб плей-лист c днб, который регулярно пополняю. Там нет чёткой структуризации, потому можно наткнутся как на чиловые сэты, так и на нейрофанк.
Ссылка: https://www.youtube.com/watch?v=yUa_hwhGlmg&list=PL3qfVPfMnrn6y30FoOe_Whw_eJZRo9EE6
Ссылка: https://www.youtube.com/watch?v=yUa_hwhGlmg&list=PL3qfVPfMnrn6y30FoOe_Whw_eJZRo9EE6
❤5🆒2🤯1
Satont. via @odesli_bot
Concord Dawn - Morning Light
Deezer | SoundCloud | Yandex Music | Spotify | YouTube Music | YouTube | Apple Music | Tidal
Deezer | SoundCloud | Yandex Music | Spotify | YouTube Music | YouTube | Apple Music | Tidal
Deezer
Morning Light
Concord Dawn
❤2
Ребят, кто с России — проверьте пожалуйста без впн открывается ли у вас https://twir.app
👍 - да
👎 - нет
👍 - да
👎 - нет
👍27👎1
Оказывается у меня Twir всё же имеет какой-то кастомный статус на твиче.
На него нельзя warning накинуть, и он может писать в followers-only чат.
Хммм, получается всё таки какие-то скрытые фильтры у них есть, которые бог есть как работают.
Может и банов больше не будет акка бота?
На него нельзя warning накинуть, и он может писать в followers-only чат.
Хммм, получается всё таки какие-то скрытые фильтры у них есть, которые бог есть как работают.
Может и банов больше не будет акка бота?
🙏3
Так как вы донатите чутка больше, чем надо на сервера — включил
Посмотрим сколько за месяц накапает в биллинг.
acrcloud для определения музыки в твире, чтобы лучше детектил музыку со стрима без подключения сторонних интеграций по типу vk, last.fm, spotify.Посмотрим сколько за месяц накапает в биллинг.
❤4
Satont. via @odesli_bot
C.A.2K - Factory
Deezer | SoundCloud | Yandex Music | Spotify | YouTube Music | YouTube | Apple Music | Tidal
Deezer | SoundCloud | Yandex Music | Spotify | YouTube Music | YouTube | Apple Music | Tidal
Deezer
Factory
C.A.2K
❤🔥2
https://youtu.be/DHA_HuGA-Mc
Какой шедевр, я не могу.
Легендарная crowd (я не знаю как на русском так же ёмко сказать).
Какой шедевр, я не могу.
Легендарная crowd (я не знаю как на русском так же ёмко сказать).
YouTube
BABYMETAL - BABYMETAL DEATH【Live Blu-ray/DVD「BABYMETAL BEGINS - THE OTHER ONE -」“CLEAR NIGHT”】
▼1st Album 「BABYMETAL」各音楽配信サイトはこちら
https://TF.lnk.to/babymetal_10thanniversary
2014年2月26日にリリースされたBABYMETALの1st Album「BABYMETAL」が、
2024年2月26日に発売から10周年を迎えるのを記念し、2023年4月1日と2日に
ぴあアリーナMMで開催された「BABYMETAL BEGINS - THE OTHER ONE -」
(2023年10月11日発売 LIVE DVD/ Blu…
https://TF.lnk.to/babymetal_10thanniversary
2014年2月26日にリリースされたBABYMETALの1st Album「BABYMETAL」が、
2024年2月26日に発売から10周年を迎えるのを記念し、2023年4月1日と2日に
ぴあアリーナMMで開催された「BABYMETAL BEGINS - THE OTHER ONE -」
(2023年10月11日発売 LIVE DVD/ Blu…
❤🔥3
Хайлоад. 😄
Это я попросил человека нафлудить 60к сообщений в чате твича, и у меня 1.7кк запросов к редису на это тригерится, и 60к+ к постгресу.
Нагрузка серверов сильно возврастает в этот момент, но при этом сервера справляются, бот в этот момент продолжает отвечать на сообщения в чате.
Оч доволен тем, как побустил перформанс. Это всё происходит на
Это я попросил человека нафлудить 60к сообщений в чате твича, и у меня 1.7кк запросов к редису на это тригерится, и 60к+ к постгресу.
Нагрузка серверов сильно возврастает в этот момент, но при этом сервера справляются, бот в этот момент продолжает отвечать на сообщения в чате.
Оч доволен тем, как побустил перформанс. Это всё происходит на
shared vcpu виртуалках от хетзнера с 4мя ядрами. Думаю с dedicated или просто большим кол-вом ядер — было бы ещё больше по запасу ресурсов.🔥6⚡2
Satont.
Хайлоад. 😄 Это я попросил человека нафлудить 60к сообщений в чате твича, и у меня 1.7кк запросов к редису на это тригерится, и 60к+ к постгресу. Нагрузка серверов сильно возврастает в этот момент, но при этом сервера справляются, бот в этот момент продолжает…
А теперь чутка детальнее.
У меня в боте используется куча систем — сборная солянка из разных ботов.
Из-за этого на каждое событие (фоллоу, сообщение и т.п.) происходит на порядок больше действий и, как следствие, — запросов к базе.
🤯 Проблема
Есть такие ребята, которые просто флудят смайликами, сообщениями, наградами — чтобы накручивать активность в сторонних сервисах (типа StreamElements).
Один из таких товарищей недавно отправил ~3 млн запросов. В итоге:
-
-
- система трижды падала
🛠 Что сделал для улучшения:
- Свап
Почему Haproxy?
1. без GC
2. без компрессии
3. стабилен под нагрузкой (написан на C)
- Добавил batch-сохранения в базу
1. Раньше: один
2. Теперь: всё уходит в очередь и раз в X мс заливается в базу одной пачкой через COPY.
Своя либка под это:
👉 https://github.com/twirapp/batch-processor
- Кэширование READ-запросов через Redis
Написал обёртку GenericCacher, которая кэширует по ключу, TTL и умеет делать invalidate. Если в кэше данных нет — вызывается
🧱 Пример использования:
Создания:
✅ Результат:
Теперь даже при диком флуде — система не ложится.
Нагрузка снижена, всё живёт.
Да, редис стал принимать на себя на порядок больше, но за-то теперь нагрузки более правильные что-ли, бот даже не теряет во времени ответа на команды в моменте оверлоада системы.
И в целом мы теперь лучше готовы к подключению бота на крупных каналах, где чат летит с такой скоростью, что даже сервер сообщений твича пролагивает из-за этого.
У меня в боте используется куча систем — сборная солянка из разных ботов.
Из-за этого на каждое событие (фоллоу, сообщение и т.п.) происходит на порядок больше действий и, как следствие, — запросов к базе.
🤯 Проблема
Есть такие ребята, которые просто флудят смайликами, сообщениями, наградами — чтобы накручивать активность в сторонних сервисах (типа StreamElements).
Один из таких товарищей недавно отправил ~3 млн запросов. В итоге:
-
traefik лёг-
postgres задохнулся- система трижды падала
🛠 Что сделал для улучшения:
- Свап
traefik → haproxy в критичных местах (EventSub webhooks)Почему Haproxy?
1. без GC
2. без компрессии
3. стабилен под нагрузкой (написан на C)
- Добавил batch-сохранения в базу
1. Раньше: один
INSERT на каждое сообщение.2. Теперь: всё уходит в очередь и раз в X мс заливается в базу одной пачкой через COPY.
Своя либка под это:
👉 https://github.com/twirapp/batch-processor
- Кэширование READ-запросов через Redis
Написал обёртку GenericCacher, которая кэширует по ключу, TTL и умеет делать invalidate. Если в кэше данных нет — вызывается
LoadFn, и данные записываются в кэш.🧱 Пример использования:
c.channelsCache.Get(ctx, channelId)
c.channelsCache.Invalidate(ctx, channelId)
Создания:
go
c.channelsCache = generic_cacher.New[channelmodel.Channel](
generic_cacher.Opts[channelmodel.Channel]{
Redis: redis,
KeyPrefix: "cache:twir:channel:",
LoadFn: repo.GetByID,
Ttl: 24 * time.Hour,
},
)
✅ Результат:
Теперь даже при диком флуде — система не ложится.
Нагрузка снижена, всё живёт.
Да, редис стал принимать на себя на порядок больше, но за-то теперь нагрузки более правильные что-ли, бот даже не теряет во времени ответа на команды в моменте оверлоада системы.
И в целом мы теперь лучше готовы к подключению бота на крупных каналах, где чат летит с такой скоростью, что даже сервер сообщений твича пролагивает из-за этого.
❤🔥14👍3🆒2⚡1
