Go · 61 строк
Один инстанс держит около 40 тысяч открытых вкладок. Консьюмер очереди вызывает OnPresence на каждое событие, в час пик это 6 тысяч событий в секунду. serve крутится в отдельной горутине на каждую вкладку и пишет статусы в веб-сокет.
Вкладку отключают два места: ошибка записи в сокет и таймер простоя в 10 минут. Отметьте строки с ошибками.
В работе: Сервис присутствия, который показывает зелёную точку у собеседника.
Как проверяем
Нажмите на строку с ошибкой и коротко напишите, что не так. Баг засчитан, если отмечена хотя бы одна его строка. Зачёт — найдено не меньше 60 % багов с учётом серьёзности (критичный весит 3, обычный 2, мелкий 1), а лишних отметок не больше, чем багов в коде. Пустые строки, скобки и комментарии лишними не считаем. Плюс 2 вопроса про поведение программы — на зачёт не влияют. Ответ один на подход: после него показываем разбор.
Источник: наша задача на данных VK: статусы «в сети» в мессенджере. Условие пересказано своими словами.
Давали на собеседовании?
package presenceimport ("sync""time")type Status struct {UserID int64Online bool}type Conn interface{ WriteJSON(v any) error }type Hub struct {mu sync.Mutexsubs map[int64]chan Status}func (h *Hub) Subscribe(connID int64) <-chan Status {ch := make(chan Status)h.mu.Lock()h.subs[connID] = chh.mu.Unlock()return ch}// Unsubscribe зовут ошибка записи и таймер простоя.func (h *Hub) Unsubscribe(connID int64) {h.mu.Lock()ch := h.subs[connID]delete(h.subs, connID)h.mu.Unlock()close(ch)}func (h *Hub) Publish(s Status) {h.mu.Lock()defer h.mu.Unlock()for _, ch := range h.subs {ch <- s}}// OnPresence вызывает консьюмер очереди на каждое событие.func (h *Hub) OnPresence(s Status) {go h.Publish(s)}func (h *Hub) serve(connID int64, ws Conn) {updates := h.Subscribe(connID)idle := time.AfterFunc(10*time.Minute, func() { h.Unsubscribe(connID) })defer idle.Stop()for s := range updates {idle.Reset(10 * time.Minute)if err := ws.WriteJSON(s); err != nil {h.Unsubscribe(connID)return}}}